从 Spring Boot 2 升到 3,我改了三天代码

举报
yd_241780069 发表于 2026/10/29 21:11:04 2026/10/29
【摘要】 起因项目还在 2.7.x,本来没打算动。直到有天收到安全扫描报告,说某个依赖在 2.x 上已经不维护了,建议升到 3.x。查了一下,Spring Boot 2.7 的开源支持到 2024 年 11 月就结束了,再拖下去连安全补丁都没了。行吧,升。原以为改改版本号的事,结果折腾了三天。 第一刀:javax 变 jakarta这是最直观也最烦人的改动。所有 javax.servlet.*、ja...

起因

项目还在 2.7.x,本来没打算动。直到有天收到安全扫描报告,说某个依赖在 2.x 上已经不维护了,建议升到 3.x。查了一下,Spring Boot 2.7 的开源支持到 2024 年 11 月就结束了,再拖下去连安全补丁都没了。

行吧,升。原以为改改版本号的事,结果折腾了三天。

第一刀:javax 变 jakarta

这是最直观也最烦人的改动。所有 javax.servlet.*、javax.persistence.*、javax.validation.* 的 import,全要换成 jakarta.*。

项目里几百个文件,手动改不现实。IDEA 有个批量替换功能,但得小心:有些 javax 开头的包跟 Jakarta EE 没关系(比如 javax.crypto),不能一刀切。我是先全局搜 import javax.,筛出 servlet、persistence、validation、annotation 这几个前缀的,再批量替换。改完编译报错少了一大半,剩下的才是真正的坑。

第二刀:MyBatis-Plus 的隐藏地雷

项目用的是 MyBatis-Plus,升完 Spring Boot 3.2 之后启动直接报:

Invalid value type for attribute 'factoryBeanObjectType': java.lang.String

查了半天,问题是 MyBatis-Plus 自带的 mybatis-spring 版本太低,跟 Spring 6 的 Bean 创建流程不兼容。解决方式是把依赖坐标换掉:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    <version>3.5.5</version>
</dependency>

注意 artifactId 里多了 spring-boot3。不是简单升个版本号就行的,坐标本身变了。这个坑如果不看报错日志,光靠猜能卡一整天。

第三刀:Security 配置全废了

老项目里 WebSecurityConfigurerAdapter 用得飞起,Spring Security 6 直接把这个类删了。所有继承它的配置类编译都过不去。

改成注册 SecurityFilterChain Bean 的方式:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/api/public/**").permitAll()
            .anyRequest().authenticated()
        )
        .csrf(csrf -> csrf.disable());
    return http.build();
}

写法跟以前完全两个风格,lambda 链式调用,得对着文档一条条迁。好在配置类不多,改了两个小时弄完了。

第四刀:Swagger 用不了了

之前用的 SpringFox,在 Spring Boot 3 下根本不工作。查了一下,SpringFox 已经不再维护,社区方案是换 SpringDoc。

依赖换掉:

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.3.0</version>
</dependency>

注解也得跟着换。@Api 变 @Tag,@ApiOperation 变 @Operation,@ApiModelProperty 变 @Schema。Controller 和实体类上几百个注解,又是一个批量替换的活。好在大部分是一对一映射,对着对照表改就行,不用动脑子,但费眼睛。

第五刀:时间序列化,最隐蔽的一个

前四刀都是编译期报错,改完就能跑。这个不一样,启动正常,接口也能调,但前端传过来的时间字符串反序列化失败,直接 400。

报错是 DateTimeParseException: Text '2024-06-15T10:30:00' could not be parsed at index 10。原因是 Spring Boot 3 的 Jackson 配置变了,旧版自动适配的 LocalDateTimeDeserializer 在新版里默认不生效了。得手动在字段上加 @JsonFormat,或者在全局配置里注册自定义的序列化器。

我选了全局配置,在 ObjectMapper 里统一注册 JavaTimeModule,省得每个实体类都写注解。

顺带提一下 Lombok

如果用的是 JDK 17,Lombok 版本得跟上。我项目里原来的版本太低,编译时报 NoSuchFieldError,升到 1.18.30 才消停。如果是 JDK 21 的项目,还得更高。这个不算 Spring Boot 本身的问题,但升级时很容易撞上。

改完之后

启动时间从原来的十几秒变成了二十多秒,可能是新版本加了东西,也可能是我本地环境的问题,暂时没深究。功能跑了一遍,核心链路都通,时间格式和 Swagger 文档确认没问题之后才算收工。

回头看,最耗时的不是技术难点,是批量改动的体力活。javax 换 jakarta、Swagger 注解替换,都是机械操作,但量大了就容易漏。建议升级前先把项目里的 javax.* 和 SpringFox 注解数量统计一下,心里有个数。

另外,别一次全升。我是先升到 3.0.x 跑通,再升 3.2.x。跨大版本直接跳,报错会叠在一起,排查起来分不清哪个是哪个的问题。


先记这些。如果你的项目还在 2.7,趁早动手,越拖改的东西越多。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。