服务调用REST接口

目录

1、背景介绍

2、HTTP客户端架构的演进

历史回顾

RestTemplate时代(Spring 3.0+)

 Spring Boot 3.4的重大变化

配置体系详解

 基础配置

高级配置

超时配置

Spring RestClient VS RestTemplate

Rest客户端

Rest模板

创建 RestTemplate

 使用 RestTemplate 创建 GET 请求

 使用 RestTemplate 创建 POST 请求

 创建一个 RestClient

使用 RestClient 创建 GET 请求

使用 RestClient 创建 POST 请求

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+)

  1. RestTemplate时代(Spring 3.0+)
    1. 同步阻塞式API
    2. 基于传统的Java模式
    3. 配置相对复杂
  2. WebClient时代(Spring 5.0+)
    1. 响应式非阻塞API
    2. 支持响应式编程
    3. 需要引入额外的响应式依赖
  3. RestClient时代(Spring 6.1+)
    1. 现代化同步API
    2. 流畅的链式调用
    3. 更简单的配置方式

 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

欢迎点赞(动动小手),评论
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

what_2018

你的鼓励是我前进的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值