背景:RestTemplate 越用越别扭
七月我们在预发环境试了 Spring 6.1 的里程碑版本(6.1 当时还没 GA,计划十一月随 Boot 3.2 一起),最让我眼前一亮的是 RestClient 和 HTTP Interface。以前用 RestTemplate,拼 URL、处理异常、解析响应处处是模板代码;WebClient 又太重,同步场景用着别扭。6.1 给了一个折中。
RestClient:流式 API 取代 RestTemplate
RestClient 是同步的、基于 ClientHttpRequestFactory 的客户端,但 API 是流畅风格,不用再 exchange 那种绕来绕去:
RestClient client = RestClient.create();
UserDto user = client.get()
.uri("https://api.internal/users/{id}", 1024)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.body(UserDto.class);
retrieve() 之后可以链式处理状态码和错误,比 RestTemplate 的 ResponseEntity 拆包清爽不少。异常也更明确——4xx/5xx 默认抛 RestClientResponseException,还能用 .onStatus(...) 自定义。
声明式 HTTP Interface:像写 Feign 一样
更香的是 HTTP Interface,把远程调用抽成接口,Spring 在启动时动态代理:
interface UserApi {
@GetExchange("/users/{id}")
UserDto getUser(@PathVariable("id") Long id);
@PostExchange("/users")
UserDto create(@RequestBody UserDto dto);
}
// 注册
@Bean
UserApi userApi(RestClient.Builder builder) {
return HttpServiceProxyFactory
.builderFor(builder.baseUrl("https://api.internal").build())
.build()
.createClient(UserApi.class);
}
调用方直接 userApi.getUser(1024),不用关心底层 HTTP 细节。这比 Feign 轻——没有独立的注解体系,直接复用 Spring 的 @GetExchange 等转换注解,且底层就是 RestClient,调试链路简单。
和老方案的取舍
- RestTemplate:没毛病但已进维护模式,新项目不建议再写。
- WebClient:异步响应式场景仍是首选;纯同步、想简单,RestClient 更合适。
- HTTP Interface:内部服务间同步调用、不想上 Feign 全家桶时很顺手。
实测:同样一个带重试的查询,RestTemplate 版 28 行,HTTP Interface 版接口声明 8 行 + 配置 6 行,且调用处彻底无模板代码。
下篇预告
这篇先把《Spring 6.1 的 RestClient 与 HTTP Interface》里的坑列了,下一篇写我们当时是怎么在线上工程里真正落地的——包括那次让领导拍桌的故障复盘。