SpringBoot4与Spring7新特性
版本演进概述
新一代框架的里程碑
2025年11月,Spring团队正式发布了Spring Framework 7.0和Spring Boot 4.0,这是继Spring 6和Spring Boot 3之后的又一次重大版本升级。此次更新带来了API版本控制、JSpecify空安全注解、内置弹性特性等革命性功能。
graph TB
A[Spring Framework 6] --> B[Spring Framework 7]
C[Spring Boot 3] --> D[Spring Boot 4]
B --> E[API版本控制]
B --> F[JSpecify空安全]
D --> G[Jackson 3迁移]
D --> H[模块化架构]
style B fill:#66ccff,rx:10,ry:10
style D fill:#66ccff,rx:10,ry:10
style E fill:#99ff99,rx:10,ry:10
style F fill:#99ff99,rx:10,ry:10
style G fill:#99ff99,rx:10,ry:10
style H fill:#99ff99,rx:10,ry:10核心更新一览
| 特性分类 | Spring Framework 7 | Spring Boot 4 |
|---|---|---|
| API版本控制 | 原生支持 | 自动配置 |
| 空安全 | JSpecify注解 | 全面集成 |
| 弹性特性 | @Retryable内置 | 开箱即用 |
| JSON处理 | Jackson 3支持 | 默认Jackson 3 |
| 模块化 | - | 自动配置模块化 |
| JDK支持 | JDK 17-25 | JDK 17-25 |
基线要求与依赖更新
JDK版本要求
Spring Framework 7保持JDK 17基线不变,同时全面拥抱JDK 25的所有新特性。这意味着开发者可以继续使用JDK 17,但建议升级到JDK 25以获得最佳体验。
graph LR
A[JDK 17] --> B[最低要求]
C[JDK 21] --> D[推荐版本]
E[JDK 25] --> F[完整支持]
style A fill:#ffcc99,rx:10,ry:10
style C fill:#99ccff,rx:10,ry:10
style E fill:#99ff99,rx:10,ry:10Jakarta EE 11基线
Spring Framework 7将Jakarta EE基线从版本9升级到版本11,带来以下变化:
graph TB
A[Jakarta EE 11] --> B[Servlet 6.1]
A --> C[WebSocket 2.2]
A --> D[Validation 3.1]
A --> E[Persistence 3.2]
B --> F[需要Tomcat 11]
D --> G[需要Hibernate Validator 9]
E --> H[需要Hibernate ORM 7.1]
style A fill:#66ccff,rx:10,ry:10
style B fill:#ff9999,rx:10,ry:10
style C fill:#ff9999,rx:10,ry:10
style D fill:#ff9999,rx:10,ry:10
style E fill:#ff9999,rx:10,ry:10重要变更:由于Undertow尚未兼容Servlet 6.1,Spring Boot 4暂时不支持Undertow作为内嵌Web服务器。
第三方依赖升级
| 依赖 | Spring Boot 3.x | Spring Boot 4.0 |
|---|---|---|
| Kotlin | 1.9.x | 2.2.20 |
| Tomcat | 10.1 | 11.0 |
| Jetty | 12.0 | 12.1 |
| Hibernate ORM | 6.x | 7.1 |
| Hibernate Validator | 8.x | 9.0 |
| Jackson | 2.x | 3.x |
| Kafka Client | 3.x | 4.1.0 |
| Flyway | 10.x | 11.11 |
| Mockito | 5.x | 5.20 |
| TestContainers | 1.x | 2.0 |
API版本控制
为什么需要API版本控制
在企业级应用中,API版本控制是常见需求:
- 向后兼容:保持老客户端正常工作
- 渐进式升级:新功能逐步发布
- 多版本并存:支持不同版本同时运行
- 废弃管理:规范化API废弃流程
graph TB
A[API版本控制需求] --> B[客户端升级]
A --> C[新功能发布]
A --> D[废弃旧API]
B --> E[保持兼容性]
C --> F[渐进式迭代]
D --> G[平滑过渡]
style A fill:#66ccff,rx:10,ry:10
style E fill:#99ff99,rx:10,ry:10
style F fill:#99ff99,rx:10,ry:10
style G fill:#99ff99,rx:10,ry:10四种版本控制策略
Spring Framework 7在Spring MVC和Spring WebFlux中原生支持四种版本控制策略:
graph TB
A[API版本控制策略] --> B[路径版本]
A --> C[请求头版本]
A --> D[查询参数版本]
A --> E[媒体类型版本]
B --> F["/api/v1/users"]
C --> G["X-API-Version: 1.1"]
D --> H["?version=1.1"]
E --> I["Accept: vnd.api.v1+json"]
style A fill:#66ccff,rx:10,ry:10
style B fill:#99ff99,rx:10,ry:10
style C fill:#99ff99,rx:10,ry:10
style D fill:#99ff99,rx:10,ry:10
style E fill:#99ff99,rx:10,ry:10路径版本控制
最常见的版本控制方式,将版本号放在URL路径中:
@RestController
@RequestMapping("/api")
public class UserController {
// v1版本接口
@GetMapping(path = "/users/{id}", version = "1")
public UserV1Response getUserV1(@PathVariable Long id) {
User user = userService.findById(id);
return new UserV1Response(user.getId(), user.getName());
}
// v2版本接口,返回更详细信息
@GetMapping(path = "/users/{id}", version = "2")
public UserV2Response getUserV2(@PathVariable Long id) {
User user = userService.findById(id);
return new UserV2Response(
user.getId(),
user.getName(),
user.getEmail(),
user.getCreatedAt()
);
}
}配置API版本策略:
@Configuration
public class ApiVersionConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer.usePathVersioning() // 使用路径版本
.defaultVersion("1") // 默认版本
.versionPrefix("v"); // 版本前缀
}
}请求示例:
# 请求v1版本
GET /api/v1/users/123
# 请求v2版本
GET /api/v2/users/123请求头版本控制
通过HTTP请求头传递版本号:
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@GetMapping(path = "/{id}", version = "1.0")
public OrderV1Response getOrderV1(@PathVariable Long id) {
return orderService.getOrderV1(id);
}
@GetMapping(path = "/{id}", version = "1.1")
public OrderV1_1Response getOrderV1_1(@PathVariable Long id) {
// v1.1版本添加了优惠信息
return orderService.getOrderV1_1(id);
}
}配置请求头版本策略:
@Configuration
public class ApiVersionConfig implements WebMvcConfigurer {
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer.useHeaderVersioning() // 使用请求头版本
.headerName("X-API-Version") // 自定义请求头名称
.defaultVersion("1.0");
}
}请求示例:
# 请求v1.0版本
GET /api/orders/123
X-API-Version: 1.0
# 请求v1.1版本
GET /api/orders/123
X-API-Version: 1.1API废弃处理
Spring Framework 7内置了符合RFC 9745规范的API废弃处理机制:
@RestController
@RequestMapping("/api/products")
public class ProductController {
// 标记为废弃的API
@GetMapping(path = "/{id}", version = "1", deprecated = true)
@Deprecated(since = "2.0", forRemoval = true)
public ProductV1Response getProductV1(@PathVariable Long id) {
return productService.getProductV1(id);
}
// 新版本API
@GetMapping(path = "/{id}", version = "2")
public ProductV2Response getProductV2(@PathVariable Long id) {
return productService.getProductV2(id);
}
}响应中会自动添加废弃信息:
HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 31 Dec 2025 23:59:59 GMT
Link: </api/v2/products/123>; rel="successor-version"客户端版本配置
使用ApiVersionInserter在客户端自动插入版本信息:
@Configuration
public class HttpClientConfig {
@Bean
public RestClient restClient(ApiVersionInserter inserter) {
return RestClient.builder()
.baseUrl("http://product-service")
.requestInterceptor(inserter)
.defaultHeader("X-API-Version", "2.0")
.build();
}
}
// 使用HTTP Interface定义客户端
@HttpExchange("/api/products")
public interface ProductClient {
@GetExchange("/{id}")
ProductResponse getProduct(@PathVariable Long id);
}JSpecify空安全注解
什么是JSpecify
JSpecify是由OpenJDK、Google、JetBrains、Broadcom(VMware)等共同参与的标准化空安全注解项目。Spring Framework 7全面采用JSpecify注解,提供编译时空安全检查。
graph TB
A[JSpecify联盟] --> B[OpenJDK]
A --> C[Google]
A --> D[JetBrains]
A --> E[Broadcom/VMware]
A --> F[Sonar]
style A fill:#66ccff,rx:10,ry:10
style B fill:#99ff99,rx:10,ry:10
style C fill:#99ff99,rx:10,ry:10
style D fill:#99ff99,rx:10,ry:10
style E fill:#99ff99,rx:10,ry:10
style F fill:#99ff99,rx:10,ry:10核心注解
Spring Framework 7提供以下空安全注解:
import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;
import org.jspecify.annotations.NullMarked;
// 类级别标记,表示该类中所有方法默认非空
@NullMarked
@Service
public class UserService {
// 参数和返回值默认非空
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
}
// 显式标记可空返回值
public @Nullable User findByEmail(String email) {
return userRepository.findByEmail(email).orElse(null);
}
// 显式标记可空参数
public List<User> searchUsers(@Nullable String keyword) {
if (keyword == null || keyword.isBlank()) {
return userRepository.findAll();
}
return userRepository.searchByKeyword(keyword);
}
}泛型与数组支持
JSpecify注解支持复杂类型场景:
@NullMarked
@Service
public class OrderService {
// 泛型类型注解
public List<@NonNull Order> findAllOrders() {
return orderRepository.findAll();
}
// 集合可能为空,但元素不为空
public @Nullable List<@NonNull OrderItem> findOrderItems(Long orderId) {
return orderRepository.findById(orderId)
.map(Order::getItems)
.orElse(null);
}
// 数组类型注解
public @NonNull String @Nullable [] getTags(Long orderId) {
// 数组可能为null,但数组元素不为null
return orderRepository.findTagsById(orderId);
}
}IDE与工具支持
graph TB
A[JSpecify生态] --> B[IntelliJ IDEA 2025.3]
A --> C[NullAway编译检查]
A --> D[Kotlin 2自动转换]
B --> E[完整数据流分析]
C --> F[编译时报错]
D --> G[Kotlin可空类型]
style A fill:#66ccff,rx:10,ry:10
style B fill:#99ff99,rx:10,ry:10
style C fill:#99ff99,rx:10,ry:10
style D fill:#99ff99,rx:10,ry:10IntelliJ IDEA配置:
IntelliJ IDEA 2025.3提供完整的JSpecify支持,包括:
- 复杂数据流分析
- 实时警告提示
- 快速修复建议
NullAway编译检查:
<plugin>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_core</artifactId>
<version>2.25.0</version>
</plugin>Kotlin自动转换:
// Kotlin 2自动识别JSpecify注解
class OrderController(private val orderService: OrderService) {
fun getOrder(id: Long): Order {
// 编译器知道findById不返回null
return orderService.findById(id)
}
fun searchOrders(keyword: String?): List<Order> {
// 编译器知道keyword可为null
return orderService.searchOrders(keyword)
}
}内置弹性特性
Spring Retry集成
Spring Framework 7将Spring Retry的核心功能集成到框架中,无需额外依赖即可使用重试和并发控制特性。
graph TB
A[Spring Framework 7弹性特性] --> B["@Retryable重试"]
A --> C["@ConcurrencyLimit并发控制"]
B --> D[声明式重试]
B --> E[指数退避]
B --> F[抖动策略]
C --> G[限流保护]
C --> H[虚拟线程优化]
style A fill:#66ccff,rx:10,ry:10
style B fill:#99ff99,rx:10,ry:10
style C fill:#99ff99,rx:10,ry:10@Retryable声明式重试
@Service
public class PaymentService {
@Retryable(
retryFor = {TransientException.class, TimeoutException.class},
maxAttempts = 3,
backoff = @Backoff(
delay = 1000, // 初始延迟1秒
multiplier = 2, // 指数倍数
maxDelay = 10000, // 最大延迟10秒
jitter = 0.1 // 10%抖动
)
)
public PaymentResult processPayment(PaymentRequest request) {
// 调用第三方支付接口
return paymentGateway.process(request);
}
@Recover
public PaymentResult recoverPayment(Exception e, PaymentRequest request) {
// 重试失败后的恢复逻辑
log.error("支付处理失败: {}", request.getOrderId(), e);
return PaymentResult.failed(request.getOrderId(), e.getMessage());
}
}重试流程时序图:
sequenceDiagram
participant C as 客户端
participant S as PaymentService
participant G as 支付网关
C->>S: processPayment(request)
S->>G: 第1次调用
G-->>S: 超时异常
Note over S: 等待1秒
S->>G: 第2次调用
G-->>S: 超时异常
Note over S: 等待2秒(指数退避)
S->>G: 第3次调用
G-->>S: 成功响应
S-->>C: 返回支付结果响应式重试支持
@Retryable自动适配响应式方法:
@Service
public class InventoryService {
@Retryable(maxAttempts = 3)
public Mono<Stock> checkStock(String productId) {
return webClient.get()
.uri("/inventory/{id}", productId)
.retrieve()
.bodyToMono(Stock.class);
}
@Retryable(maxAttempts = 3)
public Flux<Stock> checkBatchStock(List<String> productIds) {
return webClient.post()
.uri("/inventory/batch")
.bodyValue(productIds)
.retrieve()
.bodyToFlux(Stock.class);
}
}@ConcurrencyLimit并发控制
特别适合与虚拟线程配合使用的并发限制:
@Service
public class ReportService {
// 限制最多10个并发执行
@ConcurrencyLimit(10)
public Report generateReport(ReportRequest request) {
// 资源密集型操作
return reportGenerator.generate(request);
}
// 结合重试和并发控制
@Retryable(maxAttempts = 2)
@ConcurrencyLimit(5)
public ExportResult exportData(ExportRequest request) {
return dataExporter.export(request);
}
}并发控制流程:
graph TB
A[请求到达] --> B{并发数检查}
B -->|未超限| C[立即执行]
B -->|已超限| D[等待队列]
C --> E[业务处理]
D --> F{超时判断}
F -->|未超时| G[获取许可]
F -->|已超时| H[拒绝请求]
G --> E
E --> I[释放许可]
I --> J[返回结果]
style A fill:#66ccff,rx:10,ry:10
style C fill:#99ff99,rx:10,ry:10
style H fill:#ff9999,rx:10,ry:10Jackson 3迁移
主要变更
Spring Boot 4默认使用Jackson 3进行JSON处理,这是一个重大的破坏性变更。
graph TB
A[Jackson 3变更] --> B[包名变更]
A --> C[JsonMapper替代ObjectMapper]
A --> D[默认序列化行为]
B --> E[com.fasterxml.jackson → tools.jackson]
C --> F[不可变/线程安全]
D --> G[属性字母排序]
D --> H[日期ISO-8601格式]
style A fill:#66ccff,rx:10,ry:10
style B fill:#ff9999,rx:10,ry:10
style C fill:#99ff99,rx:10,ry:10
style D fill:#99ff99,rx:10,ry:10包名迁移
Jackson 2.x:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.core.JsonProcessingException;Jackson 3.x:
import tools.jackson.databind.JsonMapper;
import tools.jackson.databind.JsonNode;
import tools.jackson.core.JacksonException;JsonMapper替代ObjectMapper
Jackson 3推荐使用JsonMapper替代ObjectMapper:
@Configuration
public class JacksonConfig {
@Bean
public JsonMapper jsonMapper() {
return JsonMapper.builder()
.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.addModule(new JavaTimeModule())
.build();
}
}
@Service
public class OrderSerializer {
private final JsonMapper jsonMapper;
public OrderSerializer(JsonMapper jsonMapper) {
this.jsonMapper = jsonMapper;
}
public String serialize(Order order) throws JacksonException {
return jsonMapper.writeValueAsString(order);
}
public Order deserialize(String json) throws JacksonException {
return jsonMapper.readValue(json, Order.class);
}
}默认序列化行为变更
属性字母排序:
public class User {
private Long id;
private String name;
private String email;
private LocalDateTime createdAt;
}
// Jackson 3默认输出(按字母排序)
{
"createdAt": "2025-11-20T10:30:00",
"email": "user@example.com",
"id": 123,
"name": "张三"
}日期格式变更:
// Jackson 2默认:时间戳格式
{"createdAt": 1732096200000}
// Jackson 3默认:ISO-8601格式
{"createdAt": "2025-11-20T10:30:00"}兼容性策略
如需继续使用Jackson 2,可以进行配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>tools.jackson</groupId>
<artifactId>jackson-bom</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 使用Jackson 2 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>自动配置模块化
模块化架构
Spring Boot 4将单体的spring-boot-autoconfigure和spring-boot-test-autoconfigure JAR拆分为多个技术专用模块:
graph TB
A[Spring Boot 3.x] --> B[spring-boot-autoconfigure]
A --> C[spring-boot-test-autoconfigure]
D[Spring Boot 4.0] --> E[spring-boot-starter-webmvc]
D --> F[spring-boot-starter-data-jpa]
D --> G[spring-boot-starter-security]
D --> H[spring-boot-starter-webmvc-test]
D --> I[...]
style A fill:#ffcc99,rx:10,ry:10
style D fill:#99ff99,rx:10,ry:10
style E fill:#66ccff,rx:10,ry:10
style F fill:#66ccff,rx:10,ry:10
style G fill:#66ccff,rx:10,ry:10
style H fill:#66ccff,rx:10,ry:10模块化的优势
- 减少应用体积:只引入需要的模块
- IDE智能提示优化:不再提示未使用的类和配置
- 启动速度提升:减少类扫描范围
- 依赖更清晰:明确知道使用了哪些功能
模块使用示例
<!-- 只使用Web MVC功能 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<!-- Web MVC测试支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Kotlin序列化支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-kotlin-serialization-starter</artifactId>
</dependency>HTTP客户端增强
RestTemplate废弃计划
Spring Framework 7.1将废弃RestTemplate,推荐使用RestClient接口。Spring Framework 8将完全移除RestTemplate。
graph LR
A[Spring 7.0] --> B[RestTemplate正常使用]
B --> C[Spring 7.1]
C --> D[RestTemplate废弃]
D --> E[Spring 8.0]
E --> F[RestTemplate移除]
style B fill:#99ff99,rx:10,ry:10
style D fill:#ffcc99,rx:10,ry:10
style F fill:#ff9999,rx:10,ry:10RestClient使用
@Configuration
public class HttpClientConfig {
@Bean
public RestClient restClient(RestClient.Builder builder) {
return builder
.baseUrl("http://order-service")
.defaultHeader("Content-Type", "application/json")
.requestInterceptor((request, body, execution) -> {
// 添加认证头
request.getHeaders().setBearerAuth(getToken());
return execution.execute(request, body);
})
.build();
}
}
@Service
public class OrderClient {
private final RestClient restClient;
public OrderClient(RestClient restClient) {
this.restClient = restClient;
}
public Order getOrder(Long id) {
return restClient.get()
.uri("/orders/{id}", id)
.retrieve()
.body(Order.class);
}
public Order createOrder(CreateOrderRequest request) {
return restClient.post()
.uri("/orders")
.body(request)
.retrieve()
.body(Order.class);
}
}HTTP Interface Groups
新的HTTP Interface Groups允许批量配置HTTP Interface客户端:
@Configuration
public class HttpServiceConfig {
@Bean
public HttpServiceProxyRegistry httpServiceRegistry(RestClient.Builder builder) {
RestClient sharedClient = builder
.baseUrl("http://api-gateway")
.build();
return HttpServiceProxyRegistry.builder()
.registerGroup("orderServices", config -> {
config.httpClient(sharedClient);
config.addInterface(OrderClient.class);
config.addInterface(OrderItemClient.class);
})
.registerGroup("userServices", config -> {
config.httpClient(sharedClient);
config.addInterface(UserClient.class);
config.addInterface(AuthClient.class);
})
.build();
}
}
// 使用注册的接口
@Service
public class OrderService {
private final OrderClient orderClient;
private final UserClient userClient;
public OrderService(HttpServiceProxyRegistry registry) {
this.orderClient = registry.getClient(OrderClient.class);
this.userClient = registry.getClient(UserClient.class);
}
}RestTestClient
新增RestTestClient用于非响应式REST测试:
@SpringBootTest
@AutoConfigureRestTestClient
class OrderControllerTest {
@Autowired
private RestTestClient restTestClient;
@Test
void shouldGetOrder() {
restTestClient.get()
.uri("/api/orders/123")
.exchange()
.expectStatus().isOk()
.expectBody(Order.class)
.value(order -> {
assertThat(order.getId()).isEqualTo(123L);
assertThat(order.getStatus()).isEqualTo("CREATED");
});
}
@Test
void shouldCreateOrder() {
CreateOrderRequest request = new CreateOrderRequest("product-1", 2);
restTestClient.post()
.uri("/api/orders")
.bodyValue(request)
.exchange()
.expectStatus().isCreated()
.expectBody(Order.class)
.value(order -> {
assertThat(order.getProductId()).isEqualTo("product-1");
});
}
}可观测性增强
OpenTelemetry集成
Spring Boot 4新增spring-boot-starter-opentelemetry,提供开箱即用的OTLP指标和追踪导出:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-opentelemetry</artifactId>
</dependency>配置示例:
management:
otlp:
metrics:
export:
url: http://otel-collector:4318/v1/metrics
tracing:
export:
url: http://otel-collector:4318/v1/traces
tracing:
sampling:
probability: 1.0SSL健康检查
新增证书过期监控功能:
management:
health:
ssl:
enabled: true
certificate-validity-warning-threshold: 30d
endpoints:
web:
exposure:
include: health健康检查响应:
{
"status": "UP",
"components": {
"ssl": {
"status": "UP",
"details": {
"expiringChains": [
{
"alias": "server-cert",
"expiresIn": "25d",
"expiryDate": "2025-12-15T00:00:00Z"
}
]
}
}
}
}应用追踪示例
@RestController
@RequestMapping("/api/orders")
public class OrderController {
private final OrderService orderService;
private final ObservationRegistry registry;
@GetMapping("/{id}")
public Order getOrder(@PathVariable Long id) {
return Observation.createNotStarted("order.get", registry)
.lowCardinalityKeyValue("orderId", String.valueOf(id))
.observe(() -> orderService.findById(id));
}
}Spring Data AOT优化
编译时查询生成
Spring Data 2025.1支持在编译时生成仓库查询,显著提升启动速度:
graph TB
A[传统方式] --> B[运行时解析方法名]
B --> C[动态生成查询]
C --> D[启动时间长]
E[AOT方式] --> F[编译时解析方法名]
F --> G[预生成查询代码]
G --> H[启动时间短]
style A fill:#ffcc99,rx:10,ry:10
style E fill:#99ff99,rx:10,ry:10
style D fill:#ff9999,rx:10,ry:10
style H fill:#99ff99,rx:10,ry:10性能对比
| 指标 | 传统JIT | Spring Data AOT |
|---|---|---|
| 启动时间 | 3.2秒 | 1.0-1.5秒 |
| 提升比例 | 基准 | 50-70% |
使用方式
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
// 这些方法查询会在编译时生成
List<Order> findByCustomerId(Long customerId);
List<Order> findByStatusAndCreatedAtAfter(String status, LocalDateTime after);
@Query("SELECT o FROM Order o WHERE o.totalAmount > :amount")
List<Order> findHighValueOrders(@Param("amount") BigDecimal amount);
}启用AOT处理:
# Maven
mvn spring-boot:process-aot
# Gradle
gradle processAot其他重要更新
多因素认证
Spring Security 7引入多因素认证支持:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
)
.mfa(mfa -> mfa
.totpEnabled(true)
.recoveryCodesEnabled(true)
)
.build();
}
}JMS客户端增强
新增流式JmsClient API:
@Service
public class MessageService {
private final JmsClient jmsClient;
public void sendOrder(Order order) {
jmsClient.send("orders.queue")
.withMessage(order)
.withPriority(4)
.withTimeToLive(Duration.ofMinutes(30))
.execute();
}
public Order receiveOrder() {
return jmsClient.receive("orders.queue")
.withTimeout(Duration.ofSeconds(10))
.as(Order.class);
}
}Kafka共享消费者
Spring for Apache Kafka 4.0支持Kafka Queues的共享消费者:
@Configuration
public class KafkaConfig {
@Bean
public ConcurrentKafkaListenerContainerFactory<String, Order>
shareConsumerFactory(ConsumerFactory<String, Order> cf) {
ConcurrentKafkaListenerContainerFactory<String, Order> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(cf);
factory.getContainerProperties().setShareConsumer(true);
return factory;
}
}
@Service
public class OrderConsumer {
@KafkaListener(
topics = "orders",
containerFactory = "shareConsumerFactory"
)
public void processOrder(Order order) {
// 多个消费者共享分区中的消息
orderService.process(order);
}
}升级迁移指南
升级检查清单
graph TB
A[迁移检查清单] --> B[1. JDK版本确认]
A --> C[2. 依赖更新]
A --> D[3. 包名替换]
A --> E[4. Jackson迁移]
A --> F[5. 移除废弃API]
B --> G[JDK 17+]
C --> H[Spring Boot 4.0]
D --> I[javax → jakarta]
E --> J[ObjectMapper → JsonMapper]
F --> K[RestTemplate → RestClient]
style A fill:#66ccff,rx:10,ry:10
style G fill:#99ff99,rx:10,ry:10
style H fill:#99ff99,rx:10,ry:10
style I fill:#99ff99,rx:10,ry:10
style J fill:#99ff99,rx:10,ry:10
style K fill:#99ff99,rx:10,ry:10步骤一:更新依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.0</version>
</parent>步骤二:Jackson迁移
# 全局替换包名
find . -name "*.java" -exec sed -i '' \
's/com\.fasterxml\.jackson/tools.jackson/g' {} \;
# 替换ObjectMapper为JsonMapper
find . -name "*.java" -exec sed -i '' \
's/ObjectMapper/JsonMapper/g' {} \;步骤三:移除废弃API
// 移除javax.annotation包
// 旧代码
import javax.annotation.PostConstruct;
// 新代码
import jakarta.annotation.PostConstruct;
// RestTemplate迁移到RestClient
// 旧代码
@Autowired
private RestTemplate restTemplate;
// 新代码
@Autowired
private RestClient restClient;步骤四:使用OpenRewrite
<plugin>
<groupId>org.openrewrite.maven</groupId>
<artifactId>rewrite-maven-plugin</artifactId>
<version>5.45.0</version>
<configuration>
<activeRecipes>
<recipe>org.openrewrite.java.spring.boot3.UpgradeSpringBoot_4_0</recipe>
</activeRecipes>
</configuration>
</plugin>mvn rewrite:run常见问题
问题1:Undertow不可用
Caused by: java.lang.UnsupportedOperationException:
Undertow is not compatible with Servlet 6.1解决方案:切换到Tomcat或Jetty
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 默认使用Tomcat,无需额外配置 -->
</dependency>问题2:Jackson序列化变化
// 如需保持Jackson 2的日期格式
@Configuration
public class JacksonConfig {
@Bean
public JsonMapper jsonMapper() {
return JsonMapper.builder()
.enable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
.disable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
.build();
}
}问题3:JUnit 4不再支持
<!-- 移除JUnit 4 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- 使用JUnit 5 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>总结
Spring Boot 4和Spring Framework 7带来了众多革命性的新特性:
graph TB
A[Spring Boot 4 & Spring 7] --> B[API版本控制]
A --> C[JSpecify空安全]
A --> D[内置弹性特性]
A --> E[Jackson 3]
A --> F[模块化架构]
A --> G[HTTP客户端增强]
B --> H[规范化API演进]
C --> I[编译时空检查]
D --> J[声明式重试/限流]
E --> K[现代化JSON处理]
F --> L[按需引入依赖]
G --> M[RestClient/HTTP Interface]
style A fill:#66ccff,rx:10,ry:10
style H fill:#99ff99,rx:10,ry:10
style I fill:#99ff99,rx:10,ry:10
style J fill:#99ff99,rx:10,ry:10
style K fill:#99ff99,rx:10,ry:10
style L fill:#99ff99,rx:10,ry:10
style M fill:#99ff99,rx:10,ry:10这次升级标志着Spring生态系统向更现代化、更云原生的方向迈进,为Java开发者提供了更强大的工具和更优雅的开发体验。
更新: 2025-12-05 16:01:29
原文: https://www.yuque.com/u22210564/zoxfmt/ac612xsza02msfod