美文网首页spring
springboot2.x使用FastJson为Http消息转换

springboot2.x使用FastJson为Http消息转换

作者: 念䋛 | 来源:发表于2021-10-08 14:04 被阅读0次

    Springmvc前后台数据交互的时候,很多情况下使用的JSON来传输数据,前提使用了@RequestBody @ResponseBody接收和发送数据
    如果我们想要自定义消息转换器的话该如何实现呢,实现自定义JSON转换器是需要注意很多地方的,这里SpringBoot 2.4.5版本
    首先我们先看一下默认的转换器,使用源码的方式查看

    DispatcherServlet#doDispatch的
    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    -->AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters


    image.png

    默认的情况下有10个转换器,MappingJackson2HttpMessageConverter作为JSON转换器,现在我们要添加FastJsonHttpMessageConverter作为JSON转换器,那如何把FastJsonHttpMessageConverter添加到this.messageConverters呢,下面继续分析
    首先分析this.messageConverters是如何被赋值的,MVC在springboot的配置在2.x版本有两个类可以使用WebMvcConfigurer和WebMvcConfigurationSupport使用,这里要说明的是强烈不建议使用WebMvcConfigurationSupport,原因是WebMvcAutoConfiguration类是springboot很重要的配置类,会初始化很多Bean,类的注解
    @ConditionalOnMissingBean(WebMvcConfigurationSupport.class),所以如果继承WebMvcConfigurationSupport类并放到容器中,会导致WebMvcAutoConfiguration不能初始化,所以是不建议的.


    image.png
    实现WebMvcConfigurer接口
    代码如下
    @Configuration
    //order的作用后续解释
    @Order(-1)
    public class MvcConfiguration implements WebMvcConfigurer {
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            //1.先定义一个convert转换消息的对象
            FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter ();
            //2.添加fastjson的配置信息
            FastJsonConfig fastJsonConfig = new FastJsonConfig ();
            //2、添加fastjson的配置信息
            SerializerFeature[] serializerFeatures = new SerializerFeature[]{
                    //    输出key是包含双引号
                    //SerializerFeature.QuoteFieldNames,
                    //    是否输出为null的字段,若为null 则显示该字段
                    //SerializerFeature.WriteMapNullValue,
                    //    数值字段如果为null,则输出为0
                    SerializerFeature.WriteNullNumberAsZero,
                    //     List字段如果为null,输出为[],而非null
                    SerializerFeature.WriteNullListAsEmpty,
                    //    字符类型字段如果为null,输出为"",而非null
                    SerializerFeature.WriteNullStringAsEmpty,
                    //    Boolean字段如果为null,输出为false,而非null
                    SerializerFeature.WriteNullBooleanAsFalse,
                    //    Date的日期转换器
                    SerializerFeature.WriteDateUseDateFormat,
                    //    循环引用
                    SerializerFeature.DisableCircularReferenceDetect,
            };
            fastJsonConfig.setSerializerFeatures (serializerFeatures);
            //输入和输出的编码及
            fastJsonConfig.setCharset (Charset.forName ("UTF-8"));
            //针对前台Content-Type类型为APPLICATION_JSON进行解析
            List<MediaType> fastMediaTypes = new ArrayList<MediaType> ();
            fastMediaTypes.add (MediaType.APPLICATION_JSON);
            fastConverter.setSupportedMediaTypes (fastMediaTypes);
            //3.在convert中添加配置信息
            fastConverter.setFastJsonConfig (fastJsonConfig);
            //4.将convert添加到converters当中
            converters.add (fastConverter);
        }
    }
    
    

    1.首先收容器中获取配置类


    image.png

    2.初始化RequestMappingHandlerAdapter


    image.png
    查看getMessageConverters方法最终调用的是DelegatingWebMvcConfiguration类
    @Override

    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    this.configurers.configureMessageConverters(converters);
    }
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    this.configurers.extendMessageConverters(converters);
    }
    添加我们自定义HttpMessageConverter,也添加了默认
    到此就说明了this.messageConverters是如何添加HttpMessageConverter

    上面提到过@Order(-1)的作用,就是为了保证我们自定义HttpMessageConverter放在默认HttpMessageConverter的前面,因为使用HttpMessageConverter的时候,如果有一个适配了,就不会执行后续的HttpMessageConverter,所以要保证我们自定义HttpMessageConverter放在最前面


    image.png
    image.png

    下面分析一下HttpMessageConverter和如何工作的
    在最开始的图片中,就是关于消息的转换
    AbstractMessageConverterMethodArgumentResolver#readWithMessageConverters
    下面就是关于消息转换的源码

    //遍历所有的this.messageConverters
         for (HttpMessageConverter<?> converter : this.messageConverters) {
             Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
             GenericHttpMessageConverter<?> genericConverter =
                     (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null);
             //判断是否支持消息转换,fastMediaTypes.add (MediaType.APPLICATION_JSON);判断Content-Type是否为APPLICATION_JSON
             if (genericConverter != null ? genericConverter.canRead(targetType, contextClass, contentType) :
                     (targetClass != null && converter.canRead(targetClass, contentType))) {
                 if (message.hasBody()) {
                     //消息转换
                     HttpInputMessage msgToUse =
                             getAdvice().beforeBodyRead(message, parameter, targetType, converterType);
                     body = (genericConverter != null ? genericConverter.read(targetType, contextClass, msgToUse) :
                             ((HttpMessageConverter<T>) converter).read(targetClass, msgToUse));
                     body = getAdvice().afterBodyRead(body, msgToUse, parameter, targetType, converterType);
                 }
                 else {
                     body = getAdvice().handleEmptyBody(null, message, parameter, targetType, converterType);
                 }
                 //消息转换之后,后续的HttpMessageConverter不会执行,这也就是为什么要将我们的自定义的HttpMessageConverter放到最前面
                 break;
             }
         }
    
    

    关于FastJsonHttpMessageConverter,可看看看大神的文章
    https://blog.csdn.net/u010246789/article/details/52539576

    相关文章

      网友评论

        本文标题:springboot2.x使用FastJson为Http消息转换

        本文链接:https://www.haomeiwen.com/subject/isrxoltx.html