Spring Framework 6.1 M2 引入了 RestClient
,一个新的同步HTTP客户端。顾名思义,RestClient
提供了 WebClient
的 fluent API和 RestTemplate
的基础架构。
14年前,当 RestTemplate
在 Spring Framework 3.0 中被引入时,我们很快发现在一个类似模板的类中暴露 HTTP 的所有功能会导致过多的重载方法。因此,在 Spring Framework 5 中,我们为响应式的 WebClient
使用了 fluent API。通过 RestClient
,我们引入了一个 HTTP 客户端,它提供了类似于 WebClient
的API,并使用了 message converter、request factory、拦截器以及 RestTemplate
的其他底层组件。
创建 RestClient
{#创建-restclient}
你可以使用静态的create
方法创建一个RestClient
。你也可以使用RestClient::builder
来获得一个具有更多选项的 builder,比如指定要使用的HTTP客户端,设置默认的URL、path 变量和 header,或者注册拦截器和初始化器(initializer)。
使用 RestClient::create(RestTemplate)
,你可以使用现有 RestTemplate
的配置初始化 RestClient
。
Retrieve {#retrieve}
让我们创建一个 RestClient
,用它来设置一个基本的 GET
请求,并使用 retrieve
以字符串形式获取网站的内容:
RestClient restClient = RestClient.create();
String result = restClient.get()
.uri("https://example.com")
.retrieve()
.body(String.class);
System.out.println(result);
如果你对响应状态码和 header 感兴趣,而不仅仅是对响应内容感兴趣,你可以使用 toEntity
获取 ResponseEntity
:
ResponseEntity<String> result = restClient.get()
.uri("https://example.com")
.retrieve()
.toEntity(String.class);
System.out.println("Response status: " + result.getStatusCode());
System.out.println("Response headers: " + result.getHeaders());
System.out.println("Contents: " + result.getBody());
RestClient
还可以使用 Jackson 将 JSON 转换为对象。事实上,它可以转换 RestTemplate
支持的所有类型,因为它使用了相同的 message converter。注意 uri 变量的使用,以及 Accept
header 被设置为 JSON。
int id = ...
Pet pet = restClient.get()
.uri("https://petclinic.example.com/pets/{id}", id)
.accept(APPLICATION_JSON)
.retrieve()
.body(Pet.class);
POST {#post}
POST
请求也很简单,就像这样:
Pet pet = ...
ResponseEntity<Void> response = restClient.post()
.uri("https://petclinic.example.com/pets/new")
.contentType(APPLICATION_JSON)
.body(pet)
.retrieve()
.toBodilessEntity();
错误处理 {#错误处理}
默认情况下,当接收到 4xx 或 5xx 状态码时,RestClient
会抛出 RestClientException
异常的子类。可以使用 status handler 重载该行为,如
String result = restClient.get()
.uri("https://example.com/this-url-does-not-exist")
.retrieve()
.onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders())
})
.body(String.class);
Exchange {#exchange}
RestClient
为更高级的场景提供了 exchange
方法,因为它提供了对底层 HTTP request 和 response 的访问。当你使用 exchange
时,前面提到的 status handler 不会被应用,因为 exchange
函数已经提供了对完整 response 的访问,允许你执行任何必要的错误处理:
Pet result = restClient.get()
.uri("https://petclinic.example.com/pets/{id}", id)
.accept(APPLICATION_JSON)
.exchange((request, response) -> {
if (response.getStatusCode().is4xxClientError()) {
throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders());
}
else {
Pet pet = convertResponse(response);
return pet;
}
});
支持 RestClient
{#支持-restclient}
RestClient
只是 Spring Framework 6.1 提供的 众多特性 之一。各种组件已经支持 RestClient
:你可以通过 MockRestServiceServer
测试其用法,或将其用作 @HttpExchange
接口 的后端。
此外,Spring Boot 3.2 M1 将包括对 RestClient
的支持。
参考:https://spring.io/blog/2023/07/13/new-in-spring-6-1-restclient