Spring Boot 4.1.0-M3 于2026年3月20日发布,这是4.1系列的第三个里程碑版本,包含127项改进。本文将带你快速了解核心新特性,并掌握实战应用。
一、版本概览
Spring Boot 4.1.0-M3 带来了一系列令人兴奋的新特性:
| 特性 | 说明 | 重要程度 |
|---|---|---|
| Spring gRPC 支持 | 原生支持gRPC服务 | ⭐⭐⭐⭐⭐ |
| Log4j 日志轮转 | 原生日志文件轮转 | ⭐⭐⭐⭐ |
| OpenTelemetry 增强 | 可观测性升级 | ⭐⭐⭐⭐ |
| MongoDB Batch支持 | Spring Batch集成 | ⭐⭐⭐ |
| RabbitMQ Streams SSL | 安全增强 | ⭐⭐⭐ |
| AMQP 1.0 支持 | 消息协议扩展 | ⭐⭐⭐ |
本文将重点介绍 gRPC 、日志轮转 和 OpenTelemetry 三大核心特性。
二、Spring gRPC 原生支持
2.1 背景
在 Spring Boot 4.1 之前,我们需要:
- 手动引入
grpc-spring-boot-starter第三方库 - 复杂的配置和依赖管理
- 与Spring生态集成不够优雅
Spring Boot 4.1 带来了原生的 gRPC 支持,开箱即用!
2.2 快速开始
项目结构
bash
grpc-demo/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/com/xalgocapital/
│ │ │ ├── GrpcDemoApplication.java
│ │ │ ├── grpc/
│ │ │ │ └── HelloGrpcService.java
│ │ │ └── controller/
│ │ │ └── HelloController.java
│ │ ├── proto/
│ │ │ └── hello.proto
│ │ └── resources/
│ │ └── application.yml
│ └── test/
│ └── java/com/xalgocapital/
│ └── GrpcDemoApplicationTests.java
└── README.md
Maven 配置
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.0-M3</version>
<relativePath/>
</parent>
<groupId>com.xalgocapital</groupId>
<artifactId>grpc-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>grpc-demo</name>
<description>Spring Boot 4.1 gRPC Demo</description>
<properties>
<java.version>21</java.version>
<grpc.version>1.60.0</grpc.version>
<protobuf.version>3.25.1</protobuf.version>
</properties>
<dependencies>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-grpc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- gRPC -->
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>annotations-api</artifactId>
<version>6.0.53</version>
<scope>provided</scope>
</dependency>
<!-- Observability -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
<protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
<outputDirectory>${project.build.directory}/generated-sources/protobuf/java</outputDirectory>
<clearOutputDirectory>false</clearOutputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
Protobuf 定义
protobuf
// src/main/proto/hello.proto
syntax = "proto3";
package com.xalgocapital;
option java_package = "com.xalgocapital.grpc";
option java_multiple_files = true;
service HelloService {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
应用主类
java
// src/main/java/com/xalgocapital/GrpcDemoApplication.java
package com.xalgocapital;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GrpcDemoApplication {
public static void main(String[] args) {
SpringApplication.run(GrpcDemoApplication.class, args);
}
}
gRPC 服务实现
java
// src/main/java/com/xalgocapital/grpc/HelloGrpcService.java
package com.xalgocapital.grpc;
import io.grpc.stub.StreamObserver;
import net.devh.boot.grpc.server.service.GrpcService;
@GrpcService
public class HelloGrpcService extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void sayHello(HelloRequest request,
StreamObserver<HelloReply> responseObserver) {
String message = "Hello, " + request.getName() + "!";
HelloReply reply = HelloReply.newBuilder()
.setMessage(message)
.build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
REST 控制器(调用 gRPC)
java
// src/main/java/com/xalgocapital/controller/HelloController.java
package com.xalgocapital.controller;
import com.xalgocapital.grpc.HelloReply;
import com.xalgocapital.grpc.HelloRequest;
import com.xalgocapital.grpc.HelloServiceGrpc;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class HelloController {
@GrpcClient("hello-service")
private HelloServiceGrpc.HelloServiceBlockingStub helloStub;
@GetMapping("/hello/{name}")
public String hello(@PathVariable String name) {
HelloRequest request = HelloRequest.newBuilder()
.setName(name)
.build();
HelloReply reply = helloStub.sayHello(request);
return reply.getMessage();
}
}
应用配置
yaml
# src/main/resources/application.yml
server:
port: 8080
spring:
application:
name: grpc-demo
grpc:
server:
port: 9090
client:
hello-service:
address: static://localhost:9090
negotiation-type: plaintext
management:
endpoints:
web:
exposure:
include: health,info
logging:
level:
com.xalgocapital: DEBUG
2.3 运行测试
bash
# 编译项目
mvn clean compile
# 启动服务
mvn spring-boot:run
# 测试 gRPC(使用 grpcurl)
grpcurl -plaintext -d '{"name": "Tony"}' localhost:9090 HelloService/SayHello
# 输出:
# {
# "message": "Hello, Tony!"
# }
# 测试 REST API
curl http://localhost:8080/api/hello/Tony
# 输出:
# Hello, Tony!
三、Log4j 日志轮转
3.1 配置示例
xml
<!-- pom.xml 添加 Log4j2 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
yaml
# application.yml
logging:
log4j2:
roll:
enabled: true
max-size: 10MB
max-history: 7
total-size-cap: 1GB
pattern: "app-%d{yyyy-MM-dd}-%i.log.gz"
或者使用 XML 配置:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- src/main/resources/log4j2.xml -->
<Configuration status="WARN">
<Properties>
<Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
<RollingFile name="RollingFile"
fileName="logs/grpc-demo.log"
filePattern="logs/grpc-demo-%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="${LOG_PATTERN}"/>
<Policies>
<SizeBasedTriggeringPolicy size="10MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<DefaultRolloverStrategy max="7">
<Delete basePath="logs" maxDepth="1">
<IfFileName glob="grpc-demo-*.log.gz"/>
<IfLastModified age="7d"/>
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="com.xalgocapital" level="DEBUG" additivity="false">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Logger>
<Root level="INFO">
<AppenderRef ref="Console"/>
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
四、OpenTelemetry 增强
4.1 配置示例
yaml
# application.yml 添加 OpenTelemetry 配置
management:
tracing:
enabled: true
sampling:
probability: 1.0
propagation:
type: b3
baggage:
correlation:
enabled: true
remote-fields:
- userId
- tenantId
otlp:
tracing:
export:
enabled: true
url: http://localhost:4318/v1/traces
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
4.2 自定义追踪
java
// src/main/java/com/xalgocapital/grpc/TracedHelloGrpcService.java
package com.xalgocapital.grpc;
import io.grpc.stub.StreamObserver;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import net.devh.boot.grpc.server.service.GrpcService;
import org.springframework.beans.factory.annotation.Autowired;
@GrpcService
public class TracedHelloGrpcService extends HelloServiceGrpc.HelloServiceImplBase {
@Autowired
private Tracer tracer;
@Override
public void sayHello(HelloRequest request,
StreamObserver<HelloReply> responseObserver) {
Span span = tracer.spanBuilder("sayHello")
.setAttribute("request.name", request.getName())
.startSpan();
try (Scope scope = span.makeCurrent()) {
String message = "Hello, " + request.getName() + "!";
HelloReply reply = HelloReply.newBuilder()
.setMessage(message)
.build();
span.setStatus(StatusCode.OK);
span.setAttribute("response.message", message);
responseObserver.onNext(reply);
responseObserver.onCompleted();
} catch (Exception e) {
span.recordException(e);
span.setStatus(StatusCode.ERROR, e.getMessage());
throw e;
} finally {
span.end();
}
}
}
五、完整可运行示例
5.1 单元测试
java
// src/test/java/com/xalgocapital/GrpcDemoApplicationTests.java
package com.xalgocapital;
import com.xalgocapital.grpc.HelloReply;
import com.xalgocapital.grpc.HelloRequest;
import com.xalgocapital.grpc.HelloServiceGrpc;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
@ActiveProfiles("test")
class GrpcDemoApplicationTests {
@GrpcClient("hello-service")
private HelloServiceGrpc.HelloServiceBlockingStub helloStub;
@Test
void testSayHello() {
HelloRequest request = HelloRequest.newBuilder()
.setName("Test")
.build();
HelloReply reply = helloStub.sayHello(request);
assertNotNull(reply);
assertEquals("Hello, Test!", reply.getMessage());
}
}
yaml
# src/test/resources/application-test.yml
server:
port: 0
spring:
grpc:
server:
port: 0
client:
hello-service:
address: static://localhost:9090
negotiation-type: plaintext
5.2 启动并验证
bash
# 1. 编译
mvn clean package -DskipTests
# 2. 启动 Jaeger(可选,用于追踪可视化)
docker run -d --name jaeger \
-p 16686:16686 \
-p 4318:4318 \
jaegertracing/all-in-one:latest
# 3. 启动应用
java -jar target/grpc-demo-1.0.0-SNAPSHOT.jar
# 4. 测试 gRPC
grpcurl -plaintext -d '{"name": "World"}' localhost:9090 HelloService/SayHello
# 5. 测试 REST
curl http://localhost:8080/api/hello/World
# 6. 查看健康状态
curl http://localhost:8080/actuator/health
# 7. 查看追踪(如果启动了 Jaeger)
# 访问 http://localhost:16686
六、升级指南
6.1 版本要求
| 组件 | 最低版本 | 推荐版本 |
|---|---|---|
| Java | 17 | 21 |
| Spring Framework | 7.0 | 7.0 |
| Maven | 3.6+ | 3.9+ |
6.2 兼容性检查清单
- Java 17+ 环境
- 检查第三方依赖兼容性
- 更新废弃的 API 调用
- 测试 gRPC/消息队列集成
- 验证日志配置迁移
- 可观测性组件测试
七、总结
核心收获
- gRPC 原生支持 - 微服务通信更简单,告别第三方库
- 日志轮转 - 运维更方便,开箱即用
- OpenTelemetry 增强 - 可观测性更完善,分布式追踪更轻松
注意事项
- M3 是里程碑版本,不建议直接用于生产
- 提前在测试环境验证兼容性
- 关注后续 RC 版本和正式版发布
参考资源
- Spring Boot 4.1.0-M3 Release Notes
- Spring gRPC 官方文档
- OpenTelemetry Java Agent
- Spring Boot 4.1.0-M3 发布公告
本文首发于掘金,作者:Tony Zhang
关注我,持续分享 Java + AI 开发实战经验