Administrator
发布于 2023-07-07 / 3786 阅读
27

Spring 6.1 的 RestClient 与 HTTP Interface

背景: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》里的坑列了,下一篇写我们当时是怎么在线上工程里真正落地的——包括那次让领导拍桌的故障复盘。

参考