1. 简介
RestClient 是 Spring Framework 6.1 M2 引入的同步 HTTP 客户端,用于取代 RestTemplate。同步 HTTP 客户端采用阻塞方式发送和接收 HTTP 请求与响应,即必须等待当前请求完成才能处理下一个请求。
本文将深入探讨 RestClient 的核心特性,并与 RestTemplate 进行对比分析。
2. RestClient 与 RestTemplate 对比
RestTemplate 采用模板方法设计模式,这种模式虽然强大,但会导致大量方法重载,使用起来不够灵活。
RestClient 通过流畅式 API (Fluent API) 解决了这个问题。流畅式 API 支持方法链式调用,使代码更简洁易读,且无需中间变量。
创建 RestClient 实例非常简单:
RestClient restClient = RestClient.create();
3. HTTP 请求方法基础操作
与 RestTemplate 类似,RestClient 支持所有标准 HTTP 方法进行资源操作。我们将通过一个简单的 Article 类演示各种操作:
public class Article {
Integer id;
String title;
// 构造方法和 getter
}
3.1. GET 方法获取资源
GET 方法用于从服务器获取数据而不修改资源,是只读操作的首选。
先看一个直接获取字符串响应的简单示例:
String result = restClient.get()
.uri(uriBase + "/articles")
.retrieve()
.body(String.class);
3.2. POST 方法创建资源
POST 方法用于向服务器提交数据创建新资源,常用于表单提交等场景。
URI 需明确指定要处理的目标资源。下面创建一个 ID 为 1 的文章:
Article article = new Article(1, "如何使用 RestClient");
ResponseEntity<Void> response = restClient.post()
.uri(uriBase + "/articles")
.contentType(APPLICATION_JSON)
.body(article)
.retrieve()
.toBodilessEntity();
由于设置了 APPLICATION_JSON
内容类型,Article 对象会自动通过 Jackson 序列化为 JSON。使用 toBodilessEntity()
忽略响应体,因为 POST 接口通常不返回有效负载。
3.3. PUT 方法更新资源
PUT 方法用于完整替换现有资源,适用于更新操作。
更新之前创建的文章(注意 URI 需包含资源 ID):
Article article = new Article(1, "如何更高效地使用 RestClient");
ResponseEntity<Void> response = restClient.put()
.uri(uriBase + "/articles/1")
.contentType(APPLICATION_JSON)
.body(article)
.retrieve()
.toBodilessEntity();
同样依赖 RestClient 自动序列化请求体并忽略响应。
3.4. DELETE 方法删除资源
DELETE 方法用于删除指定资源,通常通过 URI 参数标识目标资源:
ResponseEntity<Void> response = restClient.delete()
.uri(uriBase + "/articles/1")
.retrieve()
.toBodilessEntity();
4. 请求属性支持
RestClient 的请求属性机制与 WebClient 不同:WebClient 引入属性是为了解决响应式环境中线程局部变量不可靠的问题。而 RestClient 和 RestTemplate 可以依赖线程局部变量,因此很少需要请求属性。
不过在某些场景下仍需使用,例如向拦截器传递属性。Spring Framework 6.2 在 HttpRequest
接口中添加了 getAttributes()
方法:
@Test
void updateRequestAttribute() throws Exception {
String attrName = "attr1";
String attrValue = "value1";
assertDoesNotThrow(() -> {
ClientHttpRequestInterceptor interceptor = (request, body, execution) -> {
request.getAttributes().put(attrName, attrValue);
return execution.execute(request, body);
};
});
}
大多数情况下,我们更推荐通过 URI 构建器处理查询参数,而非使用请求属性 API:
RestClient restClient = RestClient.builder()
.baseUrl("https://api.example.com")
.build();
String pathVariable = "articles";
ResponseEntity response = restClient.get()
.uri(uriBuilder -> uriBuilder
.path("/" + pathVariable)
.queryParam("page", "1")
.queryParam("size", "10")
.build())
.header("Content-Type", "application/json")
.retrieve()
.toEntity(String.class);
5. 响应反序列化
RestClient 内置 JSON 与对象转换能力,底层由 Jackson 库驱动。同时支持 RestTemplate 的所有数据类型,因为它们共享消息转换器。
获取文章并反序列化为 Article 对象:
Article article = restClient.get()
.uri(uriBase + "/articles/1")
.retrieve()
.body(Article.class);
处理泛型类型(如 List<Article>
)时,需使用 ParameterizedTypeReference
:
List<Article> articles = restClient.get()
.uri(uriBase + "/articles")
.retrieve()
.body(new ParameterizedTypeReference<>() {});
6. 使用 Exchange 解析响应
exchange()
方法提供对底层 HTTP 请求/响应的完全控制,适用于复杂场景。此时不会应用默认处理器,需手动处理状态码。
假设服务在数据库无文章时返回 204 状态码,我们需要特殊处理:
List<Article> article = restClient.get()
.uri(uriBase + "/articles")
.exchange((request, response) -> {
if (response.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(204))) {
throw new ArticleNotFoundException();
} else if (response.getStatusCode().isSameCodeAs(HttpStatusCode.valueOf(200))) {
return objectMapper.readValue(response.getBody(), new TypeReference<>() {});
} else {
throw new InvalidArticleResponseException();
}
});
由于直接操作原始响应,需使用 ObjectMapper 手动反序列化响应体。
7. 错误处理
默认情况下,遇到 4xx/5xx 状态码时 RestClient 会抛出 RestClientException 子类异常。可通过自定义状态处理器覆盖此行为。
自定义 404 错误处理:
Article article = restClient.get()
.uri(uriBase + "/articles/1234")
.retrieve()
.onStatus(status -> status.value() == 404, (request, response) -> {
throw new ArticleNotFoundException(response);
})
.body(Article.class);
8. 从 RestTemplate 构建 RestClient
作为 RestTemplate 的继任者,RestClient 支持从现有 RestTemplate 实例创建,便于旧项目迁移:
RestTemplate oldRestTemplate;
RestClient restClient = RestClient.create(oldRestTemplate);
9. 总结
本文系统介绍了 Spring Boot 中 RestClient 的核心功能,作为 RestTemplate 的替代方案,它提供了更现代的流畅式 API。我们覆盖了:
- ✅ 基础 HTTP 方法操作
- ✅ 请求属性与 URI 构建
- ✅ 响应反序列化机制
- ✅ 高级响应处理(exchange)
- ✅ 自定义错误处理
- ✅ 从 RestTemplate 迁移方案
对于需要同步 HTTP 客户端的新项目,RestClient 是当前最佳选择。