SpringBoot4-升级说明.md 6.8 KB

Spring Boot 3.2.5 → 4.1.1 升级说明

升级日期:2026-10-19 分支:feature/spring-boot-4(基于 develop 的 147bbe6,即已升到 3.5.16 的提交)

一、版本变化

组件 升级前 升级后
Spring Boot 3.2.5 4.1.1
Spring Framework 6.1.x 7.0.9(Boot 传递)
Spring Security (crypto) 6.2.x 7.0.x
Jakarta EE 基线 10(Servlet 6.0 / Tomcat 10.1) 11(Servlet 6.1 / Tomcat 11.0.24)
Jackson 2.15 3.1.5(tools.jackson.*)
MyBatis-Plus 3.5.5 / spring-boot3-starter 3.5.17 / spring-boot4-starter
JDK 21 21(不变,Boot 4 基线为 17)

升级前先单独落了一版 3.5.16(提交 147bbe6),确认零改动即可通过全部回归,再进 4.x,避免跨两个大版本混在一起排错。

二、代码改动(58 文件)

1. Jackson 包名迁移(54 文件,纯 import)

com.fasterxml.jackson.databind|core → tools.jackson.databind|core。

注解不动:@JsonProperty / @JsonIgnore / @JsonInclude / @JsonView 仍在 com.fasterxml.jackson.annotation(Jackson 3 为向后兼容刻意保留),涉及 63 个文件一行未改。

批量脚本:tools/migrate_jackson3.py(可重复执行,--dry 只统计不写)。

2. 两个自定义序列化器改写

Jackson 3 把 JsonSerializer 更名 ValueSerializer,第三个参数换成 SerializationContext, 异常由受检的 IOException 改为非受检的 JacksonException:

// 旧
public class PhpFloatSerializer extends JsonSerializer<Double> {
    public void serialize(Double v, JsonGenerator gen, SerializerProvider p) throws IOException
// 新
public class PhpFloatSerializer extends ValueSerializer<Double> {
    public void serialize(Double v, JsonGenerator gen, SerializationContext ctxt) throws JacksonException
  • common/util/PhpFloatSerializer.java
  • common/util/UserLiteSerializer.java(另:new ObjectMapper().setSerializationInclusion(..) 不可用,改为 JsonMapper.builder().build();默认包含策略本就是 ALWAYS)

这两个类被 8 处 @JsonSerialize(using = ...) 引用,改完实体侧无需改动。

3. Redis 序列化器重写

config/RedisConfig.java:

  • new ObjectMapper() + setVisibility(..) + enableDefaultTyping(NON_FINAL) 全部不可用 (Jackson 3 的 mapper 不可变,这些方法已移除)。
  • 改用 Spring Data Redis 4 新增的 GenericJacksonJsonRedisSerializer:

    GenericJacksonJsonRedisSerializer.builder().enableUnsafeDefaultTyping().build()
    

    语义等价于原 GenericJackson2JsonRedisSerializer / default typing(写 @class 类型信息), RedisTemplate<String,Object> 与 RedisCacheManager 共用同一个工厂方法。

  • config/RedisConfigCacheManager.java 的 DEFAULT_PAIR 同步换成 RedisConfig.jsonSerializer()。

注:项目内 @Cacheable 用量为 0,缓存管理器实际未被业务使用,因此即便有旧缓存格式差异也不影响业务。

4. MyBatis-Plus 两处适配

  1. 分页插件拆包:MP 3.5.9 起 PaginationInnerInterceptor 移到独立模块,需显式引入 com.baomidou:mybatis-plus-jsqlparser(版本随 mybatis-plus.version)。 不加会报 cannot find symbol: class PaginationInnerInterceptor。
  2. JSON TypeHandler 换 Jackson 3 版:Goods.deliveryType 原来用 JacksonTypeHandler(Jackson 2 实现), Boot 4 不再带 Jackson 2,启动时会 NoClassDefFoundError: com/fasterxml/jackson/core/JacksonException。 改为 MP 3.5.17 提供的 Jackson3TypeHandler。

5. Lombok 注解处理器需显式声明

Boot 4 的 maven-compiler-plugin 3.15.0 不再从 classpath 自动发现注解处理器, 只配 <parameters>true</parameters> 时 @Data 完全不生成方法(一开始报了 200 个 "cannot find symbol: getXxx")。pom 里补:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <configuration>
    <annotationProcessorPaths>
      <path>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
      </path>
    </annotationProcessorPaths>
  </configuration>
</plugin>

三、不受影响的部分(已核实)

  • 时间格式:实体时间字段是 Integer 时间戳 + getCreateTimeText() 手工 TimeUtil.format, 不走 Jackson 日期序列化。Jackson 3 把 WRITE_DATES_AS_TIMESTAMPS 默认改为 ISO-8601 的变化 对本项目出参零影响,spring.jackson.date-format 保留即可。
  • @JsonView:spring.jackson.mapper.default-view-inclusion: true 在 Boot 4 仍有效 (已实测 goods/list 不含 content、goods/detail 含 content)。
  • spring.jackson.date-format / time-zone / mapper.*:配置项在 4.1.1 中均仍存在。
  • ObjectNode.remove(Collection) / createObjectNode() / valueToTree():签名未变,ApiView 只改了 import。
  • 多模块拦截器:WebMvcConfig / StoreAuthInterceptor / AdminAuthInterceptor / ApiAuthInterceptor 未改。
  • PHP $2y$ 口令:Spring Security 7 的 BCryptPasswordEncoder 仍能校验 (用 PHP 8.2 password_hash 生成 $2y$ 哈希实测登录成功)。

四、唯一的行为变化(可接受)

Jackson 3 默认开启 SORT_PROPERTIES_ALPHABETICALLY,实体经 valueToTree 后字段顺序变为字母序 (如 goodsId 之前排在 goodsName 前,现在 aloneGradeEquity 开头)。字段名与值不变, 前端按名取值不受影响;手工 put 的 ObjectNode 仍保持插入顺序。 旧的 compare_*.py 若按字节比 JSON 会误报,这些脚本已随驼峰改造废弃。

五、回归结果(全部在 Boot 4.1.1 上跑)

脚本 内容 结果
test_api_batch1.py api 只读接口 52 / 0
test_api_batch2.py 购物车/结算/订单/地址 97 / 0
test_api_batch3.py 用户中心/售后/充值/上传 99 / 0
test_api_batch4.py 登录/验证码/收银台/支付回调 77 / 0
test_admin_api.py 平台后台 45 / 0
test_token_user.py store 登录态(Redis) 20 / 0
smoke_camel.py 驼峰冒烟 全部通过

合计 390 项断言,0 失败。

六、回滚方式

git checkout develop          # Boot 3.5.16,随时可发布
# 或
git checkout feature/spring-boot-4

七、后续可选

  • Boot 4 仍保留 spring-boot-jackson2 模块(spring.jackson2.* 属性), 万一某个第三方库只支持 Jackson 2,可用它过渡,但属废弃路径,不建议长期依赖。
  • 若将来引入 @Cacheable,注意 Boot 4 + Jackson 3 的缓存值格式与 Jackson 2 的 GenericJackson2JsonRedisSerializer 不完全一致(@class vs 数组式 typing),切流时先清缓存。