Spring Boot 2.7.18 升级到 3.4.5 的 历程记录及分析
一、升级点
模块 |
2.7.18 |
3.4.5 |
是否需手动改动 |
说明 |
Java 版本 |
Java 8 / 11 / 17 支持 |
必须 Java 17+ |
✅ 必须 |
Boot 3.x 强制要求 |
Spring Framework |
5.3.x |
6.1.x |
✅ 必须 |
包名变化、注解变化 |
Spring Security |
基于 WebSecurityConfigurerAdapter |
弃用该方式,改用 DSL API |
✅ 必须 |
代码大幅重构 |
JPA & Hibernate |
Hibernate 5.6 |
Hibernate 6.x |
✅ 必须 |
Query 语法变化 |
Java EE API |
javax.* |
全部替换为 jakarta.* |
✅ 必须 |
编译将直接失败 |
Swagger |
springfox (不兼容) |
推荐使用 springdoc-openapi |
✅ 推荐 |
springfox 无法兼容 Boot 3 |
二、修改点
1. Java EE → Jakarta 命名空间替换(最容易忽略)
旧的导入方式 |
替换为 |
javax.servlet.* |
jakarta.servlet.* |
javax.persistence.* |
jakarta.persistence.* |
javax.validation.* |
jakarta.validation.* |
javax.annotation.* |
jakarta.annotation.* |
javax.transaction.* |
jakarta.transaction.* |
注意事项:
- 不只是 import,还影响依赖和 classpath。
- JPA 实体、DTO Bean、拦截器、Servlet Filter、验证注解都要改。
- 有些注解包(如
@NotNull
)需引入 jakarta.validation-api
。
2. Spring Security 重构(踩坑最多)
❌ 被弃用的旧写法:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
✅ 新写法:基于 SecurityFilterChain
DSL 风格:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
}
踩坑提示:
authorizeRequests()
被移除 → 改为 authorizeHttpRequests()
- 不写
.build()
会报错
- 用户信息需要手动注册
UserDetailsService
或使用 JWT 等方式
3. Spring Data JPA + Hibernate 6 升级注意点
项目 |
修改建议或影响 |
javax.persistence.* |
✅ 替换为 jakarta.persistence.* |
Hibernate |
✅ 使用 Hibernate 6(Boot 自动引入) |
查询语法 |
HQL 更严格,必须使用 select 等全语法 |
命名参数 |
✅ 推荐 :paramName 替代 ?1 |
@JoinFetch 多级联表 |
结果映射更严格,DTO 投影推荐使用 |
❗ 容易出错的例子:
@Query("FROM User u WHERE u.name = :name")
应改为:
@Query("SELECT u FROM User u WHERE u.name = :name")
4. pom.xml
依赖调整(Spring Boot 3 专用依赖)
<properties>
<java.version>17java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
<dependency>
<groupId>jakarta.servletgroupId>
<artifactId>jakarta.servlet-apiartifactId>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.springdocgroupId>
<artifactId>springdoc-openapi-starter-webmvc-uiartifactId>
<version>2.5.0version>
dependency>
dependencies>
三、容易忽略 & 踩坑细节汇总
项目 |
踩坑说明 |
@RequestMapping 默认返回 |
Spring 6 开启了严格 Content Negotiation,建议显式加 @ResponseBody |
Actuator 权限 |
默认只开放 health 和 info ,需重新配置 management.endpoints.web.exposure.include=* |
单元测试 |
@WebMvcTest 类中静态嵌套类不能用了,需要调整结构 |
Jackson 与 Jakarta 注解兼容性 |
老版本 Jackson 不兼容 jakarta.annotation.* ,需升级 |
静态资源路径 |
/webjars/** 默认被拦截,需在 authorizeHttpRequests 中放行 |
四、升级后问题记录及解决
问题类型 |
升级后常见问题 |
原因分析与解决 |
编译失败 |
javax.* 无法识别 |
替换为 jakarta.* ,升级依赖包版本 |
安全配置异常 |
403 Forbidden /未授权 |
需使用新的 DSL 配置 Security |
JSON 转换错误 |
@JsonIgnore/@JsonProperty 无效 |
检查 Jackson 和 Jakarta 注解兼容性 |
单元测试异常 |
Spring BootTest 无法注入组件 |
检查 Bean 配置是否受包名变更影响 |
Swagger 报错 |
NoClassDefFoundError 等 |
Springfox 不支持,替换为 springdoc-openapi |
五、可使用的辅助工具
工具 |
功能 |
jdeps |
检测 javax 包使用情况 |
OpenRewrite |
自动重写 javax -> jakarta 、Spring Security DSL 升级 |
IDE Replace in Path |
快速重构 javax. 为 jakarta. |
Spring Migrator CLI |
官方实验性工具,用于 Boot 2→3 |