Spring Boot 2.x → 3.x 全链路迁移记录:javax→jakarta 与 Security 6 的 10 个坑
📌原创声明:本文基于本人课程实训期间独立开发的 CoolShark 微服务电商平台(Spring Cloud Alibaba)实战经验整理,为第一手踩坑记录,内容已脱敏。项目代码已开源:https://github.com/yunxuan4309/csmall
实战复盘 · 框架大版本升级
项目背景:微服务电商平台(8 个业务模块)从 Spring Boot 2.x 升级到 3.x,涉及 Jakarta EE 9+、Spring Security 6.x、MyBatis-Plus 新版本。本文记录了全链路迁移的踩坑清单。
一、坑 1:Servlet API 包名变更(javax → jakarta)
现象:编译报错Cannot resolve symbol 'ServletException'、Cannot resolve symbol 'HttpServletRequest'。
根因:Spring Boot 3.x 基于 Jakarta EE 9+,所有javax.*包名重命名为jakarta.*。
解决:
// 修复前importjavax.servlet.FilterChain;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;// 修复后importjakarta.servlet.FilterChain;importjakarta.servlet.ServletException;importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;涉及面:8 个模块的 SSOFilter、MyAccessDeniedHandler、MyAuthenticationEntryPoint、ResourceWebSecurityConfiguration 等 25+ 文件。
二、坑 2:WebSecurityConfigurerAdapter 已移除
Spring Security 6.x 移除了WebSecurityConfigurerAdapter,改为SecurityFilterChain Bean + Lambda DSL:
// 旧(5.x)http.csrf().disable();http.authorizeRequests().antMatchers("/public/**").permitAll();// 新(6.x)http.csrf(csrf->csrf.disable());http.authorizeHttpRequests(auth->auth.requestMatchers("/public/**").permitAll());其他关键变更:
@EnableGlobalMethodSecurity→@EnableMethodSecuritysetAllowedOrigins("*")→setAllowedOriginPatterns("*")http.sessionManagement().sessionCreationPolicy(...)→http.sessionManagement(session -> session.sessionCreationPolicy(...))
三、坑 3:Gateway + Knife4j 循环依赖
Knife4jSwaggerProvider使用@Autowired直接注入RouteLocator,形成循环依赖。
解决:使用ObjectProvider<RouteLocator>构造器注入 +getIfAvailable()延迟加载。
四、坑 4:MyBatis-Plus Starter 不兼容
- 必须用
mybatis-plus-spring-boot3-starter,不能用mybatis-plus-boot-starter - 分页插件:3.5.9 将分页插件移到独立模块,需额外添加
mybatis-plus-jsqlparser依赖 - 分页类型转换:
IPage<Model>无法直接转IPage<VO>,需手动 stream +convertToVO+ newPage<> - API 变更:
mapper.update(entity)→mapper.updateById(entity);selectCount()返回long不是int;代码生成器AutoGenerator→FastAutoGenerator
五、坑 5:实体类与数据库字段映射
@TableName 缺失
MyBatis-Plus 默认用类名转蛇形作为表名,如Spu→spu,但实际表名是pms_spu。为 25 个实体类添加@TableName注解。
is_ 前缀字段不匹配
MyBatis-Plus 将deleted映射为列deleted,但数据库实际列名是is_deleted。为 5 个字段添加@TableField注解。
pms_category 表结构不一致
Mapper XML 期望的字段(depth、keywords、enable)与数据库实际字段(level、is_parent、is_display)不匹配。
六、坑 6:SPU 测试数据不可见
init-test-data.sql中 SPU INSERT 未显式设置is_checked和is_deleted,默认 0 导致前端查询不到商品。解决:显式设置is_checked=1, is_deleted=0。
七、其他小坑汇总
| 问题 | 解决 |
|---|---|
org.apache.commons.lang.StringUtils找不到 | 改为org.apache.commons.lang3.StringUtils |
NacosRandomUtils不可用 | 改为ThreadLocalRandom |
MediaType.APPLICATION_JSON_UTF8废弃 | 直接用APPLICATION_JSON(RFC 8259) |
CORSsetAllowedOrigins("*")报错 | setAllowedOriginPatterns("*")+setAllowCredentials(true) |
| Long 精度丢失(雪花 ID 19 位) | 全局 Jackson 配置 Long → String 序列化 |
八、经验总结
- 大版本升级先列"受影响面清单":javax→jakarta、Security 6 的 API 变更波及 8 个模块 25+ 文件,提前梳理避免遗漏
- 编译错误只是第一关:JJWT 密钥长度、CORS 配置这类问题编译期不报,运行时才暴露,升级后必须全功能回归
- 框架升级往往伴随第三方库连锁升级:MyBatis-Plus、JJWT、Nacos 客户端都要同步适配
- 写清楚"旧→新"对照表:本文所有变更都以对照表形式记录,方便全局搜索替换和他人参考