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中的writewriteInternal打了断点,再次执行,竟然什么都没有发生,根本没有走这两个方法,于是在自定义的SpringMvcConfigureconfigureMessageConverters方法内打了断点,想看看这个方法参数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 }

 

 

  总结

  1. 最重要的还是解决了springboot2.0.2配置fastjson不生效的问题
  2. 更加明白stream api返回的都是全新的对象
  3. 更理解java是值传递而不是引用传递
  4. 了解到想要在迭代过程中对集合进行操作要用Iterator,而不是直接简单的for循环或者增强for循环
posted @ 2019-10-15 17:58  oldmonk  阅读(1067)  评论(0编辑  收藏  举报
Fork me on GitHub