springboot 自定义消息处理

css 复制代码
package com.my.config;

import cn.hutool.core.io.FileUtil;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.google.gson.Gson;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonInputMessage;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.util.TypeUtils;

import java.io.*;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 自定义消息处理
 */
public class CryptMessageConvertPro extends MappingJackson2HttpMessageConverter {

    private List<MediaType> supportedMediaTypesNew = new ArrayList<>();

    private final static String APPLICATION_CRYPT = "application/crypt;charset=UTF-8";

    private static final Map<String, JsonEncoding> ENCODINGS = new HashMap(JsonEncoding.values().length + 1);

    private static  CryptMessage cryptMessage;

    static {
        JsonEncoding[] var0 = JsonEncoding.values();
        int var1 = var0.length;

        for(int var2 = 0; var2 < var1; ++var2) {
            JsonEncoding encoding = var0[var2];
            ENCODINGS.put(encoding.getJavaName(), encoding);
        }

        ENCODINGS.put("US-ASCII", JsonEncoding.UTF8);

        /**
         * 消息处理工具类,即对数据加解密操作
         */
        cryptMessage = new MessageCryptUtils.Base64Message();//base64加解密
//        cryptMessage = new MessageCryptUtils.AESMessage("1qazxsw23edcvfr4");//aes加解密
//        cryptMessage = new MessageCryptUtils.RSAMessage(FileUtil.readUtf8String("F:\\primary.pem"),FileUtil.readUtf8String("F:\\public.pem"));//rsa加解密
    }



    /**
     * 此处加入自定义的 MediaType
     * @return
     */
    @Override
    public List<MediaType> getSupportedMediaTypes() {
        if (supportedMediaTypesNew.isEmpty()) {
            supportedMediaTypesNew.addAll(super.getSupportedMediaTypes());
            supportedMediaTypesNew.add(new MediaType("application","crypt", StandardCharsets.UTF_8));
        }
        return Collections.unmodifiableList(this.supportedMediaTypesNew);
    }


    @Override
    protected void writeInternal(Object o, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

        MediaType contentType = outputMessage.getHeaders().getContentType();
        JsonEncoding encoding = this.getJsonEncoding(contentType);
        OutputStream body = outputMessage.getBody();

        Object object  = o;

        /** ========此处做加密处理========== **/
        if (APPLICATION_CRYPT.startsWith(Objects.requireNonNull(outputMessage.getHeaders().getContentType()).toString())) {
            try {
                String jsonString = this.objectMapper.writeValueAsString(object);
                object = cryptMessage.encodeCrypt(jsonString);
            } catch (Exception e) {
                throw new RuntimeException("响应结果加密异常");
            }
        }
        /** =======此处做加密处理========== **/

        JsonGenerator generator = this.objectMapper.getFactory().createGenerator(body, encoding);

        try {
            this.writePrefix(generator, object);
            Object value = object;
            Class<?> serializationView = null;
            FilterProvider filters = null;
            JavaType javaType = null;
            if (object instanceof MappingJacksonValue) {
                MappingJacksonValue container = (MappingJacksonValue)object;
                value = container.getValue();
                serializationView = container.getSerializationView();
                filters = container.getFilters();
            }

            if (type != null && TypeUtils.isAssignable(type, value.getClass())) {
                javaType = this.getJavaType(type, (Class)null);
            }

            ObjectWriter objectWriter = serializationView != null ? this.objectMapper.writerWithView(serializationView) : this.objectMapper.writer();
            if (filters != null) {
                objectWriter = objectWriter.with(filters);
            }

            if (javaType != null && javaType.isContainerType()) {
                objectWriter = objectWriter.forType(javaType);
            }

            SerializationConfig config = objectWriter.getConfig();
            if (contentType != null && contentType.isCompatibleWith(MediaType.TEXT_EVENT_STREAM) && config.isEnabled(SerializationFeature.INDENT_OUTPUT)) {
                objectWriter = objectWriter.with(new DefaultPrettyPrinter());
            }

            objectWriter.writeValue(generator, value);
            this.writeSuffix(generator, object);
            generator.flush();
        } catch (InvalidDefinitionException var13) {
            InvalidDefinitionException ex = var13;
            throw new HttpMessageConversionException("Type definition error: " + ex.getType(), ex);
        } catch (JsonProcessingException var14) {
            JsonProcessingException ex = var14;
            throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getOriginalMessage(), ex);
        }
    }


    @Override
    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        JavaType javaType = this.getJavaType(clazz, (Class)null);
        return this.readJavaType(javaType, inputMessage);
    }

    @Override
    public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        JavaType javaType = this.getJavaType(type, contextClass);
        return this.readJavaType(javaType, inputMessage);
    }

    private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) throws IOException {
        MediaType contentType = inputMessage.getHeaders().getContentType();
        Charset charset = contentType != null && contentType.getCharset() != null ? contentType.getCharset() : StandardCharsets.UTF_8;
        boolean isUnicode = ENCODINGS.containsKey(charset.name());

        try {
            InputStream body = inputMessage.getBody();

            /**=======此处做解密处理==========**/
            if (contentType != null && contentType.toString().equals(APPLICATION_CRYPT)) {//解密加密数据
                try {
                    byte[] bytes = new byte[body.available()];
                    body.read(bytes);
                    String res = cryptMessage.decodeCrypt(bytes);
                    Object result = this.objectMapper.readValue(res.getBytes(StandardCharsets.UTF_8), javaType);
                    return result;
                } catch (Exception e) {
                    throw new RuntimeException("参数解密失败");
                }
            }
            /**==========此处做解密处理=======**/

            if (inputMessage instanceof MappingJacksonInputMessage) {
                Class<?> deserializationView = ((MappingJacksonInputMessage)inputMessage).getDeserializationView();
                if (deserializationView != null) {
                    ObjectReader objectReader = this.objectMapper.readerWithView(deserializationView).forType(javaType);
                    if (isUnicode) {
                        return objectReader.readValue(body);
                    }

                    Reader reader = new InputStreamReader(body, charset);
                    return objectReader.readValue(reader);
                }
            }

            if (isUnicode) {
                return this.objectMapper.readValue(body, javaType);
            } else {
                Reader reader = new InputStreamReader(body, charset);
                return this.objectMapper.readValue(reader, javaType);
            }
        } catch (InvalidDefinitionException var9) {
            InvalidDefinitionException ex = var9;
            throw new HttpMessageConversionException("Type definition error: " + ex.getType(), ex);
        } catch (JsonProcessingException var10) {
            JsonProcessingException ex = var10;
            throw new HttpMessageNotReadableException("JSON parse error: " + ex.getOriginalMessage(), ex, inputMessage);
        }
    }



}

spring的配置

css 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class WebConfig implements WebMvcConfigurer {

 @Override
 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
     // 设置优先级为 0,优先使用
     converters.set(1, new CryptMessageConvertPro());
 }
}

加密工具

css 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class WebConfig implements WebMvcConfigurer {

 @Override
 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
     // 设置优先级为 0,优先使用
     converters.set(1, new CryptMessageConvertPro());
 }
}

用法

css 复制代码
    @RequestMapping(method = RequestMethod.POST,value = "/test2",produces = "application/crypt")
    @ResponseBody
    public CryptResult test2(@RequestBody Map<String,Object> param, HttpServletRequest request) throws InterruptedException {
        String string = UUID.randomUUID().toString();
        param.put("uuid", string);
        System.out.println(string);

        return CryptResult.success(param);
    }
相关推荐
我真的是大笨蛋1 小时前
MySQL临时表深度解析
java·数据库·sql·mysql·缓存·性能优化
九皇叔叔1 小时前
【02】微服务系列 之 初始化工程
java·数据库·微服务
季明洵1 小时前
两数之和、四数相加II、三数之和、四数之和
java·数据结构·算法·leetcode·蓝桥杯·哈希算法
人道领域1 小时前
javaWeb从入门到进阶(SpringBoot基础案例3)
java·spring boot·后端
西门吹-禅2 小时前
.gradle迁移d盘
java
士别三日&&当刮目相看2 小时前
Spring两大核心思想:IoC和AOP
java·spring
轩情吖2 小时前
数据结构-并查集
开发语言·数据结构·c++·后端··并查集
你想考研啊2 小时前
win11配置maven
java·数据库·maven
独自破碎E2 小时前
LCR001-两数相除
java·开发语言