在 Spring 应用中使用 Fastjson2

Fastjson2Fastjson 的一个重大升级版本。

以下摘自官方的介绍:

FASTJSON 2是一个性能极致并且简单易用的Java JSON库。

总得来说,提高了性能(拳打 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 中的 FastJsonHttpMessageConverterFastJsonJsonView 为 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 中的 GenericFastJsonRedisSerializerFastJsonRedisSerializer 为 Spring Data Redis 提供更好的性能体验。

4.1、通用的 RedisSerializer

使用 GenericFastJsonRedisSerializer 作为 RedisTemplateRedisSerializer 来提升 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 作为对象序列/反序列化的方式并对序列化速度有较高的要求的话,可以对 FastJsonConfigjsonb 参数进行配置,该参数是 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;
    }
}

参考:Spring Messaging 中文文档


Ref:https://github.com/alibaba/fastjson2/blob/main/docs/spring_support_cn.md