Spring Boot 4.1.0 深度拆解:gRPC 入列、SSRF 兜底、观测性补全
发布时间: 2026-06-10 基线: Spring Framework 7.0.8 | Spring Security 7.1 | JDK 17(基线)/ 21(解锁 jOOQ 3.20)
---
一、定位:不是推倒重来,是给 4.0 打补丁
Spring Boot 4.0(2025年11月)完成了 Jakarta EE 11 基线迁移、Jackson 3 升级、JSpecify 空值安全注解替换。那一波的迁移成本不低,很多团队到现在还在消化 javax.* → jakarta.* 的编译错误。
4.1.0 的定位很明确:不碰基线,补生产缺口。 官方 release notes 里没有任何架构层面的 Breaking Change,只有两类改动: 1. 新能力(gRPC、SSRF 防护、懒加载连接) 2. 4.0 废弃项的清理(Derby、layertools jar mode 等)
这意味着 4.0.x → 4.1.0 的升级路径是增量式的,不是 3.x → 4.0 那种"先编译爆掉再修"的体验。
---
二、gRPC 官方入列:从野路子到一等公民
之前的问题
在 4.1 之前,Spring Boot 里跑 gRPC 只有两条路:
- 手写 Netty 启动代码 + 手动注册 service + 自己配拦截器
- 依赖第三方 starter(最常用的是
grpc-spring-boot-starter)
4.1 的做法
官方直接提供了三个 starter:
<!-- 服务端 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-grpc-server</artifactId>
</dependency>
<!-- 客户端 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-grpc-client</artifactId>
</dependency>
核心注解:
@GrpcService:自动注册到 Netty / Servlet HTTP/2 传输层@GrpcClient("service-name"):从 Spring 配置注入 stub@GrpcAdvice+@GrpcExceptionHandler:统一异常处理,对标@RestControllerAdvice
ObservationGrpcServerInterceptor,Micrometer / OpenTelemetry 的 metrics 和 tracing 开箱即得。不需要手写拦截器去埋点。两种传输模式
| 模式 | 适用场景 |
|---|---|
| Standalone Netty | 纯 gRPC 服务,追求吞吐 |
| Servlet HTTP/2 | 已有 Servlet 容器(如 Tomcat),不想额外开端口 |
迁移注意
如果你之前用了 Spring gRPC 1.0(第三方),官方给了迁移指南到 Spring gRPC 1.1。主要变化是包名和配置前缀统一到 spring.grpc.*。
---
三、SSRF 防护:框架层兜底
背景
SSRF(Server-Side Request Forgery)一直是 Web 应用的高危漏洞。攻击者通过一个可被控制的 URL 参数,让服务端去请求内网资源(http://169.254.169.254/latest/meta-data/ 这种云厂商元数据地址是经典目标)。
以前的做法是在业务代码里自己写 Filter,或者依赖 WAF。问题在于:
- 每个项目重复造轮子
- 容易遗漏(比如重定向后的地址绕过了初筛)
4.1 的解法
框架层引入 InetAddressFilter,在 HTTP Client 发出请求前拦截:
spring:
http:
client:
ssrf:
enabled: true
deny-ip-subnets:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
- 127.0.0.0/8
- 169.254.0.0/16 # 链路本地地址(云元数据)
allow-ip-subnets:
- 192.168.1.0/24 # 白名单优先
逻辑顺序:先匹配白名单 → 再匹配黑名单 → 默认拦截未明确允许的地址。
这个 Filter 同时作用于:
RestClient(同步阻塞)WebClient(Reactive)
---
四、可观测性:OpenTelemetry 补完
环境变量对齐
4.1 支持读取标准的 OpenTelemetry 环境变量(OTEL_EXPORTER_OTLP_ENDPOINT、OTEL_EXPORTER_OTLP_TIMEOUT 等),与 OTel Java Agent 的配置方式保持一致。
这在容器化环境里很实用——运维侧统一配环境变量,不需要改 application.yml。
新增的开关和限制
management.opentelemetry.enabled:彻底关闭 OTel SDK,用 no-op 实现替代(之前想禁用得排除依赖)management.opentelemetry.tracing.sampler:配置采样率management.opentelemetry.tracing.limits.*/management.opentelemetry.logging.limits.*:配置 Span 和 Log 的大小限制- OTLP 指标导出支持 gzip 压缩(
management.otlp.metrics.export.compression-mode: gzip) - Micrometer 的
OtlpRegistry自动支持 exemplars(关联 trace 的指标样本)
观测约定自动装配
以下 Bean 现在会被自动探测并装配,不需要手动注册:
| 组件 | 自动装配的 Convention Bean |
|---|---|
| Kafka | KafkaListenerObservationConvention, KafkaTemplateObservationConvention |
| RabbitMQ | RabbitListenerObservationConvention, RabbitTemplateObservationConvention, RabbitStreamListenerObservationConvention, RabbitStreamTemplateObservationConvention |
| JVM 指标 | JvmMemoryMeterConventions, JvmThreadMeterConventions, JvmClassLoadingMeterConventions, JvmCpuMeterConventions |
五、数据访问:懒加载连接是亮点
LazyConnectionDataSourceProxy
新增配置:
spring:
datasource:
connection-fetch: lazy # 默认 eager
效果:DataSource 初始化时不会立刻从连接池拿物理连接,等到第一个 JDBC Statement 执行时才获取。
这在微服务场景下启动速度提升明显——很多服务启动时先执行各种 health check、schema validation,如果此时还不需要真正查库,懒加载能避免不必要的连接开销。
Derby 正式退休
Apache Derby 项目已宣布退役,Spring Boot 4.1 中将相关类标记为 @Deprecated:
DatabaseDriver.DERBYEmbeddedDatabaseConnection.DERBY
JPA Bootstrap 模式调整
spring.data.jpa.repositories.bootstrap-mode 的 deferred 和 lazy 模式行为有细化:
deferred:如果找不到合适的AsyncTaskExecutor,现在会抛异常(之前可能静默失败)lazy:不再设置 bootstrap executor,因为懒加载场景下通常不需要
六、构建与运维:一些务实的改进
Log4j 文件轮转
以前要手写 log4j2.xml 配置 RollingFileAppender,现在 YAML 里直接配:
logging:
log4j2:
file:
rotation:
strategy: size # 可选:size / time / size-and-time / cron
max-size: 100MB
max-history: 30
compression: gz
四种策略覆盖了大多数场景。运维侧不用再维护一份独立的 XML。
Maven Layers 从 Classpath 加载
自定义的 Docker layers 配置可以放在 META-INF/spring/layers/,作为插件依赖加载。这对多模块项目更友好——每个模块可以自带自己的分层策略。
Gradle bootBuildImage 支持命令行环境变量
./gradlew bootBuildImage --environment BP_JVM_VERSION=21
CI 流水线里动态指定构建参数更方便。
---
七、容易被忽略但实用的改动
@RedisListener 自动配置
Spring Data Redis 的 @RedisListener 注解现在可以自动装配,不需要手动配 RedisMessageListenerContainer。
@RedisListener(patterns = "user:*")
public void handleUserEvent(RedisMessage message) {
// 自动注册到默认容器
}
Spock 支持回归
Spock 2.4 支持 Groovy 5,Spring Boot 4.1 恢复了对 Spock 的自动配置支持。Groovy 测试栈的用户不用再卡在 3.x。
OAuth2 资源服务器增强
支持用 SpEL 表达式从 JWT 中提取 authorities:
spring:
security:
oauth2:
resourceserver:
jwt:
authorities-claim-expressions:
- "claims['roles']"
比之前的 authorities-claim-name 更灵活,可以处理嵌套结构。
Docker Compose 失败时自动输出日志
docker compose up 或 start 失败时,Spring Boot 会自动执行 docker compose logs 并把输出打到日志里(默认 INFO 级别)。本地开发调试时省了一个手动步骤。
Value Objects 绑定 Optional 参数
构造函数绑定的 @ConfigurationProperties 中,Optional 类型的参数现在绑定为 Optional.empty() 而不是 null。更类型安全,减少 NPE。
测试:@AutoConfigureWebServer
新增测试注解,可以在不启动完整 Spring 上下文的情况下注入嵌入式 web server factory bean。单元测试里测 web 层相关逻辑时启动更快。
---
八、升级前的检查清单
必须处理
| 项目 | 操作 |
|---|---|
| 4.0 废弃 API | mvn -DskipTests compile 检查所有 deprecation warning,全部替换 |
| jOOQ | 确认使用 Java 21+(jOOQ 3.20 的要求) |
| Derby | 迁移到 H2 / HSQL |
| Maven AOT 处理 | -DskipTests 不再跳过测试的 AOT 处理,改用 -Dmaven.test.skip |
建议评估
| 项目 | 说明 |
|---|---|
| RabbitMQ / AMQP | 部分变更推迟到 4.2,当前版本谨慎评估 |
| Reactor HTTP Client 默认代理 | proxyWithSystemProperties() 不再默认配置,如需恢复手动设置 |
| Spring Data JPA bootstrap-mode | deferred/lazy 行为有调整,确认是否符合预期 |
九、总结:谁该升,谁不急
建议直接升:
- 已有 4.0.x 项目 —— 增量升级,成本低,收益明确
- 计划引入 gRPC 的团队 —— 官方支持比第三方 starter 可靠
- 安全敏感型应用 —— SSRF 防护是框架层兜底,值得切
- 微服务架构 —— 懒加载数据源对启动速度有实打实的帮助
- 3.x 项目 —— 需要先完成 3.x → 4.0 的 Jakarta 迁移,再考虑 4.1
- 重度使用 jOOQ + JDK 17 —— 必须先把 JDK 升到 21
---
*参考:Spring Boot 4.1 Release Notes (github.com/spring-projects/spring-boot/wiki)* *#SpringBoot #Java #gRPC #SSRF #OpenTelemetry #小凯*
🌟 智谱 GLM-5 已上线
我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。
🎁 领取 2000万 Tokens