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);
    }
相关推荐
IT_陈寒3 分钟前
JavaScript的异步地狱,我差点没爬出来
前端·人工智能·后端
NEGl DRYN4 分钟前
Go基础之环境搭建
开发语言·后端·golang
AI木马人5 分钟前
20.人工智能实战:大模型项目如何从 Demo 走向生产?一套可落地的上线验收清单与工程治理方案
java·开发语言·人工智能
CandyU27 分钟前
Unity —— 反射
java·开发语言
楼田莉子9 分钟前
仿照Muduo的高并发服务器:EventLoop模块及与TimeWheel模块联调
java·开发语言
小雅痞11 分钟前
[Java][Leetcode middle] 3. 无重复字符的最长子串
java·开发语言·leetcode
SamDeepThinking12 分钟前
为什么你做技术方案总是漏掉边界情况
java·后端·程序员
逻辑驱动的ken22 分钟前
Java高频面试考点场景题21
java·开发语言·面试·职场和发展·求职招聘
你好潘先生23 分钟前
Next.js + Spring Boot 实现 AI 多模型并行对话系统(架构设计与关键实现)
spring boot·向量检索·next.js·pgvector·ai对话·多模型对比·sse流式输出
苍煜24 分钟前
SpringBoot单体应用到分布式下的数据库锁、事务、Redis事务、分布式锁、分布式事务协调
数据库·spring boot·分布式