在 Spring 应用中使用 Fastjson2
Fastjson2
是 Fastjson
的一个重大升级版本。
以下摘自官方的介绍:
FASTJSON 2
是一个性能极致并且简单易用的Java JSON库。
FASTJSON 2
是FASTJSON
项目的重要升级,和FASTJSON 1相比,性能有非常大的提升,解决了autoType功能因为兼容和白名单的安全性问题。- 性能极致,性能远超过其他流行 JSON 库,包括 jackson/gson/org.json,性能数据: https://github.com/alibaba/fastjson2/wiki/fastjson_benchmark
- 支持JDK新特性,包括
JDK 11
/JDK 17
,针对compact string
优化,支持Record,支持GraalVM Native-Image
- 完善的
JSONPath
支持,支持 SQL:2016 的JSONPath
语法- 支持
Android 8+
,客户端和服务器一套 API- 支持
Kotlin
https://alibaba.github.io/fastjson2/kotlin_cn- 支持
JSON Schema
https://alibaba.github.io/fastjson2/json_schema_cn- 新增加支持二进制格式 JSONB https://alibaba.github.io/fastjson2/jsonb_format_cn
总得来说,提高了性能(拳打 Gson,脚踢 Jackson)和饱解决了饱受诟病的安全问题(因为 Fastjson
屡次爆出反序列化安全问题,在国内被戏称为 Bugjson)。
Fastjson2 确实一个款性能很高的 Json 库,API 也设计得比较简单、易用。本文将带你了解如何在 Spring 中使用 Fastjson2。
1、依赖
Fastjson2
采用 多模块 的结构设计,对 Spring 等框架的支持现独立在 extension
包中。
2.0.23
版本之后为了兼容 Spring 5.x / 6.x,将不同的版本独立出来了。
使用 Maven:
<!-- Sring 5 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension-spring5</artifactId>
<version>2.0.42</version>
</dependency>
<!-- 或者 -->
<!-- Sring 6 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension-spring6</artifactId>
<version>2.0.42</version>
</dependency>
使用 Gradle:
dependencies {
implementation 'com.alibaba.fastjson2:fastjson2-extension-spring5:2.0.42'
}
// 或者
dependencies {
implementation 'com.alibaba.fastjson2:fastjson2-extension-spring6:2.0.42'
}
1.1、2.0.23
之前的版本
如过你使用的是 Fastjson2 2.0.23
之前的版本,则可以直接使用以下依赖。
使用 Maven:
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension</artifactId>
<version>2.0.x</version>
</dependency>
使用 Gradle:
dependencies {
implementation 'com.alibaba.fastjson2:fastjson2-extension:2.0.x'
}
2、参数配置
Fastjson2 对于序列化和反序列化的行为进行了重新设计,所以 FastJsonConfig
也会重新适配。
配置类 com.alibaba.fastjson2.support.config.FastJsonConfig
的可配置参数如下表:
参数 | 类型 | 描述 |
---|---|---|
charset |
Charset | 指定的字符集,默认 UTF-8 |
dateFormat |
String | 指定的日期格式,默认 yyyy-MM-dd HH:mm:ss |
writerFilters |
Filter[] | 配置序列化过滤器 |
writerFeatures |
JSONWriter.Feature[] | 配置序列化的指定行为,更多配置请见:Features |
readerFilters |
Filter[] | 配置反序列化过滤器 |
readerFeatures |
JSONReader.Feature[] | 配置反序列化的指定行为,更多配置请见:Features |
jsonb |
boolean | 是否采用JSONB进行序列化和反序列化,默认false |
symbolTable |
JSONB.SymbolTable | JSONB 序列化和反序列化的符号表,只有使用 JSONB 时生效 |
3、在 Spring Web MVC 中集成 Fastjson2
可以使用 Fastjson2 中的 FastJsonHttpMessageConverter
和 FastJsonJsonView
为 Spring MVC 构建的 Web 应用提供更好的性能体验。
2.1、Spring Web MVC Converter
使用 FastJsonHttpMessageConverter
来替换 Spring MVC 默认的 HttpMessageConverter
以提高 @RestController
、@ResponseBody
和 @RequestBody
注解的 JSON 序列化和反序列化速度。
FastJsonHttpMessageConverter
的配置示例如下:
// com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter
@Configuration
@EnableWebMvc
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
//自定义配置...
FastJsonConfig config = new FastJsonConfig();
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
config.setReaderFeatures(JSONReader.Feature.FieldBased, JSONReader.Feature.SupportArrayToBean);
config.setWriterFeatures(JSONWriter.Feature.WriteMapNullValue, JSONWriter.Feature.PrettyFormat);
converter.setFastJsonConfig(config);
converter.setDefaultCharset(StandardCharsets.UTF_8);
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
converters.add(0, converter);
}
}
2.2、pring Web MVC View
使用 FastJsonJsonView
来设置 Spring MVC 默认的视图模型解析器,以提高 @Controller
@ResponseBody
ModelAndView
JSON 序列化速度。
FastJsonJsonView
配置实例如下:
// com.alibaba.fastjson2.support.spring.webservlet.view.FastJsonJsonView
@Configuration
@EnableWebMvc
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
FastJsonJsonView fastJsonJsonView = new FastJsonJsonView();
//自定义配置...
//FastJsonConfig config = new FastJsonConfig();
//config.set...
//fastJsonJsonView.setFastJsonConfig(config);
registry.enableContentNegotiation(fastJsonJsonView);
}
}
参考:Spring 中文文档的 Spring Web MVC 部分。
3、在 Spring Web Socket 中集成 Fastjson2
Fastjson2 同样也对 Spring WebSocket 提供了支持。可以使用 FastjsonSockJsMessageCodec
进行配置。
FastjsonSockJsMessageCodec
配置示例如下:
@Component
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Resource
WebSocketHandler handler;
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//自定义配置...
//FastjsonSockJsMessageCodec messageCodec = new FastjsonSockJsMessageCodec();
//FastJsonConfig config = new FastJsonConfig();
//config.set...
//messageCodec.setFastJsonConfig(config);
registry.addHandler(handler, "/sockjs").withSockJS().setMessageCodec(new FastjsonSockJsMessageCodec());
}
}
参考:Spring 中文文档 Spring WebSocket 部分 。
4、在 Spring Data Redis 中集成 Fastjson2
同样可以使用 Fastjson2 中的 GenericFastJsonRedisSerializer
或 FastJsonRedisSerializer
为 Spring Data Redis 提供更好的性能体验。
4.1、通用的 RedisSerializer
使用 GenericFastJsonRedisSerializer
作为 RedisTemplate
的 RedisSerializer
来提升 JSON 序列化和反序列化速度。
GenericFastJsonRedisSerializer
配置示例如下:
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
redisTemplate.setDefaultSerializer(fastJsonRedisSerializer);//设置默认的Serialize,包含 keySerializer & valueSerializer
//redisTemplate.setKeySerializer(fastJsonRedisSerializer);//单独设置keySerializer
//redisTemplate.setValueSerializer(fastJsonRedisSerializer);//单独设置valueSerializer
return redisTemplate;
}
}
4.2、自定义 RedisSerializer
通常使用 GenericFastJsonRedisSerializer
即可满足大部分场景,如果你想定义特定类型专用的 RedisTemplate
可以使用 FastJsonRedisSerializer
来代替 GenericFastJsonRedisSerializer
,配置和上面类似。
FastJsonRedisSerializer
配置示例如下:
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(User.class);
redisTemplate.setDefaultSerializer(fastJsonRedisSerializer);
return redisTemplate;
}
}
4.3、JSONB RedisSerializer
如果你准备使用 JSONB 作为对象序列/反序列化的方式并对序列化速度有较高的要求的话,可以对 jsonb 参数进行配置,该参数是 fastjson 2.0.6
版本中新增的支持,配置也很简单。
配置示例如下:
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// GenericFastJsonRedisSerializer use jsonb
// GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer(true);
// FastJsonRedisSerializer use jsonb
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(User.class);
// FastJsonConfig fastJsonConfig = new FastJsonConfig();
// fastJsonConfig.setJSONB(true);
// fastJsonRedisSerializer.setFastJsonConfig(fastJsonConfig);
redisTemplate.setDefaultSerializer(fastJsonRedisSerializer);
return redisTemplate;
}
}
参考:Spring Data Redis 中文文档。
5、在 Spring Messaging 中集成 Fastjson2
在Fastjson2中,同样可以使用 MappingFastJsonMessageConverter
为 Spring Messaging 提供更好的性能体验。
5.1、JSON MessageConverter
使用 MappingFastJsonMessageConverter
在 Spring Cloud Stream 或 Spring Messaging 中提升 Message 的序列化和反序列化速度。
MappingFastJsonMessageConverter
配置示例如下:
@Configuration
public class StreamConfiguration {
@Bean
@StreamMessageConverter
public MappingFastJsonMessageConverter messageConverter() {
return new MappingFastJsonMessageConverter();
}
}
5.2、JSONB MessageConverter
如果你准备使用 JSONB 作为对象序列/反序列化的方式并对序列化速度有较高的要求的话,可以对 FastJsonConfig
的 jsonb
参数进行配置,该参数是 fastjson 2.0.6
版本中新增的支持,配置也很简单。
注意:JSONB 仅支持将 Message 的 Payload 序列化为 byte[]
!
配置示例如下:
@Configuration
public class StreamConfiguration {
@Bean
@StreamMessageConverter
public MappingFastJsonMessageConverter messageConverter() {
MappingFastJsonMessageConverter messageConverter = new MappingFastJsonMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setJSONB(true); // use jsonb
messageConverter.setFastJsonConfig(fastJsonConfig);
return messageConverter;
}
}
Ref:https://github.com/alibaba/fastjson2/blob/main/docs/spring_support_cn.md