springboot2.x使用FastJson为Http消息转换
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