目录
Spring RestClient VS RestTemplate
RestClient 与 RestTemplate 性能对比?
四种方式调用REST接口(RestClient、WebClient、RestTemplate、HTTP Interface)
Spring Framework 提供了以下调用 REST 端点的选择:
RestClient- 具有流畅 API 的同步客户端。
WebClient- 具有流畅 API 的非阻塞、反应式客户端。
RestTemplate- 具有模板方法 API 的同步客户端。
HTTP 接口- 带有生成的动态代理实现的注释接口。
1、背景介绍
在Spring生态系统中,HTTP客户端一直是一个重要的组件。从最早的RestTemplate,到WebClient,再到现在的RestClient,每一次演进都带来了更好的开发体验。Spring Boot 3.4版本在HTTP客户端支持方面带来了重大更新,这些更新不仅提供了更多的选择,还大大简化了配置过程。
2、HTTP客户端架构的演进
历史回顾
RestTemplate时代(Spring 3.0+)
- RestTemplate时代(Spring 3.0+)
- 同步阻塞式API
- 基于传统的Java模式
- 配置相对复杂
- WebClient时代(Spring 5.0+)
- 响应式非阻塞API
- 支持响应式编程
- 需要引入额外的响应式依赖
- RestClient时代(Spring 6.1+)
- 现代化同步API
- 流畅的链式调用
- 更简单的配置方式
Spring Boot 3.4的重大变化
在Spring Boot 3.4中,新增了对使用Reactor Netty的HttpClient和JDK HttpClient的自动配置支持。现在支持的客户端按优先顺序排列如下:
- Apache HTTP Components
- 实现类:HttpComponentsClientHttpRequestFactory
- 特点:功能最完整,支持高级特性
- 适用场景:企业级应用,需要高度定制化
- Jetty Client
- 实现类:JettyClientHttpRequestFactory
- 特点:轻量级,性能优秀
- 适用场景:中小型应用,追求性能
- Reactor Netty HttpClient
- 实现类:ReactorClientHttpRequestFactory
- 特点:支持响应式编程,异步处理能力强
- 适用场景:需要处理大量并发请求
- JDK HttpClient
- 实现类:JdkClientHttpRequestFactory
- 特点:JDK原生支持,无需额外依赖
- 适用场景:简单应用,追求轻量级
- Simple JDK HttpURLConnection
- 实现类:SimpleClientHttpRequestFactory
- 特点:最基础的实现,功能有限
- 适用场景:简单测试,原型开发
配置体系详解
基础配置
# 选择HTTP客户端实现
spring.http.client.factory=reactor# 可选值说明:
# http-components:使用Apache HTTP Components
# jetty:使用Jetty Client
# reactor:使用Reactor Netty
# jdk:使用JDK HttpClient
# simple:使用简单的HttpURLConnection
重定向处理配置
# 重定向策略配置
spring.http.client.redirects=dont-follow# 其他相关配置
spring.http.client.max-redirects=5 # 最大重定向次数
spring.http.client.connect-timeout=5000 # 连接超时(毫秒)
spring.http.client.read-timeout=15000 # 读取超时(毫秒)
高级配置
SSL/TLS配置
# SSL配置
spring.http.client.ssl.enabled=true
spring.http.client.ssl.key-store=classpath:keystore.jks
spring.http.client.ssl.key-store-password=secret
spring.http.client.ssl.trust-store=classpath:truststore.jks
spring.http.client.ssl.trust-store-password=secret
连接池配置
# 连接池配置
spring.http.client.pool.max-connections=100
spring.http.client.pool.max-idle-time=30s
spring.http.client.pool.validation-interval=30s
超时配置
@Configuration
public class RestClientConfig {
@Value("${vims-set.gateway-url}")
private String url;
@Bean
public RestClient restClient() {
JdkClientHttpRequestFactory jdkClientHttpRequestFactory = new JdkClientHttpRequestFactory();
// 读取超时时间为 3 秒
jdkClientHttpRequestFactory.setReadTimeout(3000);
return RestClient.builder()
.requestFactory(jdkClientHttpRequestFactory)
.baseUrl(url)
.build();
}
}
Spring RestClient VS RestTemplate
RestTemplate 是 Spring 开发人员用来与 REST API 通信的工具。RestClient 现在是 Spring Framework 6.1 中引入的新选项。本文将比较和对比这两个 HTTP 客户端,以帮助您选择最适合您项目的客户端。
它被设计为旧 RestTemplate 类的现代替代品。以下是 RestClient 提供的功能的简要介绍。
Rest客户端
流畅的 API:通过将方法链接在一起使代码看起来像自然语言。
更加简洁,可读性更强。
需要 Spring Framework 6.1 或更高版本。
Rest模板
模板方法API为具有特定步骤的操作定义了一个骨架,允许子类自定义行为。
您现有的代码严重依赖于 RestTemplate,这需要进行极少的更改。
RestTemplate 和 RestClient 提供了多种选项,可用于构建 HTTP 请求、处理响应以及自定义与外部服务的交互。让我们看看如何使用 RestTemplate 和 RestClient 创建 HTTP 请求,重点介绍常见场景,例如发出 GET 和 POST 请求、设置标头、处理错误和处理响应。
我将通过实际示例向您展示 RestTemplate 和 RestClient 之间的相似之处和不同之处。这将帮助您决定哪种选项最适合您的项目需求。
创建 RestTemplate
// 使用 Apache HttpComponents HttpClient 为 HTTP 请求创建 ClientHttpRequestFactory。
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory ();
//使用指定的 requestFactory 创建自定义 RestTemplate 实例。RestTemplate
customTemplate = new RestTemplate ( requestFactory); // 向 RestTemplate 添加拦截器。
//此拦截器通过添加自定义标头(“My-Header”:“Foo”)来修改传出的请求。
customTemplate.getInterceptors ().add((request, body, executive) -> {
request.getHeaders().add( "My-Header" , "Foo" ); // 向请求添加自定义标头
return executive.execute(request, body); // 继续执行请求
}
);
使用 RestTemplate 创建 GET 请求
// 使用 restTemplate 发送 GET 请求
RestTemplate restTemplate = new RestTemplate ();
// 设置标头
HttpHeaders headers = new HttpHeaders ();
headers.set( "Correlation" , correlationId);
// 使用标头构建实体
HttpEntity<Void> entity = new HttpEntity <>(headers);
try {
// 执行带有错误处理的 GET 请求
ResponseEntity<MyResponse> response = restTemplate.exchange(
"https://developers.ascendcorp.com" , // 指定要连接到的 URL
HttpMethod.GET,
entity,
MyResponse.class);
// 处理成功的响应
MyResponse myResponse = response.getBody();
} catch (RestClientResponseException e) {
// 检查 4xx 错误
if (e.getStatusCode().is4xxClientError()) {
throw new MyCustomRuntimeException (e.getStatusCode(), e.getResponseHeaders());
} else {
// 处理其他错误
throw e;
}
}
使用 RestTemplate 创建 POST 请求
// 创建一个包含请求数据的 HttpEntity
HttpEntity<MyRequest> requestEntity = new HttpEntity <>(request);
// 创建 HttpHeaders 对象来保存 HTTP 标头
HttpHeaders headers = new HttpHeaders ();
// 添加自定义标头“my-header-a”和“my-header-b”及其各自的值
headers.add( "my-header-a" , headerA);
headers.add( "my-header-b" , headerB);
// 使用指定的 HttpEntity 和 HttpHeaders 向“https://developers.ascendcorp.com”发送 POST 请求,
//并期望响应映射到 MyResponse.class
MyResponse response = restTemplate.postForEntity(
"https://developers.ascendcorp.com" ,
requestEntity,
MyResponse.class,
headers
).getBody();
创建一个 RestClient
// 使用 RestClient.builder() 方法构建自定义 RestClient RestClient customClient = RestClient.builder() .requestFactory( new HttpComponentsClientHttpRequestFactory ()) // 设置请求工厂以使用 Apache HttpComponents HttpClient 进行 HTTP 请求 .defaultHeader( "My-Header" , "Foo" ) // 为 RestClient 发出的所有请求添加默认标头 .requestInterceptor(myCustomInterceptor) // 向 RestClient 添加请求拦截器以拦截和修改请求 .build(); // 构建 RestClient 实例
使用 RestClient 创建 GET 请求
// 使用 customClient 发送 GET 请求 RestClient
MyResponse response = customClient.get()
.uri(URI.create( "https://developers.ascendcorp.com" )) // 指定要连接的 URL
.header( "Correlation" , correlationId) // 设置标头
.retrieve() // 检索响应
.onStatus(HttpStatusCode::is4xxClientError, (request, response) -> { // 为所有 4xx 状态代码设置状态处理程序
// 遇到 4xx 客户端错误时抛出自定义异常
throw new MyCustomRuntimeException (response.statusCode(), response.headers());
})
.body(MyResponse.class); // 将 JSON 响应转换为 MyResponse 域对象dy(MyResponse.class); // 将 JSON 响应转换为 MyResponse 域对象
使用 RestClient 创建 POST 请求
// 使用 customClient 发送 POST 请求 RestClient
MyResponse response = customClient.post()
.uri(URI.create( "https://developers.ascendcorp.com" )) // 指定要连接的 URL
.body(request) // 设置请求正文
.header( "my-header-a" , headerA) // 设置自定义标头“my-header-a”
.header( "my-header-b" , headerB) // 设置自定义标头“my-header-b”
.retrieve() // 检索响应
.toEntity(MyResponse.class) // 将响应转换为 ResponseEntity
.getBody(); // 获取此实体的正文
RestClient 与 RestTemplate 性能对比?
对于大多数用例,在 RestClient 和 RestTemplate 之间进行选择不会影响性能。我的团队已经将部分服务迁移到 RestClient。结果没有差异。两者都是同步客户端,这意味着它们会等待服务器的响应后再继续。影响性能的关键因素是底层 HTTP 客户端库、网络条件、请求复杂性和缓存策略。
Spring RestClient 具有流畅的 API,但使用阻塞 I/O。对于真正高并发场景,请考虑使用 Spring WebClient 非阻塞方法同时处理多个请求,而无需等待每个响应。与 RestClient 和 RestTemplate 等同步客户端相比,这可以显著提高性能。
选择合适的工具
RestClient 是 Spring HTTP 客户端的一个强大补充。其流畅的 API 和抽象功能使其成为新项目的可靠选择,尤其是针对 Spring Framework 6.1 或更高版本的项目。但是,RestTemplate 仍然是不需要重写的现有代码库的可靠选择。通过了解它们的优势和劣势,您可以做出明智的决定,确定哪个客户端最适合您的开发需求。
官网参考:REST Clients :: Spring Framework
Spring Boot 3.4新特性:RestClient和RestTemplate的重大更新详解_springboot restclient-优快云博客
spring的restClient连接池分析_restclient 连接池-优快云博客
https://developers.ascendcorp.com/spring-restclient-vs-resttemplate-a742aa499e6f
https://developers.ascendcorp.com/spring-restclient-vs-resttemplate-a742aa499e6f
欢迎点赞(动动小手),评论