Spring Boot 3.x新特性学习笔记

前言

最近把项目升级到了Spring Boot 3.x,顺便记录一下升级过程中遇到的一些新特性和变化。其实升级还算顺利,就是有些依赖和配置调整了一下。

JDK版本要求

首先最明显的变化就是JDK版本要求了,Spring Boot 3.x最低要求JDK 17,基础也升级到了Jakarta EE 9

所以如果你的项目还在用JDK 8或者JDK 11,得先升级JDK版本

我用的JDK 17,感觉还不错,新版本的一些语法糖确实好用

依赖包变化

javax到jakarta的迁移

这个改动挺大的,所有的javax.*包都改成了jakarta.*

比如之前的:

1
2
3
import javax.servlet.http.HttpServletRequest;
import javax.persistence.Entity;
import javax.validation.constraints.NotNull;

现在要改成:

1
2
3
import jakarta.servlet.http.HttpServletRequest;
import jakarta.persistence.Entity;
import jakarta.validation.constraints.NotNull;

如果项目里用了大量的javax包,这个迁移工作量还挺大的。IDEA有自动替换功能,但是有些地方还是得手动改

我这边主要涉及的是Spring Security和Validation相关的注解

Spring Security 6的变化

Spring Security也跟着升级到了6.x,配置方式有一些调整

之前常用的WebSecurityConfigurerAdapter已经被彻底移除了

现在推荐使用基于组件的配置方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/user/login").anonymous()
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(exception -> exception
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler)
)
.cors(cors -> cors.configure(http));

return http.build();
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}
}

这种新的配置方式用的是Lambda DSL,写起来确实比之前简洁一些,但是刚开始看还有点不习惯

可观测性改进

Spring Boot 3.x在可观测性方面做了不少改进,整合了Micrometer Tracing

之前用Spring Cloud Sleuth做链路追踪,现在可以直接用Micrometer Tracing了

添加依赖:

1
2
3
4
5
6
7
8
<dependency>
<groupId io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-observation-registry</artifactId>
</dependency>

配置文件里添加:

1
2
3
4
5
6
7
management:
tracing:
sampling:
probability: 1.0 # 采样率
zipkin:
tracing:
endpoint: http://localhost:9411/api/v2/spans

这样就能自动追踪请求链路了,挺方便的

AOT编译和GraalVM

Spring Boot 3.x支持AOT(Ahead-of-Time)编译和GraalVM原生镜像

这个功能可以让应用启动更快,内存占用更少

不过我暂时还没在生产环境用,毕竟GraalVM的兼容性还有待验证,有些反射和动态代理的场景可能会出问题

如果要尝试原生镜像,可以添加依赖:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aot</artifactId>
</dependency>

然后用命令构建:

1
mvn -Pnative native:compile

构建出来的可执行文件启动确实快,从我测试来看,启动时间从2秒左右降到了不到100ms

配置属性的变化

有些配置属性的名称也变了

比如之前配置DataSource:

1
2
3
4
5
6
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver

现在url改成了jdbc-url

1
2
3
4
5
6
spring:
datasource:
jdbc-url: jdbc:mysql://localhost:3306/test
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver

不过旧的url属性还能用,只是会有个警告提示

其他小改动

Actuator路径变化

有些actuator的端点路径变了:

  • /actuator/httptrace 改成了 /actuator/httpexchanges
  • /actuator/caches 的响应格式也有调整

LocalDate支持

@DateTimeFormat注解现在支持java.time类型了,不用再自己写转换器

1
2
3
4
5
6
7
8
9
@RestController
public class UserController {

@GetMapping("/users")
public List<User> getUsers(
@RequestParam @DateTimeFormat(iso = ISO.DATE) LocalDate date) {
// ...
}
}

总结

总的来说,Spring Boot 3.x的升级还算平滑,主要就是:

  1. JDK版本要求提升到了17
  2. javax包名迁移到jakarta
  3. Spring Security配置方式改变
  4. 可观测性增强
  5. 支持GraalVM

建议升级前先做充分测试,尤其是涉及到一些底层框架或者第三方依赖的部分

我这次升级还算顺利,就是花了点时间改包名和Security配置。升级完之后,感觉性能和可维护性都有提升,还是值得的

暂时就先记录这么多,后面如果遇到其他坑再补充