Spring Boot项目从Fastjson1升级到Fastjson2的完整实践指南

📅 2026/8/12 11:03:46
Spring Boot项目从Fastjson1升级到Fastjson2的完整实践指南
1. 项目概述为什么我们要从Fastjson1升级到Fastjson2如果你是一个Java后端开发者尤其是Spring Boot项目的常客那么“Fastjson”这个名字你一定不陌生。作为国内广泛使用的JSON处理库它以速度快、API简单著称几乎成了很多项目的默认选择。但最近几年围绕Fastjson 1.x版本的安全漏洞新闻层出不穷从反序列化漏洞到远程代码执行RCE每一次CVE编号的公布都让运维同学心头一紧。我亲身经历过几次半夜被安全部门电话叫醒紧急排查和升级Fastjson版本的经历那种感觉实在不好受。与此同时Fastjson的作者也意识到了1.x版本在架构和安全上的历史包袱于是推出了全新的Fastjson2。这不仅仅是一个简单的版本迭代而是一次彻底的重构。Fastjson2在性能、安全性、API设计上都有了质的飞跃并且官方明确表示Fastjson2是未来发展的重点。所以对于还在使用Fastjson1的老项目来说升级到Fastjson2已经不是“要不要做”的选择题而是“什么时候做”的必答题。这次我就结合自己最近将一个中型Spring Boot服务从Fastjson 1.2.83平滑升级到Fastjson 2.0.64的完整过程把其中的核心步骤、配置细节、遇到的坑以及解决方案毫无保留地分享给你。无论你是为了修复安全漏洞还是追求极致的性能这篇教程都能给你提供一条清晰的路径。2. 升级前的核心评估与准备工作在动手写一行代码之前充分的评估和准备是保证升级顺利、不出生产事故的关键。盲目升级导致的接口报错、数据错乱其修复成本远高于升级本身。2.1 深度评估你的项目真的适合直接升级吗首先我们需要对现有项目进行一次“体检”。打开你的pom.xml或者build.gradle找到Fastjson的依赖。1. 依赖关系梳理不仅仅是显式依赖的fastjson更要关注那些传递性依赖。比如你可能引入了某个第三方SDK它内部依赖了Fastjson 1.x。使用Maven命令可以清晰地看到依赖树mvn dependency:tree -Dincludescom.alibaba:fastjson或者Gradle命令./gradlew dependencies | grep fastjson记录下所有依赖Fastjson 1.x的库。如果某个核心的第三方库强依赖了老版本并且没有兼容的更新那么你的升级之路可能会很坎坷需要考虑是否替换该库或者寻找其他解决方案。2. 代码使用情况扫描Fastjson 1.x的API使用非常广泛且随意。你需要重点检查以下几类用法直接使用JSON.parseObject/toJSONString这是最普遍的。使用JSONField注解用于定制序列化/反序列化行为。使用SerializeConfig/ParserConfig进行全局配置比如定制枚举处理、日期格式等。使用TypeReference处理泛型如JSON.parseObject(jsonString, new TypeReferenceListUser(){})。使用了Fastjson特有的特性如JSONPath、JSONValidator等。我建议在IDE中全局搜索import com.alibaba.fastjson和import com.alibaba.fastjson2先快速了解现状。3. 兼容性模式调研Fastjson2提供了一个非常重要的特性兼容模式。通过JSON.config可以设置使用Fastjson 1.x的兼容API。这对于存量代码巨大的项目是一个福音可以逐步迁移。但需要注意的是兼容模式并非100%全覆盖某些非常冷门的特性或API可能不支持。官方文档是评估的第一手资料。2.2 工具与依赖准备评估完成后就可以开始准备升级了。1. 依赖变更对于Maven项目首先需要排除所有传递进来的Fastjson 1.x依赖然后显式引入Fastjson2。dependency groupIdcom.alibaba.fastjson2/groupId artifactIdfastjson2/artifactId version2.0.64/version !-- 建议使用当前最新稳定版 -- /dependency dependency groupIdcom.alibaba.fastjson2/groupId artifactIdfastjson2-extension-spring5/artifactId !-- 用于Spring 5/Spring Boot 2.x/3.x集成 -- version2.0.64/version /dependency关键点fastjson2-extension-spring5这个扩展包至关重要它提供了FastJsonHttpMessageConverter等类让我们能轻松集成到Spring MVC中。没有它后续的配置会麻烦很多。2. 备份与分支这是一个老生常谈但绝不能省略的步骤。在升级前确保你的代码已经提交并创建一个新的Git分支例如feature/upgrade-fastjson2。所有改动都在这个分支上进行与主开发线隔离。3. Spring Boot中配置Fastjson2为默认消息转换器这是升级的核心步骤目标是将Spring Boot默认的Jackson替换为Fastjson2。Spring Boot的自动配置为我们提供了便捷的入口但我们需要覆盖它。3.1 基础配置替换HttpMessageConverter在Spring Boot中HttpMessageConverter负责处理HTTP请求和响应中的内容转换如JSON到Java对象。我们需要提供一个基于Fastjson2的转换器。创建一个配置类例如Fastjson2Config.javaimport com.alibaba.fastjson2.support.config.FastJsonConfig; import com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; Configuration public class Fastjson2Config implements WebMvcConfigurer { Override public void configureMessageConverters(ListHttpMessageConverter? converters) { // 1. 创建FastJsonHttpMessageConverter实例 FastJsonHttpMessageConverter converter new FastJsonHttpMessageConverter(); // 2. 创建FastJsonConfig并配置这是核心配置入口 FastJsonConfig config new FastJsonConfig(); config.setDateFormat(yyyy-MM-dd HH:mm:ss); // 设置全局日期格式 config.setCharset(StandardCharsets.UTF_8); // 设置字符集 // 3. 可选但推荐配置序列化特性 // Fastjson2使用基于Getter/Setter的序列化而非字段反射更安全。 // 你可以通过config.setWriterFeatures()和config.setReaderFeatures()来精细控制行为。 // 例如默认情况下Fastjson2不会序列化null值这通常符合API设计规范。 // config.setWriterFeatures(JSONWriter.Feature.WriteMapNullValue); // 如果需要序列化null可开启 converter.setFastJsonConfig(config); // 4. 设置支持的MediaType必须加上application/json ListMediaType supportedMediaTypes new ArrayList(); supportedMediaTypes.add(MediaType.APPLICATION_JSON); supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); // 兼容旧版本 converter.setSupportedMediaTypes(supportedMediaTypes); // 5. 将Fastjson2的转换器添加到转换器列表的最前面优先使用 converters.add(0, converter); } }为什么这么做WebMvcConfigurer接口允许我们自定义Spring MVC的行为。将自定义的FastJsonHttpMessageConverter插入到列表首位converters.add(0, converter)是为了确保在处理application/json类型的请求时优先使用Fastjson2而不是Jackson。通过FastJsonConfig进行全局配置比在每次序列化/反序列化时传递参数更优雅、更统一。3.2 处理常见配置需求在实际项目中我们往往有更复杂的序列化/反序列化需求。1. 全局日期格式如上例所示通过config.setDateFormat(“yyyy-MM-dd HH:mm:ss”)可以统一设置日期序列化格式。这比在每个Date字段上使用JSONField(format“...”)更高效。2. 处理空值Fastjson2默认不序列化值为null的字段。这能使JSON响应更简洁也是很多API设计规范所推荐的。如果你的前端强依赖某些字段即使为null也必须出现则需要开启特定特性。import com.alibaba.fastjson2.JSONWriter; config.setWriterFeatures(JSONWriter.Feature.WriteMapNullValue);3. 自定义序列化/反序列化器对于特殊类型如自定义枚举、脱敏字段、LocalDateTime特殊格式等你可能需要定制。config.setWriterFilters(new MyValueFilter()); // 自定义序列化过滤器 config.setReaderFilters(new MyNameFilter()); // 自定义反序列化过滤器你也可以为特定类注册ObjectSerializer和ObjectDeserializer但这通常更复杂在FastJsonConfig层面通过Feature和Filter配置更能满足大部分场景。注意在Spring Boot 2.x及以上版本默认使用Jackson处理application/json。我们的配置成功生效后通过curl或Postman测试接口查看响应头的Content-Type和响应体格式确认已是Fastjson2处理后的结果例如日期格式变了null字段消失了。4. 解决代码层面的API兼容性问题即使配置好了消息转换器项目中散落的直接调用Fastjson API的代码也需要处理。这里有两条路激进重构或平滑兼容。4.1 方案一启用兼容模式平滑过渡如果你的老代码里到处都是JSON.parseObject短期内全部改为Fastjson2的APIJSON.parseObject变成了JSON.parseObject包名变了工作量巨大且风险高。此时Fastjson2的兼容模式是你的救星。在你的应用启动类Application.java或某个核心配置类中添加静态代码块import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONFactory; import com.alibaba.fastjson2.JSONReader; import com.alibaba.fastjson2.JSONWriter; import com.alibaba.fastjson2.support.config.FastJsonConfig; public class Application { static { // 启用Fastjson 1.x兼容模式 JSONFactory.setUseJacksonAnnotation(false); // 如果你不用Jackson注解可以关闭以提升性能 JSON.config(JSONReader.Feature.SupportAutoType, JSONWriter.Feature.WriteMapNullValue); // 按需配置特性 // 注意兼容模式主要针对 API 签名一些内部行为可能仍有差异。 } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }启用后你原来import com.alibaba.fastjson.JSON;的代码在编译时就会报错因为类路径下已经没有了1.x的jar包。你需要将所有这些导入语句批量替换为import com.alibaba.fastjson2.JSON;。替换后由于兼容模式的存在大部分JSON.parseObject、toJSONString等方法可以无需修改参数直接运行。兼容模式的局限性并非100%行为一致对于深度使用ParserConfig、SerializeConfig进行黑名单/白名单、自定义序列化等高级功能的代码需要仔细测试。性能上可能比原生Fastjson2 API略差因为它多了一层适配。它只是一个过渡方案最终目标还是应该迁移到纯正的Fastjson2 API。4.2 方案二逐一切换为Fastjson2原生API彻底升级这是推荐的做法尤其是对于新项目或你有足够测试覆盖率和重构窗口的老项目。Fastjson2的API设计更合理、更安全。1. 包名和基础API变更包名com.alibaba.fastjson-com.alibaba.fastjson2核心类JSON-JSON(类名没变但包变了)常用方法签名基本保持一致这是兼容模式的基础。2. 注解变更Fastjson 1.x的JSONField在Fastjson2中仍然存在但包名变了。// Fastjson 1.x import com.alibaba.fastjson.annotation.JSONField; // Fastjson 2.x import com.alibaba.fastjson2.annotation.JSONField;大部分属性如name,format,serialize,deserialize都是兼容的。但建议检查是否有使用不常见的属性。3. 重要行为差异坑点自动类型识别AutoType这是Fastjson 1.x众多安全漏洞的根源。Fastjson2默认关闭了AutoType。这意味着如果你的JSON字符串中包含type这样的字段来指示类型默认情况下反序列化会失败。如果你确实有合理的需求需要使用AutoType通常内部可信通信必须显式、谨慎地开启JSON.parseObject(jsonStr, User.class, JSONReader.Feature.SupportAutoType);强烈建议审查所有需要AutoType的场景尽可能通过其他方式如直接指定Class替代从根源上杜绝反序列化攻击风险。对null值的处理如前所述默认不序列化null字段。日期处理Fastjson2对java.util.Date和java.time.*LocalDateTime等的支持更好行为更一致。5. 测试、验证与性能调优配置和代码修改完成后绝不能直接上生产。必须经过严格的测试。5.1 构建全面的测试用例1. 单元测试为所有直接调用Fastjson API的工具类、方法添加或更新单元测试。重点测试包含复杂嵌套对象、集合、泛型的序列化/反序列化。日期、枚举、BigDecimal等特殊类型的处理。字段为null时的序列化结果。使用了JSONField注解的字段。2. 接口集成测试使用Postman、Swagger或编写集成测试代码对所有暴露的RESTful API进行测试。测试请求反序列化发送JSON请求体确保Controller能正确接收参数。测试响应序列化检查API返回的JSON格式是否符合预期日期格式、null字段、字段名映射等。边界测试发送畸形的JSON、超大的JSON、包含特殊字符的JSON观察系统的容错和处理。3. 兼容性回归测试如果你的服务被其他多个服务或前端调用需要协调进行联调测试确保数据格式的变更不会导致调用方解析失败。特别是字段缺失null不序列化的情况必须通知前端并确认其兼容性。5.2 性能对比与监控升级的一大动力是性能提升。你可以做一个简单的基准测试。1. 使用JMH进行微基准测试创建一个JMH测试对比同一个Java对象使用Jackson、Fastjson1和Fastjson2进行序列化和反序列化的吞吐量与时延。Fastjson2在大多数场景下应该优于Fastjson1并与Jackson互有胜负取决于数据类型。2. 全链路压测在测试环境对核心接口进行压测如使用JMeter对比升级前后的QPS、平均响应时间、P99延迟等关键指标。观察在高压下新的JSON处理库是否稳定内存使用是否正常。3. 监控告警上线后在监控系统如PrometheusGrafana中密切关注JVM GC情况序列化库频繁创建临时对象可能影响GC。接口错误率特别是4xx错误可能源于反序列化失败。接口耗时关注P95、P99响应时间是否有异常波动。6. 上线部署与回滚预案即使测试充分生产环境依然存在不确定性。必须有完整的发布和回滚计划。1. 分阶段发布如果服务集群规模大采用金丝雀发布或蓝绿部署。先让一小部分流量如5%切换到新版本观察监控指标和错误日志稳定后再逐步扩大流量比例。2. 准备快速回滚方案回滚方案必须简单、快速。通常就是准备好上一个稳定版本的部署包仍然使用Fastjson1并在发布脚本中写好一键回滚的命令。确保数据库等持久层数据格式在版本回滚后依然兼容。3. 日志与排查在配置中确保Fastjson2的日志级别在DEBUG或WARN。虽然Fastjson2自身日志不多但一旦出现序列化/反序列化异常其抛出的异常信息如JSONException对于定位问题至关重要。确保这些异常能被你的日志框架如Logback、Log4j2捕获并记录。7. 常见问题与排查技巧实录在实际升级过程中我遇到了不少问题这里把典型问题和解决方案记录下来希望能帮你少走弯路。7.1 问题一启动报错 -ClassNotFoundException或NoClassDefFoundError现象应用启动失败提示找不到com/alibaba/fastjson/JSON或相关的类。原因这是最典型的问题。虽然你引入了Fastjson2但项目中某个角落可能是某个jar包仍然在代码层面依赖Fastjson 1.x的类。排查与解决检查依赖树再次运行mvn dependency:tree确保所有com.alibaba:fastjson的依赖都被排除了。检查本地仓库有时候IDE缓存或本地Maven仓库混乱会导致依赖解析错误。尝试清理IDE缓存对于IDEA是File - Invalidate Caches...并执行mvn clean install -U强制更新依赖。检查第三方依赖如果错误来自某个第三方JAR你可能需要联系该库的维护者询问是否支持Fastjson2或者寻找替代库。7.2 问题二接口返回的JSON格式不符合预期现象日期格式变回了时间戳、null字段消失了或出现了、字段名变了。原因Spring Boot中配置的FastJsonHttpMessageConverter没有生效或者配置不正确。排查与解决确认配置类被加载在配置类中加一个日志输出或断点确保Spring Boot启动时加载了它。检查Converter顺序确保你的配置中使用了converters.add(0, converter)将其放在最前面。如果放在后面可能会被Jackson先处理。检查EnableWebMvc注解如果你在配置类上加了EnableWebMvc它会完全接管MVC配置导致通过WebMvcConfigurer添加的转换器失效。除非你需要完全自定义MVC否则不要轻易使用这个注解。检查配置属性确认FastJsonConfig中的日期格式、字符集、特性Features设置正确。可以通过编写一个简单的RestController测试接口返回一个包含各种数据类型的对象来验证。7.3 问题三反序列化时出现JSONException: autoType not support现象解析包含type信息的JSON字符串时抛异常。原因Fastjson2基于安全考虑默认关闭了AutoType特性。解决最佳实践重构代码避免使用AutoType。使用明确的Class类型进行反序列化。如果必须使用在反序列化时显式开启SupportAutoType特性。// 方式1在每次解析时指定 MyClass obj JSON.parseObject(jsonStr, MyClass.class, JSONReader.Feature.SupportAutoType); // 方式2通过FastJsonConfig全局配置危险谨慎使用 // config.setReaderFeatures(JSONReader.Feature.SupportAutoType);警告全局开启AutoType会重新引入安全风险务必确保输入的JSON来源绝对可信并考虑结合白名单机制Fastjson2也提供了相关配置。7.4 问题四升级后性能反而下降现象压测结果显示QPS降低或延迟增高。原因与排查兼容模式开销如果你开启了兼容模式会有一层额外的适配开销。对于性能极度敏感的场景建议最终迁移到原生API。配置不当例如错误地配置了大量不必要的Feature如WriteMapNullValue、PrettyFormat在生产环境或者序列化过滤器Filter逻辑复杂。数据类型差异Fastjson2对不同数据类型的优化程度不同。如果你的业务对象结构发生了巨大变化例如大量使用了之前Fastjson1针对某种结构做的特殊优化可能需要重新审视。JVM Warm-up确保压测前JVM已经充分预热因为Just-In-Time编译器会对热点代码进行优化。7.5 一个容易被忽略的“坑”Spring Boot Actuator端点如果你的项目使用了Spring Boot Actuator来提供监控端点如/actuator/health,/actuator/metrics需要注意Actuator这些端点的JSON输出默认可能仍然由Jackson处理不受我们自定义的WebMvcConfigurer影响。解决方案如果需要统一可以尝试通过自定义ObjectMapperBean来影响Actuator但更常见的做法是接受这种不一致因为Actuator端点的数据结构是固定的且通常只被监控系统消费。只要业务接口正确即可。整个升级过程从评估、配置、修改代码到测试上线更像是一次对项目JSON处理能力的深度梳理和加固。踩过这些坑之后最大的体会是对于基础组件的升级尤其是涉及安全漏洞的态度要坚决但操作要谨慎。完备的测试和清晰的回滚方案是胆量的来源。Fastjson2不仅带来了性能提升更重要的是在安全性上迈出了一大步默认关闭AutoType这个决定就值得所有开发者为其升级投上一票。