springboot2.1.1默認采用的json converter是MappingJackson,通過調試springboot項目中代碼可以確定這點。在springboot項目中定義WebMvcConfig.java
@Configuration @Import({WebMvcAutoConfiguration.class}) @ComponentScan( value = "com.dx.test.web", includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class) }) public class WebMvcConfig implements WebMvcConfigurer { /** * 使用 fastjson 代替 jackson * * @param converters */ @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { List<HttpMessageConverter<?>> myConverters = converters; } }
斷電設置在"List<HttpMessageConverter<?>> myConverters = converters;"這行代碼處,然后調試進入該出斷電,查看converters集合下元素:
從上表調試截圖,可以發現springboot2.1.1默認采用的json converter是MappingJackson。
新建SpringBoot項目,並引入fastjson:
pom.xml配置如下:
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <!-- springboot web組件依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.56</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies>
SpringBoot入口類:
package com.dx.test.app; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Hello world! */ @SpringBootApplication(scanBasePackages = {"com.dx.test"}) public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
使用fastjson作為springboot2.x的json converter的兩種實現方法:
- 實現WebMvcConfigurer接口的void configureMessageConverters(List<HttpMessageConverter<?>> converters)方法;
- 在WebMvcConfigurer接口實現類內定義bean(HttpMessageConverters)
為什么要使用fastjson替換jackson呢?
1)fastjson快;
2)國產,支持國產。
實現WebMvcConfigurer接口來使用fastjson:
實現代碼如下:
/** * WebMvcConfigurerAdapter 這個類在SpringBoot2.0已過時,官方推薦直接實現 WebMvcConfigurer 這個接口 */ @Configuration @Import({WebMvcAutoConfiguration.class}) @ComponentScan( value = "com.dx.test.web", includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class) }) public class WebMvcConfig implements WebMvcConfigurer { /** * 使用 fastjson 代替 jackson * * @param converters */ @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { /* 先把JackSon的消息轉換器刪除. 備注:(1)源碼分析可知,返回json的過程為: Controller調用結束后返回一個數據對象,for循環遍歷conventers,找到支持application/json的HttpMessageConverter,然后將返回的數據序列化成json。 具體參考org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor的writeWithMessageConverters方法 (2)由於是list結構,我們添加的fastjson在最后。因此必須要將jackson的轉換器刪除,不然會先匹配上jackson,導致沒使用 fastjson */ for (int i = converters.size() - 1; i >= 0; i--) { if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) { converters.remove(i); } } FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); //自定義fastjson配置 FastJsonConfig config = new FastJsonConfig(); config.setSerializerFeatures( SerializerFeature.WriteMapNullValue, // 是否輸出值為null的字段,默認為false,我們將它打開 SerializerFeature.WriteNullListAsEmpty, // 將Collection類型字段的字段空值輸出為[] SerializerFeature.WriteNullStringAsEmpty, // 將字符串類型字段的空值輸出為空字符串 SerializerFeature.WriteNullNumberAsZero, // 將數值類型字段的空值輸出為0 SerializerFeature.WriteDateUseDateFormat, SerializerFeature.DisableCircularReferenceDetect // 禁用循環引用 ); fastJsonHttpMessageConverter.setFastJsonConfig(config); // 添加支持的MediaTypes;不添加時默認為*/*,也就是默認支持全部 // 但是MappingJackson2HttpMessageConverter里面支持的MediaTypes為application/json // 參考它的做法, fastjson也只添加application/json的MediaType List<MediaType> fastMediaTypes = new ArrayList<>(); fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes); converters.add(fastJsonHttpMessageConverter); } }
實現思路,先把jackson從converters中移除掉,然后加入fastjson converter。
注意:
1)在該fastjson converter注入時,設置了fastjson配置信息:FastJsonConfig.setSerializerFeatures(循環依賴,是否輸出null的字段等),這些設置將會影響Restful Api輸出信息。
2)但是這個設置並不會影響系統JSON.toJSONString(List<Article>)的配置信息,如果需要控制序列化配置,需要這么使用:
// 序列化為json
String content = JSON.toJSONString(orderByItems, SerializerFeature.WriteMapNullValue);
在WebMvcConfigurer接口實現類內定義bean(HttpMessageConverters)來使用fastjson:
實現代碼如下:
/** * WebMvcConfigurerAdapter 這個類在SpringBoot2.0已過時,官方推薦直接實現 WebMvcConfigurer 這個接口 */ @Configuration @Import({WebMvcAutoConfiguration.class}) @ComponentScan( value = "com.dx.test.web", includeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class) }) public class WebMvcConfig implements WebMvcConfigurer { /** * +支持fastjson的HttpMessageConverter * * @return HttpMessageConverters */ @Bean public HttpMessageConverters fastJsonHttpMessageConverters() { AbstractHttpMessageConverter abstractHttpMessageConverter = null; //1.需要定義一個convert轉換消息的對象; FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); //2:添加fastJson的配置信息; FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures( SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.DisableCircularReferenceDetect); fastJsonConfig.setCharset(Charset.forName("utf-8")); //3處理中文亂碼問題 List<MediaType> fastMediaTypes = new ArrayList<>(); fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); //4.在convert中添加配置信息. fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes); fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig); HttpMessageConverter<?> converter = fastJsonHttpMessageConverter; return new HttpMessageConverters(converter); } }
該方式會自動覆蓋(替換jackson converter)。
針對json輸出字段處理:格式化日期&控制字段是否輸出:
1)日期格式化輸出設置:只需要在實體的屬性上添加注解@JSONField(format = "yyyy-MM-dd")
public class MyVo { ... @JSONField(format = "yyyy-MM-dd") @ApiModelProperty(value = "最新StartTime,不存在時,返回null") private Date lastStartTimePlus1Day;// 最新startTime /** * @return the lastStartTimePlus1Day */ public Date getLastStartTimePlus1Day() { return lastStartTimePlus1Day; } /** * @param lastStartTimePlus1Day the lastStartTimePlus1Day to set */ public void setLastStartTimePlus1Day(Date lastStartTimePlus1Day) { this.lastStartTimePlus1Day = lastStartTimePlus1Day; } }
2)控制字段是否輸出,添加注解
public class MyVo{ ... @JSONField(serialize = true) @ApiModelProperty("權重排序:僅排序使用,序列化不輸出") private Double weight; /** * @return the weight */ public Double getWeight() { return weight; } /** * @param weight the weight to set */ public void setWeight(Double weight) { this.weight = weight; } }