spring

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

2021-10-08  本文已影响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

上一篇下一篇

猜你喜欢

热点阅读