springboot升级2.0 fastjson报错? 2.0以上应该怎么整合fastjson?
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循环