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; } }