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循環


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM