SpringBoot2.0如何集成fastjson?在网上查了一堆资料,但是各文章的说法不一,有些还是错的,可能只是简单测试一下就认为ok了,最后有没生效都不知道。恰逢公司项目需要将JackSon换成fastjson,因此自己来实践一下SpringBoot2.0和fastjson的整合,同时记录下来方便自己后续查阅。
一、Maven依赖说明
SpringBoot的版本为: <version>2.1.4.RELEASE</version>
在pom文件中添加fastjson的依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60/version>
</dependency>
二、整合
整合之前,我们先说下springboot1.0的方法,轻车熟路的去自定了一个SpringMvcConfigure
去继承WebMvcConfigurerAdapter
,然后你就发现这个WebMvcConfigurerAdapter
竟然过时了?what?点进去看源码:
1 /**
2 * An implementation of {@link WebMvcConfigurer} with empty methods allowing
3 * subclasses to override only the methods they're interested in.
4 *
5 * @author Rossen Stoyanchev
6 * @since 3.1
7 * @deprecated as of 5.0 {@link WebMvcConfigurer} has default methods (made
8 * possible by a Java 8 baseline) and can be implemented directly without the
9 * need for this adapter
10 */
11 @Deprecated
12 public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {}
可以看到从spring5.0开始就被@Deprecated,原来是java8中支持接口中有默认方法,所以我们现在可以直接实现WebMvcConfigurer
,然后选择性的去重写某个方法,而不用实现它的所有方法.
于是就实现了WebMvcConfigurer
:
1 @Configuration
2 public class SpringMvcConfigure implements WebMvcConfigurer {
3
4 /**
5 * 配置消息转换器
6 * @param converters
7 */
8 @Override
9 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
10 FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
11 //自定义配置...
12 FastJsonConfig config = new FastJsonConfig();
13 config.setSerializerFeatures(SerializerFeature.QuoteFieldNames,
14 SerializerFeature.WriteEnumUsingToString,
15 /*SerializerFeature.WriteMapNullValue,*/
16 SerializerFeature.WriteDateUseDateFormat,
17 SerializerFeature.DisableCircularReferenceDetect);
18 fastJsonHttpMessageConverter.setFastJsonConfig(config);
19 converters.add(fastJsonHttpMessageConverter);
20 }
21
22 }
本以为这样子配置就可以完事儿,但是诡异的事情发生了,我明明注释了SerializerFeature.WriteMapNullValue
,可是返回的json中仍然有为null
的字段,然后我就去com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter
中的write
和writeInternal
打了断点,再次执行,竟然什么都没有发生,根本没有走这两个方法,于是在自定义的SpringMvcConfigure
中configureMessageConverters
方法内打了断点,想看看这个方法参数converters
里边到底有什么:
看到这里就想到,肯定是我自己添加的fastjson在后边,所以没有生效,所以就加了以下代码:
1 @Override
2 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
3 converters = converters.stream()
4 .filter((converter)-> !(converter instanceof MappingJackson2HttpMessageConverter))
5 .collect(Collectors.toList());
6 FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
7 //自定义配置...
8 FastJsonConfig config = new FastJsonConfig();
9 config.setSerializerFeatures(SerializerFeature.QuoteFieldNames,
10 SerializerFeature.WriteEnumUsingToString,
11 /*SerializerFeature.WriteMapNullValue,*/
12 SerializerFeature.WriteDateUseDateFormat,
13 SerializerFeature.DisableCircularReferenceDetect);
14 fastJsonHttpMessageConverter.setFastJsonConfig(config);
15 converters.add(fastJsonHttpMessageConverter);
16 }
这还是不生效的,继续追踪,得出如下结论:
(1)源码分析可知,返回json的过程为:
Controller调用结束后返回一个数据对象,for循环遍历conventers,找到支持application/json的HttpMessageConverter,然后将返回的数据序列化成json。
具体参考org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor的writeWithMessageConverters方法
(2)由于是list结构,我们添加的fastjson在最后。因此必须要将jackson的转换器删除,不然会先匹配上jackson,导致没使用fastjson
最终得出代码如下:
1 @Configuration
2 public class SpringWebMvcConfigurer implements WebMvcConfigurer {
3
4 private final Logger logger = LoggerFactory.getLogger(SpringWebMvcConfigurer.class);
5
6 //使用阿里 FastJson 作为JSON MessageConverter
7 @Override
8 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
9
10 /*
11 先把JackSon的消息转换器删除.
12 备注: (1)源码分析可知,返回json的过程为:
13 Controller调用结束后返回一个数据对象,for循环遍历conventers,找到支持application/json的HttpMessageConverter,然后将返回的数据序列化成json。
14 具体参考org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor的writeWithMessageConverters方法
15 (2)由于是list结构,我们添加的fastjson在最后。因此必须要将jackson的转换器删除,不然会先匹配上jackson,导致没使用fastjson
16 */
17 for (int i = converters.size() - 1; i >= 0; i--) {
18 if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
19 converters.remove(i);
20 }
21 }
22
23 FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
24 FastJsonConfig config = new FastJsonConfig();
25 config.setSerializerFeatures(
26 SerializerFeature.WriteMapNullValue,//保留空的字段
27 SerializerFeature.WriteNullStringAsEmpty,//String null -> ""
28 SerializerFeature.WriteNullNumberAsZero,//Number null -> 0
29 SerializerFeature.WriteDateUseDateFormat);//日期格式化
30
31 converter.setFastJsonConfig(config);
32 converter.setDefaultCharset(Charset.forName("UTF-8"));
33 converters.add(converter);
34 }
35 }
总结
- 最重要的还是解决了springboot2.0.2配置fastjson不生效的问题
- 更加明白stream api返回的都是全新的对象
- 更理解java是值传递而不是引用传递
- 了解到想要在迭代过程中对集合进行操作要用Iterator,而不是直接简单的for循环或者增强for循环