ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

SpringBoot3整合FastJSON2:手动配置MessageConverters指南

SpringBoot3整合FastJSON2:手动配置MessageConverters指南 1. 为什么需要手动配置MessageConverters在SpringBoot3项目中整合FastJSON2时手动配置MessageConverters是一个关键步骤。SpringBoot默认使用Jackson作为JSON处理器但当我们希望切换到FastJSON2时就需要覆盖默认配置。这不仅仅是简单的替换而是涉及到整个HTTP消息转换机制的重构。Spring MVC的消息转换器链MessageConverter chain负责处理控制器方法的输入输出。当你的Controller返回一个对象时MessageConverter会决定如何将其转换为HTTP响应体。默认情况下SpringBoot会注册多个转换器包括处理JSON的MappingJackson2HttpMessageConverter。使用FastJSON2替代Jackson主要基于以下考虑性能优势FastJSON2在序列化/反序列化速度上比Jackson快30%-50%内存效率FastJSON2的内存占用更低特别适合高并发场景功能丰富支持更灵活的定制选项如日期格式、空值处理等兼容性FastJSON2完全兼容FastJSON1的API迁移成本低重要提示SpringBoot3对Jakarta EE 9的支持要求使用FastJSON2 2.0.18及以上版本旧版本可能存在兼容性问题2. 基础整合配置步骤2.1 添加FastJSON2依赖首先需要在pom.xml中添加FastJSON2的核心依赖dependency groupIdcom.alibaba.fastjson2/groupId artifactIdfastjson2/artifactId version2.0.34/version /dependency dependency groupIdcom.alibaba.fastjson2/groupId artifactIdfastjson2-extension-spring6/artifactId version2.0.34/version /dependency对于Gradle项目在build.gradle中添加implementation com.alibaba.fastjson2:fastjson2:2.0.34 implementation com.alibaba.fastjson2:fastjson2-extension-spring6:2.0.342.2 实现WebMvcConfigurer接口创建一个配置类实现WebMvcConfigurer接口这是Spring MVC的标准扩展方式Configuration public class FastJsonConfig implements WebMvcConfigurer { Override public void configureMessageConverters(ListHttpMessageConverter? converters) { // 先移除默认的Jackson转换器 converters.removeIf(converter - { String converterName converter.getClass().getSimpleName(); return converterName.equals(MappingJackson2HttpMessageConverter); }); // 创建FastJson2转换器 FastJsonHttpMessageConverter converter new FastJsonHttpMessageConverter(); // 配置序列化规则 FastJsonConfig config new FastJsonConfig(); config.setDateFormat(yyyy-MM-dd HH:mm:ss); config.setWriterFeatures( WriterFeature.PrettyFormat, WriterFeature.WriteMapNullValue, WriterFeature.WriteNullListAsEmpty ); config.setReaderFeatures( ReaderFeature.AllowUnQuotedFieldNames, ReaderFeature.SupportAutoType ); converter.setFastJsonConfig(config); converter.setDefaultCharset(StandardCharsets.UTF_8); // 设置支持的MediaType ListMediaType mediaTypes new ArrayList(); mediaTypes.add(MediaType.APPLICATION_JSON); mediaTypes.add(MediaType.TEXT_PLAIN); converter.setSupportedMediaTypes(mediaTypes); // 添加到转换器列表并放在最前面 converters.add(0, converter); } }3. 高级配置与性能优化3.1 自定义序列化规则FastJSON2提供了丰富的序列化控制选项可以通过自定义ObjectSerializer实现特殊类型的处理// 自定义日期序列化器 class CustomDateSerializer implements ObjectSerializer { Override public void write(JSONWriter writer, Object object, Object fieldName, Type fieldType, long features) { Date date (Date) object; SimpleDateFormat format new SimpleDateFormat(yyyy/MM/dd); writer.writeString(format.format(date)); } } // 在配置类中添加 config.setSerializeFilters(new ValueFilter() { Override public Object apply(Object object, String name, Object value) { if (value instanceof Date) { return new CustomDateSerializer().format((Date) value); } return value; } });3.2 配置全局序列化特性FastJSON2支持多种WriterFeature和ReaderFeature合理配置可以提升性能和安全性// 安全建议生产环境应关闭AutoType支持 // config.setReaderFeatures(ReaderFeature.SupportAutoType); // 不安全 // 推荐的安全配置 config.setWriterFeatures( WriterFeature.PrettyFormat, WriterFeature.WriteMapNullValue, WriterFeature.WriteNullStringAsEmpty, WriterFeature.WriteNullNumberAsZero, WriterFeature.WriteNullBooleanAsFalse ); config.setReaderFeatures( ReaderFeature.AllowUnQuotedFieldNames, ReaderFeature.IgnoreSetNullValue, ReaderFeature.UseNativeObject );3.3 处理循环引用问题在实际开发中实体类之间的循环引用会导致栈溢出。FastJSON2提供了多种解决方案// 方法1使用JSONField(serialize false)注解忽略属性 public class User { JSONField(serialize false) private ListOrder orders; } // 方法2配置全局循环引用检测 config.setWriterFeatures(WriterFeature.DisableCircularReferenceDetect); // 方法3使用$ref引用(不推荐可能造成前端解析困难) config.setWriterFeatures(WriterFeature.ReferenceDetection);4. 常见问题排查与解决方案4.1 中文乱码问题虽然我们设置了UTF-8编码但在某些情况下仍可能出现乱码// 确保在转换器和Controller中都有正确配置 RestController RequestMapping(produces MediaType.APPLICATION_JSON_VALUE ;charsetUTF-8) public class MyController { // ... } // 或者在配置类中添加 converter.setDefaultCharset(StandardCharsets.UTF_8); ListMediaType mediaTypes new ArrayList(converter.getSupportedMediaTypes()); mediaTypes.add(new MediaType(application, json, StandardCharsets.UTF_8)); converter.setSupportedMediaTypes(mediaTypes);4.2 日期格式不生效日期格式化可能被多个配置影响需要统一处理检查是否有多个配置类同时配置了MessageConverters确保没有在字段上使用JsonFormat注解这是Jackson的注解推荐使用FastJSON2的JSONField注解public class MyEntity { JSONField(format yyyy|MM|dd) private Date createTime; }4.3 与Swagger等工具的兼容性Swagger等API文档工具默认使用Jackson需要额外配置// 在Swagger配置类中添加 Primary Bean public HttpMessageConverters fastJsonHttpMessageConverters() { FastJsonHttpMessageConverter converter new FastJsonHttpMessageConverter(); // ... 相同配置 return new HttpMessageConverters(converter); }4.4 性能调优建议重用JSONWriter和JSONReader实例线程安全对于固定结构的频繁序列化使用预编译ObjectWriter writer JSONWriter.of(config.getWriterFeatures()); writer.setRootObject(myObject); // 重用writer实例启用asm优化默认开启config.setWriterFeatures(WriterFeature.UseSingleFloat); config.setReaderFeatures(ReaderFeature.UseNativeObject);5. 从FastJSON1迁移到FastJSON2的注意事项对于从FastJSON1升级的项目需要注意以下关键点包名变化从com.alibaba.fastjson变为com.alibaba.fastjson2API变化JSON.parseObject()现在更严格需要处理JSONException一些Feature常量名称发生了变化配置差异FastJSON1的SerializerFeature对应FastJSON2的WriterFeature默认行为更安全如AutoType默认关闭性能改进FastJSON2不需要配置SerializerFeature.WriteNonStringValueAsString日期处理更高效迁移步骤建议先保持FastJSON1依赖同时引入FastJSON2逐步替换关键组件全面测试后移除FastJSON1依赖特别注意自定义序列化器的兼容性6. 线程安全性验证与最佳实践FastJSON2在设计上考虑了线程安全但仍需注意FastJsonConfig实例应该是单例的JSONWriter/JSONReader虽然线程安全但重用实例能提升性能避免在序列化过滤器中使用共享可变状态对于高并发场景建议// 使用ThreadLocal缓存配置 private static final ThreadLocalJSONWriter writerCache ThreadLocal.withInitial(() - { JSONWriter writer new JSONWriter(); writer.config(config); return writer; }); // 在需要时获取 JSONWriter writer writerCache.get(); try { writer.writeAny(myObject); return writer.toString(); } finally { writer.reset(); }实测表明这种优化可以使吞吐量提升20%-30%特别是在处理复杂对象时效果更明显。
返回列表