spring3.5的本质改变

Spring Boot 3.5 在项目里「常用且本质」的变化,可以分成两类:必须改的底座,和日常开发会真正用到的能力。


一、项目里必须接受的 5 个本质改变

这些是 2.x → 3.x 的「换地基」,不处理就跑不起来或隐患很大。

1. Java 17 起步

复制代码
<!-- pom.xml -->
<properties>
    <java.version>17</java.version>
</properties>

项目影响:

  • 构建、CI、Docker 镜像都要升到 JDK 17+
  • 可以开始用 record、文本块、switch 表达式等
  • 还在 Java 8/11 的老项目,先升 JDK,再升 Spring Boot

2. javaxjakarta(改动面最大)

几乎凡是用到 Servlet、JPA、Validation、JAX-RS 的地方都要改:

复制代码
// 2.x
import javax.persistence.Entity;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
// 3.5
import jakarta.persistence.Entity;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.NotNull;

项目影响:

  • 业务代码、Filter、Interceptor、Entity 全要扫一遍
  • 第三方 jar 必须支持 Jakarta(老版 Swagger、部分工具包会卡住)
  • 这是迁移时 工作量最大 的一块

3. Spring Security 写法彻底换一套

2.x 常见写法:

复制代码
// 已废弃
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()...
    }
}

3.5 项目里标准写法:

复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            )
            .csrf(csrf -> csrf.disable())  // 纯 JWT API 常要显式处理
            .build();
    }
}

项目影响:

  • 所有安全配置类要重写
  • authorizeRequests()authorizeHttpRequests()
  • antMatchers()requestMatchers()

4. 持久层跟着 Hibernate 6 变

项目里常见变化:

复制代码
// 分页查询要显式写 countQuery(很多 2.x 项目会踩坑)
@Query(value = "SELECT u FROM User u WHERE u.status = :status",
       countQuery = "SELECT count(u) FROM User u WHERE u.status = :status")
Page<User> findByStatus(@Param("status") String status, Pageable pageable);

项目影响:

  • 实体映射、方言、时间类型、JSON 字段行为可能和 2.x 不一致
  • 启动后要多跑一轮 CRUD、分页、复杂查询回归
  • Flyway/Liquibase 脚本有时要适配新方言

5. 配置项和依赖版本整体换代

项目里要习惯的事:

复制代码
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.5.x</version>
</parent>
  • 很多 spring.* 配置项改名或语义收紧(3.5 里 .enabled 只认 true/false
  • Actuator 端点权限更严(如 heapdump 默认不开放)
  • Redis、Prometheus Pushgateway 等部分配置 key 有变化

升级时可临时加:

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-properties-migrator</artifactId>
    <scope>runtime</scope>
</dependency>

启动日志会提示哪些配置过时/无效。


二、3.5 项目里「日常真会用」的能力

这些是升到 3.x 后,新项目或重构时最常落地的,不是纸上谈兵。

1. 虚拟线程(高并发 I/O 项目很实用)

复制代码
spring.threads.virtual.enabled=true

适合:

  • 大量 HTTP 调用、RPC、数据库 I/O
  • 不想上 WebFlux,又想提高并发

项目本质:还是同步写法,但底层线程模型变了,少写一套响应式。

2. RestClient 替代 RestTemplate

复制代码
@Service
public class UserService {
    private final RestClient restClient;
    public UserService(RestClient.Builder builder) {
        this.restClient = builder.baseUrl("https://api.xxx.com").build();
    }
    public UserDTO getUser(Long id) {
        return restClient.get()
            .uri("/users/{id}", id)
            .retrieve()
            .body(UserDTO.class);
    }
}

项目本质:外部接口调用代码更简洁,新代码别再用 RestTemplate。

3. 声明式 HTTP Client(@HttpExchange

复制代码
@HttpExchange("/api/order")
public interface OrderClient {
    @GetExchange("/{id}")
    OrderDTO getById(@PathVariable Long id);
}

项目本质:轻量替代 Feign,适合内部服务调用,接口即客户端。


4. Docker Compose / Testcontainers(本地开发和测试)

复制代码
# compose.yaml
services:
  mysql:
    image: mysql:8
    ports: ["3306:3306"]

@SpringBootTest
@Testcontainers
class OrderServiceTest {
    @Container
    @ServiceConnection
    static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8");
}

项目本质:

  • 本地不用手启 MySQL/Redis/Kafka
  • 集成测试少写一堆 @DynamicPropertySource

5. 结构化日志(上云、接 ELK/Loki 几乎必备)

复制代码
logging.structured.format.console=ecs
logging.structured.format.file=logstash

项目本质:日志从「给人看」变成「给系统采集」,运维和排障方式变了。


6. 可观测性默认更强

复制代码
// 业务代码可挂 Observation
Observation.createNotStarted("order.create", registry)
    .observe(() -> orderService.create(dto));

配合:

  • Actuator
  • Micrometer
  • OpenTelemetry(3.5 对 OTEL_* 环境变量支持更好)

项目本质:监控不再全靠手写埋点,框架层统一了指标/链路接入方式。

7. 3.5 新增的「项目向」小改动

这些不华丽,但进项目后很实用:

能力 项目里干嘛用
@FilterRegistration / @ServletRegistration 注册 Filter/Servlet,少写 RegistrationBean
spring.config.import=env:XXX K8s/容器里一段环境变量导入多行配置
WebClient 全局超时配置 统一外部调用超时,不用每个 Client 手写
SSL Bundle + 证书指标 HTTPS 证书过期监控,生产环境很有用
Bean 后台初始化 大项目启动优化

三、落到项目结构上的「本质变化」

如果从 2.x 项目视角看,变化其实是这几层:

2.x 项目 3.5 项目

────────────────────────────────────────────────

Java 8/11 → Java 17+

javax 包 → jakarta 包

Security 继承 Adapter → SecurityFilterChain Bean

RestTemplate → RestClient / @HttpExchange

手写测试容器配置 → @ServiceConnection

普通线程池扛并发 → 可选虚拟线程

文本日志 → 结构化 JSON 日志

零散监控埋点 → Observation + Actuator 统一体系

本地手启中间件 → compose.yaml 自动管理

可以概括成一句话:

3.5 不是多几个注解,而是项目从「传统 Servlet + javax + 同步线程」切到「Jakarta + 现代 Java + 云原生运维」这一套。


四、如果你现在就要动一个老项目,优先改什么

按优先级:

  1. JDK 17
  2. javaxjakarta
  3. Security 配置重写
  4. Hibernate/JPA 回归测试
  5. 废弃配置清理(用 properties-migrator)
  6. 新代码开始用 RestClient / 结构化日志 / 虚拟线程

五、结合真实业务的判断

项目类型 3.5 最值得先上的
对外 API / 微服务 Jakarta 迁移 + Security + RestClient + 结构化日志
高并发查询服务 虚拟线程
重集成测试 Testcontainers + @ServiceConnection
金融/政企后台 SSL 证书监控 + Actuator 权限收紧
还在 2.7 维护态 先停在新功能,规划 2.7 → 3.0 迁移
相关推荐
kuonyuma2 小时前
MyBatis入门·注解操作
java·spring boot·mysql·spring·mybatis
我登哥MVP3 小时前
SpringCloud 核心组件解析:服务链路追踪
java·spring boot·后端·spring·spring cloud·java-ee·maven
夏天的味道٥5 小时前
Spring-AI 多模型接入实战:本地 deepseek + 阿里云百炼 + 硅基流动
人工智能·spring·阿里云
小刘|5 小时前
SpringAIAlibaba快速接入阿里云百炼
java·spring boot·spring·maven
Han.miracle5 小时前
Jackson 工具类详解:ObjectMapper 配置、泛型擦除、TypeReference 与 JavaType
java·spring boot·spring
我登哥MVP6 小时前
SpringCloud 核心组件解析:服务调用和负载均衡
java·spring boot·后端·spring·spring cloud·java-ee·负载均衡
swordbob6 小时前
Spring Bean 生命周期
开发语言·spring
摇滚侠6 小时前
SpringMVC 入门到实战 域对象共享数据 33-43
java·后端·spring·intellij-idea