SpringBoot替换为FastJSon

2,971 阅读5分钟

本文介绍了在SpringBoot项目中将默认的Jackson替换为阿里巴巴的FastJson。

1、原理说明

HttpMessageConverter的作用

先看HttpMessageConverter接口源码。

public interface HttpMessageConverter<T> {

    boolean canRead(Class<?> clazz, MediaType mediaType);

    boolean canWrite(Class<?> clazz, MediaType mediaType);

    List<MediaType> getSupportedMediaTypes();

    T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
            throws IOException, HttpMessageNotReadableException;

    void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
            throws IOException, HttpMessageNotWritableException;
}

   Http请求响应报文其实都是字符串,在Spring的处理过程中,一次请求报文和一次响应报文,分别被抽象为一个请求消息HttpInputMessage和一个响应消息HttpOutputMessage。
   在请求进入对应Mapping()方法前,会根据@RequestBody注解选择对应HttpMessageConverter实现类来将请求参数解析到param变量中,因为这里的参数的类型的,选择使用StringHttpMessageConverter()类或者JsonbHttpMessageConverter(),它的canRead()方法返回true,然后read()方法会从请求中读出请求参数,绑定到Mapping()注解对应的方法param变量中。同理当执行Mapping()方法后,由于返回值标识了@ResponseBody,SpringMVC / SpringBoot将使用StringHttpMessageConverter的write()方法,将结果作为String值写入响应报文,当然,此时canWrite()方法返回true。
   整个过程:

IMG_0207.JPG

   我们需要替换的便是HttpMessageConverter中默认Json解析器。

2、实现步骤

2.1 添加依赖

所有的都要去除spring-boot-starter-json依赖

<!-- Spring Boot web启动器 -->
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-json</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-json</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>

2.2 配置fastjson

2.2.1 方法一:重写configureMessageConverters()方法的方式

package com.smallthanks.psi.config;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;


/**
 * @author SmallThanks
 * 使用FastJson替换原有的Jackson
 */
@SpringBootConfiguration
public class JsonConfig implements WebMvcConfigurer{

	/**
	 * 第一种实现方式
	 * @param converters 转换器
	 */
	@Override
	public void configureMessageConverters(List<HttpMessageConverter<?>> converters){
		// 0、定义一个convert转换消息的对象
		FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
		// 1、添加fastJson的配置信息
		FastJsonConfig fastJsonConfig = new FastJsonConfig();
		fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
		fastConverter.setFastJsonConfig(fastJsonConfig);
		converters.add(fastConverter);
	}
}

2.2.1 方法一:注入bean方式

package com.smallthanks.psi.config;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;


/**
 * @author SmallThanks
 * 使用FastJson替换原有的Jackson
 */
@SpringBootConfiguration
public class JsonConfig {

//  第二种实现方式和第一种一样
	@Bean
	public HttpMessageConverters fastJsonHttpMessageConverters() {
		// 0、定义一个convert转换消息的对象
		FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
		// 1、添加fastJson的配置信息
		FastJsonConfig fastJsonConfig = new FastJsonConfig();
		fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
		fastConverter.setFastJsonConfig(fastJsonConfig);
		return new HttpMessageConverters(fastConverter);
	}
}

3、疑问解答

3.1 日期问题

   如果想在全局使用一个格式返回,那么可以设置fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
   如果使用@JSONField(format = "yyyy-MM-dd HH:mm:ss")修饰属性,那么返回我们指定的格式,有且只对当前的对象生效。其中JSONFiled中的name属性,是指定当前当前属性转成JSON后的key。

3.2 SerializerFeatures/序列化器功能

   我们可以看到fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);这样的一句话,这句话是全局设定在将对象转为JSON中对于属性的规则,具体我们看下表。
   同样我们也可以在对象的每一个属性上加一个注解@JSONField(serialzeFeatures="xxx")中指定一个属性单独的格式。

枚举名作用备注
QuoteFieldNames输出key时是否使用双引号,默认为true已验证
UseSingleQuotes使用单引号而不是双引号,默认为false已验证
WriteMapNullValue是否输出值为null的字段,默认为false默认不输出null的key
WriteEnumUsingToStringEnum输出name()或者original,也就是转为toString已验证
WriteEnumUsingNameenum值序列化为其Name,默认为true。其效果同上已验证
UseISO8601DateFormatDate使用ISO8601格式输出,默认为false。已验证
WriteNullListAsEmptyList字段如果为null,输出为[],而非null已验证
WriteNullStringAsEmpty字符类型字段如果为null,输出为”“,而非null已验证
WriteNullNumberAsZero数值字段如果为null,输出为0,而非null已验证
WriteNullBooleanAsFalseBoolean字段如果为null,输出为false,而非null已验证
SkipTransientField如果是true,类中的Get方法对应的Field是transient,
get方法有transient注解序列化时将会被忽略。默认为true
不常用未验证
SortField排序输出不知道是不是按照字母排序,验证未成功
WriteTabAsSpecial把\t做转义输出,默认为false已过时,不使用
PrettyFormat结果是否格式化,默认为false已验证,按照标准的格式格式化json
WriteClassName序列化时写入class信息,反序列化是需用到已验证
DisableCircularReferenceDetect消除对同一对象循环引用的问题,默认为false禁用循环引用检测(强烈建议禁用)
WriteSlashAsSpecial对斜杠’/’进行转义已验证
BrowserCompatible将中文都会序列化为\uXXXX格式,能兼容IE6,默认为falseIE 已经淘汰,基本没有
WriteDateUseDateFormat全局修改日期格式,默认为false默认格式yyyy-MM-dd HH:mm:ss
NotWriteRootClassName不输出根class名称,随着WriteClassName使用,
不输出当前类的信息,输入属性中包含类的信息
已验证
DisableCheckSpecialChar禁止特殊字符检查已过时不使用
BeanToArray将对象转为array输出转为一个数组输出
WriteNonStringKeyAsStringkey不是String的字段写为String也就是数字的字段加上""
NotWriteDefaultValue默认的值不输出属性没有进行赋值操作不输出
BrowserSecure待补充待补充
IgnoreNonFieldGetter忽略没有getter方法的属性没有get字段不在序列化
WriteNonStringValueAsStringvalue字段不是String写为String也就是value数字的字段加上""
IgnoreErrorGetter忽略 getter 方法报错目前不知道有什么用
WriteBigDecimalAsPlain使用 BigDecimal.toPlainString() 序列化目前不知道有什么用
MapSortField对属性排序输出目前测试出对map集合中的key排序

3.3、@JSONField中属性作用

名称作用默认值
ordinal配置序列化和反序列化的顺序,作用好像不大0
name序列化时候的key""
format指定日期的格式,可以使用JSON.DEFFAULT_DATE_FORMAT""
serialize是否序列化True
deserialize是否反序列化True
serialzeFeatures序列化的规则,如上表{}
parseFeatures反序列化的规则,懒得做-。-{}
....其他的(wo)不(ye)太(bu)重(hui)要的...

还有几个注解我也不会,会的同学可以评论我。至此基本已经完成了FastJSON的基本学习。