Boot4升后WebClient starter怎么换
升到 Spring Boot 4 之后,不少团队会撞上同一类启动失败:业务代码里照旧注入 WebClient.Builder,结果容器里根本没有这个 bean,直接抛出 NoSuchBeanDefinitionException。或者只加了 spring-boot-starter-webmvc,却指望 RestClient、RestTemplate 的自动配置还像以前一样「跟着 Web 栈一起白送」。根因通常不是业务写法突然错了,而是 HTTP 客户端自动配置从「跟着服务端 starter 传递」改成了「显式声明客户端 starter」。
本文只讲 starter / 依赖怎么换、怎么验 。retrieve、exchange、错误处理等 API 迁移动线,见已发文 166986622(RestTemplate→RestClient 写法主文);Jackson3、Flyway、probes 等其它 Boot4 升级坑,分别见 167872166、167764600、167981493,本稿一句带过、不展开。读完你应能:对照表选对 starter、改测试侧依赖与包名、用「加/去/再加回」三步把失败钉死在缺依赖上。
现象:缺 starter,Builder 就不在了
最常见的日志形态是:
text
NoSuchBeanDefinitionException: No qualifying bean of type
'org.springframework.web.reactive.function.client.WebClient$Builder' available
Imperative 侧也可能表现为:工程里明明有 webmvc,却发现 RestClient.Builder 没有按预期自动配置出来;或者集成测试里突然拿不到以前「默认就有」的测试客户端。升级周报里这类问题很容易被误判成「配置类写错了」「Profile 没激活」,排查半天才发现:pom 里根本没有客户端 starter。
Boot 4 的模块化策略下,仅有 Web 服务端 starter,不再等价于「客户端自动配置也齐了」 。要客户端,就显式声明客户端 starter。官方参考文档仍说明:有相应自动配置时,Boot 会创建并预配置原型 WebClient.Builder / RestClient.Builder,建议注入后再 build()。结合 Migration Guide,前提变成:先有对应的 webclient / restclient starter(或模块) ,不能指望只靠 starter-webmvc「白送」客户端自动配置。
把现象写进升级 checklist 很有用:「启动失败且堆栈点名 WebClient.Builder / 测试缺 TestRestTemplate → 先查客户端 starter,再查业务配置。」
Migration 对照表:WebClient 与 RestClient 怎么选
Spring Boot 4.0 Migration Guide「Web Client Starters」给出了清晰对照(以官方 wiki 为准,页面曾于 2026-06-28 编辑):
| 技术 | 主依赖(starter) | 测试(starter) |
|---|---|---|
Imperative:RestClient / RestTemplate |
spring-boot-starter-restclient |
spring-boot-starter-restclient-test |
Reactive:WebClient |
spring-boot-starter-webclient |
spring-boot-starter-webclient-test |
决策口诀可以压成三句:
- 要 Reactive
WebClient→ 加spring-boot-starter-webclient - 要 Imperative
RestClient/RestTemplate自动配置 → 加spring-boot-starter-restclient - client-only 场景:不要再整包拉一个
starter-webflux「只当 HTTP 客户端」;webflux starter 在 Web Starters 行的定位是反应式服务端栈,模块化后客户端应走上表显式 starter
Maven 示例(版本号跟 parent / BOM,正文只写 artifactId,勿锁死某个 patch):
xml
<!-- Reactive:WebClient -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webclient</artifactId>
</dependency>
<!-- Imperative:RestClient / RestTemplate -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-restclient</artifactId>
</dependency>
测试侧成对出现更清晰,例如:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webclient-test</artifactId>
<scope>test</scope>
</dependency>
Gradle 同理,把 artifactId 换成上表对应 starter 即可。两个 starter 按实际技术选型选一个主路径,不要「两个都加以防万一」------依赖树只会更糊,排障更费时间。
非 starter 模块:一句边界
若不走 starter、只想挂模块:Migration Guide Modules 表对应 spring-boot-webclient / spring-boot-restclient(及 -test)。多数应用团队继续用 starter 更省事;模块坐标留给需要精细裁剪依赖树、或已经自管传递依赖的场景。实践上优先 starter;提模块只为边界完整。
Boot3 传递依赖 → Boot4 显式 starter
下面这张决策流把「选哪个 starter、测不测、验不验」串在一起,方便贴进内部升级文档:

记忆点只有一条:Boot4 不再把客户端自动配置绑死在「只要起了 Web」上;要哪种客户端,就声明哪种 starter。从 Boot3 迁过来时,最容易踩的坑正是「以前碰巧传递进来了,Boot4 切模块后没了,却还按老习惯排业务配置」。
业务侧怎么验:加 → 去 → 再加回
验法刻意做成可复现三步,方便写进 MR 与升级 checklist。目标不是证明「业务调用下游成功」,而是证明 Builder bean 是否由自动配置提供。
第一步:加 starter。 依赖里加入 spring-boot-starter-webclient(或 restclient),启动后注入:
java
@Service
public class DownstreamCaller {
private final WebClient webClient;
public DownstreamCaller(WebClient.Builder builder) {
this.webClient = builder.baseUrl("https://example.invalid").build();
}
}
能正常启动、且构造注入 / @Autowired WebClient.Builder 不报缺 bean,即主路径通过。RestClient.Builder 同理,换成 spring-boot-starter-restclient。
第二步:故意去掉依赖。 从 pom / Gradle 里删掉该 starter,重启------应重新出现 NoSuchBeanDefinitionException(或等价缺 bean)。这能证明失败与 starter 缺失直接相关,而不是偶发 Profile、条件注解或自写 @Bean 冲突。
第三步:再加回。 恢复 starter,启动恢复成功。把「删依赖复现 → 加回恢复」写进 MR 描述,后续同事复查成本最低,也避免「修了一堆无关配置碰巧好了」的假象。
再次强调:这里只验证 Builder 是否由自动配置提供 。具体请求怎么写、超时怎么配、怎么从 RestTemplate 迁到 RestClient API,仍以 166986622 为准,本稿不重复,也不展开 Builder 级 timeout 配置(另文/另线处理)。
测试侧:@SpringBootTest 不再白送
Migration Guide 专节写得很直:使用 @SpringBootTest 将不再提供任何 WebClient 或 TestRestTemplate bean 。升 Boot4 后集成测试「突然没有 TestRestTemplate / WebClient」------先查依赖与注解 ,不要先怀疑业务 @Configuration。这和主工程缺 starter 是同一条模块化逻辑:测试客户端也从「注解一贴就有」变成「显式依赖 + 显式自动配置注解」。
TestRestTemplate 要加什么
按官方「TestRestTemplate Failures」口径,缺一不可:
- 测试依赖:
org.springframework.boot:spring-boot-resttestclient - 运行时还需要:
org.springframework.boot:spring-boot-restclient - 测试类加:
@AutoConfigureTestRestTemplate - 包名迁到 :
org.springframework.boot.resttestclient.TestRestTemplate(从旧包迁出;@AutoConfigureTestRestTemplate在org.springframework.boot.resttestclient.autoconfigure)
java
import org.springframework.boot.resttestclient.TestRestTemplate;
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureTestRestTemplate
class OrderApiIT {
// 注入 org.springframework.boot.resttestclient.TestRestTemplate
}
编译期最容易漏的是 旧 import 没改 :IDE 可能还残留旧包路径,导致「依赖加了、注解加了,类型却解析不到」。以 4.0 API 文档包名为准即可。测试 starter 也可对照表使用 spring-boot-starter-restclient-test / spring-boot-starter-webclient-test,与主 starter 成对出现,依赖意图更清晰。
可选:RestTestClient(一句)
若团队愿意换新测试客户端,可考虑 RestTestClient + @AutoConfigureRestTestClient。这与本稿「starter 怎么换」主线无关,点到为止即可,不必扩成测试客户端选型长文。
升级周常见误判(对照表外的坑)
现场排障时,缺 starter 经常被其它噪音盖住。下面几条是周报里反复出现、却和对照表无关的误判,写出来是为了少绕路:
误判一:先改业务 @Bean。 看到 NoSuchBeanDefinitionException,有人立刻手写一个 WebClient.Builder @Bean「顶上」。短时能启动,但等于绕过 Boot 预配置的原型 Builder(编解码、消息转换器等自动装配链路也会一并绕开)。正确顺序应是:先加官方 starter,确认自动配置上了;只有在确有定制需求时,再在 已有自动配置 之上做定制,而不是用裸 Builder 顶替缺失的 starter。
误判二:把 webmvc 当万能依赖。 「主工程是 MVC,客户端也应该跟着有」在 Boot3 传递依赖较松时偶尔碰巧成立,Boot4 模块化后不再成立。webmvc 解决的是 服务端 Web ;WebClient / RestClient 自动配置要单独买单。混用 MVC 服务端 + WebClient 出站时,两边 starter 都要在依赖树里看得见。
误判三:测试绿了就以为主工程也齐了。 有的仓库测试里碰巧拉了 ...-webclient-test / resttestclient,主工程却漏了 spring-boot-starter-webclient。结果是 CI 集成测试通过、生产或本地主启动仍炸。验法必须覆盖 主 classpath :用业务 @Service 注入 Builder 做一次启动验,不要只看测试模块。
误判四:只改 test scope、忘了运行时模块。 TestRestTemplate 文档写明:除 spring-boot-resttestclient 外,还需要运行时依赖 spring-boot-restclient。只加测试坐标、漏了 restclient,会出现「注解加了仍注入失败」的假象。对照 checklist 逐项勾,比凭感觉加依赖稳。
把这四条和上一节「加 → 去 → 再加回」合在一起,升级 MR 里基本能自证:失败可复现、修复可归因、没有顺手塞无关 @Bean。
FAQ
Spring Boot 4 为什么注入 WebClient.Builder 会失败?
缺 spring-boot-starter-webclient(或模块 spring-boot-webclient)时,对应自动配置不会上,原型 WebClient.Builder bean 就不存在。堆栈点名 Builder 时,优先查依赖表,而不是先改业务 @Bean。
webclient 和 restclient 两个 starter 怎么选?
Reactive 用 webclient;Imperative 的 RestClient / RestTemplate 用 restclient。按调用栈技术选型选一个主路径;混用两套客户端时,两边 starter 都要显式声明,但那是架构选择问题,不是「随便加一个就能顶替」。
还能不能用 starter-webflux 只当 HTTP 客户端?
client-only 应显式 spring-boot-starter-webclient。webflux starter 是反应式 Web 服务端栈,不是「只要客户端」的推荐替代。Boot4 模块化的目的之一,就是把这类「整包当客户端」的模糊依赖收干净。
测试里 TestRestTemplate / WebClient 要额外加什么?
@SpringBootTest 不再白送。TestRestTemplate:@AutoConfigureTestRestTemplate + spring-boot-resttestclient + spring-boot-restclient,并改新包名。WebClient 测试侧对齐 ...-webclient-test 等对照表。漏注解或漏运行时 restclient 依赖,都会表现为「测试起不来 / 注入失败」。
小结 checklist
- 主工程:WebClient →
spring-boot-starter-webclient;RestClient/RestTemplate →spring-boot-starter-restclient - 测试:成对加
...-webclient-test/...-restclient-test(或按文档加模块坐标) - 集成测试:确认不再假设
@SpringBootTest白送 WebClient / TestRestTemplate - TestRestTemplate:注解 +
resttestclient依赖 + 新包名org.springframework.boot.resttestclient.TestRestTemplate - 验法:加 starter 能注入 Builder;去掉依赖复现失败;再加回恢复
- 不把本文当成 RestClient API 教程;不与 probes / Jackson3 / Flyway 升级文抢主线
按表换依赖、用「删依赖复现」验一遍,这类 Boot4 启动失败通常很快闭环。升级周报贴上对照表和三步验法,比事后口头解释「怎么突然没 bean 了」高效。