springboot3 RestClient、HTTP 客户端区别

1 RestClient使用

RestClientSpring 6.1 M2 中引入的同步 HTTP 客户端,它取代了 RestTemplate。同步 HTTP 客户端以阻塞方式发送和接收 HTTP 请求和响应,这意味着它会等待每个请求完成后才继续下一个请求。本文将带你了解 RestClient 的功能以及它与 RestTemplate 的比较。

1.1 RestClientRestTemplate

RestTemplate,顾名思义,是基于模板设计模式构建的。它是一种行为设计模式,用于在方法中定义算法的框架,允许子类为某些步骤提供特定的实现。虽然这是一种强大的模式,但它会导致需要进行方法覆写,这可能是不方便的。

为了改进这一点,RestClient 采用了 Fluent API。Fluent API 也是一种设计模式,它允许以一种使代码更易读和表达的方式进行方法链式调用,通常无需使用中间变量。从创建一个基本的 RestClient 开始:

RestClient restClient = RestClient.create();

1.2 使用各种 HTTP 方法发起请求

RestTemplate 或其他 REST 客户端类似,RestClient 可以使用不同的 HTTP 方法发起请求。创建一个用于操作的 Article 类:

java 复制代码
public class Article {
    Integer id;
    String title;
    // 构造函数和 getter/setter
}

1.2.1 使用 GET 请求获取资源

GET 请求用于检索 Web 服务器上指定资源的数据,而不对其进行修改。通常,这是一个只读的操作!获取服务器响应的字符串(String):

java 复制代码
String result = restClient.get()
  .uri(uriBase + "/articles")
  .retrieve()
  .body(String.class);

1.2.2 使用 POST 请求创建资源

POST 请求用于提交数据到 Web 服务器上,进行新的资源创建。资源通常是通过 URI 定义的。向服务器发送一篇 ID 为 1Article

java 复制代码
Article article = new Article(1, "How to use RestClient");
ResponseEntity<Void> response = restClient.post()
  .uri(uriBase + "/articles")
  .contentType(APPLICATION_JSON)
  .body(article)
  .retrieve()
  .toBodilessEntity();

由于指定了 APPLICATION_JSON Content Type,Jackson 库会自动将 Article 类实例序列化为 JSON。在本例中,使用 toBodilessEntity() 方法忽略了响应体。POST 端点不需要返回任何 Payload,通常也不会返回任何 Payload。

1.2.3 使用 PUT 请求更新资源

接下来是 PUT 请求,用于更新或替换已经存在的资源。修改上一段中创建的 Article,URI 中的 ID 即表示要修改的资源:

java 复制代码
Article article = new Article(1, "How to use RestClient even better");
ResponseEntity<Void> response = restClient.put()
  .uri(uriBase + "/articles/1")
  .contentType(APPLICATION_JSON)
  .body(article)
  .retrieve()
  .toBodilessEntity();

与 POST 请求一样,依靠 RestClient 对 Payload 进行序列化,并忽略响应。

1.2.4 使用 DELETE 请求删除资源

使用 DELETE 请求从 Web 服务器上删除指定资源。与 GET 类似,通常不提供任何 Payload,而是在 URI 参数中指定要删除的资源:

java 复制代码
ResponseEntity<Void> response = restClient.delete()
  .uri(uriBase + "/articles/1")
  .retrieve()
  .toBodilessEntity();

1.3 反序列化响应

通常,我们希望将请求序列化,并将响应反序列化为我们可以操作的类。RestClient 具有执行 JSON 到对象转换的功能,该功能由 Jackson 库提供。此外,由于共享使用了 Message Converter,因此可以使用 RestTemplate 支持的所有数据类型。通过 ID 获取一篇文章,并将其序列化为 Article 类的实例:

java 复制代码
Article article = restClient.get()
  .uri(uriBase + "/articles/1")
  .retrieve()
  .body(Article.class);

当我们需要获取 List 等泛型类的实例时,指定 body 的类就比较复杂了。例如,如果我们想获取所有 Article,以 List<Article> 对象形式返回。在这种情况下,可以使用 ParameterizedTypeReference 抽象类来告诉 RestClient 我们要获取什么对象。甚至不需要指定泛型类型,Java 会自动推断出类型:

java 复制代码
List<Article> articles = restClient.get()
  .uri(uriBase + "/articles")
  .retrieve()
  .body(new ParameterizedTypeReference<>() {});

1.4 使用 Exchange 解析响应

RestClient 包含 exchange() 方法。通过提供对底层 HTTP 请求和响应的访问权限,用于处理更复杂的情况。在这种情况下,库不会应用默认的 Handler,我们必须自己处理响应的 Status。

比方说,当数据库中没有文章时,服务会返回 204 (No Content)状态代码。由于这种行为略显非标准,我们希望以一种特殊的方式来处理它。当状态代码等于 204 时,抛出一个 ArticleNotFoundException 异常;当状态代码不等于 200 时,抛出一个更通用的异常:

java 复制代码
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 对 Response Body 进行反序列化。

1.5 异常处理

默认情况下,当 RestClient 在 HTTP 响应中遇到 4xx5xx 状态码时,它会抛出一个 RestClientException 子类的异常。我们可以通过自定义 Status Handler 来覆盖这一行为。自定义 Status Handler,在找不到文章时抛出一个自定义异常:

java 复制代码
Article article = restClient.get()
  .uri(uriBase + "/articles/1234")
  .retrieve()
  .onStatus(status -> status.value() == 404, (request, response) -> {
      throw new ArticleNotFoundException(response)
  })
  .body(Article.class);

1.6 从 RestTemplate 构建 RestClient

如果你已经在项目中使用上了 RestTemplate,也可以可从 RestTemplate 构建 RestClient

java 复制代码
RestTemplate oldRestTemplate;
RestClient restClient = RestClient.create(oldRestTemplate);

2 HTTP 客户端区别

2.1 RestTemplate

RestTemplate 是 Spring 框架提供的同步 HTTP 客户端,专用于发起 RESTful 请求。它通过封装 HTTP 请求和响应的样板代码,提供了一种简洁的方式与 REST 服务进行交互。

2.1.1 核心特性

  • 同步API: RestTemplate以同步方式运行,阻塞当前线程直到收到响应。
  • 模板方法: 提供了用于常见HTTP操作(GET、POST、PUT、DELETE等)的预定义方法。
  • 可定制性: 允许通过拦截器、错误处理程序和消息转换器进行定制。
  • 对象映射: 可以使用消息转换器自动将请求和响应体转换为Java对象。

2.1.2 优点和缺点

优点:

  • 使用简单易懂: RestTemplate 提供了直观的 API,简化了与 RESTful 服务的交互,开发者可以轻松上手。
  • 适用于简单用例: 对于常见的 CRUD 操作和简单的 HTTP 请求处理,RestTemplate 是一种方便的选择。
  • 与 Spring 生态系统良好集成: 作为 Spring 框架的一部分,RestTemplate 与 Spring 的其他组件紧密配合,能够无缝融入到 Spring 应用中。

缺点:

  • 同步特性可能在高并发场景中影响性能: 由于 RestTemplate 是同步的,调用线程会阻塞直到响应返回,这在高并发情况下可能导致性能瓶颈。
  • 对异步和响应式编程的支持有限: RestTemplate 不支持异步处理,也无法与响应式编程模式兼容,这使得它在需要非阻塞操作的场景中不够灵活。
  • 正在被 WebClient 取代: 随着 Spring 5 的推出,WebClient 作为更现代的 HTTP 客户端出现,逐渐成为 RestTemplate 的替代品,尤其是在响应式编程场景下。

2.1.3 使用 RestTemplate 的时机

RestTemplate 适用于那些同步行为可接受且性能要求不高的简单用例。对于需要进行直接 REST 交互的中小型应用程序,RestTemplate 可能是一个理想的选择。特别是在以下情况下,它是不错的工具:

  • 简单的 CRUD 操作: 当应用程序主要处理创建、读取、更新和删除等基本 REST 操作时,RestTemplate 提供了简洁易用的 API。
  • 同步请求: 如果应用程序可以容忍同步请求,且并发需求不高,那么 RestTemplate 可以很好地满足需求。
  • 快速原型开发: 在开发阶段,RestTemplate 可以快速帮助构建和测试 RESTful API 的交互逻辑。

然而,当需要处理复杂的异步操作、流式处理或者更高的并发需求时,应该考虑使用 WebClientRestClient

2.2 WebClient

WebClient 是在 Spring 5 中引入的非阻塞、响应式 HTTP 客户端,被设计为 RestTemplate 的替代品。它基于 Project Reactor 构建,支持异步和非阻塞操作。这种方式非常适合构建现代、可扩展的应用程序,特别是在需要高效处理高并发场景时,WebClient 能够显著提高性能和系统的响应能力。

WebClient 提供了灵活且强大的 API,使开发者能够轻松处理复杂的 HTTP 交互,包括流式数据处理和异步操作。由于它与 Spring 的响应式编程模型紧密集成,因此对于现代微服务架构和高并发应用来说,WebClient 是一个至关重要的工具。

2.2.1 核心特性

  • 响应式 API: WebClient 利用 MonoFlux 等响应式编程概念来进行异步操作,使开发者可以轻松处理单个或多个异步数据流。
  • 流畅接口: WebClient 提供了声明式、可读性强的 API,用于构建和执行 HTTP 请求,开发者可以通过链式调用方式轻松定义复杂的请求逻辑。
  • 非阻塞: WebClient 的非阻塞特性允许在不阻塞当前线程的情况下发起请求,从而提高了资源利用率,特别是在高并发场景下表现尤为出色。
  • 与 Spring 生态系统集成: WebClientSpring Data ReactiveSpring Security 等其他 Spring 组件无缝集成,支持响应式数据访问和安全认证等功能,使得它能够完美融入 Spring 响应式堆栈。

2.2.2 优点和缺点

优点:

  • 非阻塞和异步: WebClient 支持非阻塞的异步操作,可以更高效地利用系统资源,特别是在处理大量并发请求时表现出色。
  • 并发请求的高性能: 通过异步处理和非阻塞 I/O,WebClient 能够处理更高的并发请求量,适合需要高吞吐量的应用场景。
  • 支持响应式编程: WebClient 与 Spring 的响应式编程模型紧密集成,支持 MonoFlux,能够更自然地处理流式数据和异步操作。
  • 更适合现代应用程序架构: 对于微服务架构、响应式系统等现代架构,WebClient 提供了更丰富的功能和更高的灵活性,能够适应复杂的需求。

缺点:

  • 学习曲线更陡峭: 由于 WebClient 基于响应式编程模型,开发者可能需要掌握 MonoFlux 等响应式编程概念,这对不熟悉响应式编程的开发者来说会有一定的学习难度。
  • 更复杂的错误处理:RestTemplate 相比,WebClient 的错误处理可能更复杂,需要开发者在处理响应状态、异常和重试机制时更加小心和全面。

2.2.3 使用WebClient的时机

WebClient 是大多数现代 Spring 应用程序的首选工具。它非常适合微服务架构、高流量应用程序,以及那些非阻塞行为至关重要的场景。在构建响应式系统或需要高效处理大量并发请求时,WebClient 是一个值得优先考虑的选择。无论是处理复杂的 HTTP 交互,还是构建高度可扩展的系统,WebClient 都能为开发者提供强大的功能和灵活性,使其能够轻松应对现代应用程序的需求。

2.3 RestClient

RestClient 是 Spring HTTP 客户端领域的最新发展,作为 RestTemplate 的现代化和高效替代品引入。它旨在解决 RestTemplate 的一些局限性,同时结合了 WebClient 的最佳实践。

RestClient 提供了更先进的功能,专注于优化性能和提高开发效率,尤其在处理 RESTful API 请求时,结合了响应式编程和非阻塞操作的优点。通过引入 RestClient,Spring 提供了一种更现代的解决方案,能够更好地满足当前和未来的应用需求。

2.3.1 核心特性和改进

  • 构建者模式: RestClient 使用构建者模式来构建请求,这种模式提供了更流畅、可读性更高的 API,使得请求的配置和管理更加直观和灵活。
  • 异步操作: 尽管 RestClient 的异步能力不如 WebClient 那么全面,但它通过 CompletableFuture 提供了一定程度的非阻塞能力,适合需要异步处理但不要求完全响应式的场景。
  • 响应式支持: RestClient 可以与 Project Reactor 等响应式编程框架集成,支持响应式编程模型,使其能够更好地适应现代应用程序的需求,并提高应用程序的可扩展性。
  • 简化的错误处理: RestClient 提供了改进的错误处理机制,使得异常处理和 HTTP 状态码的管理变得更加简单和直接,有助于提高开发效率和代码质量。

2.3.2 使用RestClient的时机

当我们需要在 RestTemplate 的简单性和 WebClient 的高级特性之间取得平衡时,RestClient 是一个合适的选择。它适用于那些需要异步操作但不需要完全响应式编程的项目,提供了一种折衷方案。

此外,如果您正在从 RestTemplate 迁移并希望逐步过渡,RestClient 也是一个很好的选择。它不仅保留了 RestTemplate 的易用性,还引入了现代化的特性,使得迁移过程更加平滑,同时为未来的需求提供了更多的灵活性。

2.4 三者比较

以下是 RestTemplateWebClientRestClient 的特性对比表:

特性 RestTemplate WebClient RestClient
同步/异步 同步 异步 同步/异步
API 风格 模板方法 流畅构建者 流畅构建者
响应式 部分
性能 较低 较高 中等
复杂性 较低 较高 中等
Spring 版本 旧版本 Spring 5+ Spring 6.1+

2.4.1 重要考虑因素

  • 性能: 对于需要处理高并发和非阻塞操作的场景,WebClient 显然是最佳选择,它提供了高性能和良好的资源利用效率。
  • 复杂性: RestTemplate 提供了简单易用的 API,适合初学者和简单用例;而 WebClientRestClient 提供了更多高级特性和灵活性,但复杂性也相应较高。
  • 项目需求: 如果您的项目需要同步行为和易用性,RestTemplate 可能已经足够。如果您正在构建现代响应式应用程序,WebClient 是最佳选择。RestClient 则提供了一种在这两者之间的平衡方案,适合那些需要异步操作但不完全响应式的场景。
  • Spring 版本: 选择客户端时,请确保与您当前使用的 Spring 版本兼容。RestTemplate 是较旧版本的选择,而 WebClientRestClient 则需要较新的 Spring 版本。

2.4.2 建议

  • 新项目: 如果您正在开始一个新项目,优先考虑使用 WebClient,因为它提供了最佳的性能和响应式能力,适合现代应用程序的需求。
  • 现有项目: 对于已经使用 RestTemplate 的现有项目,如果计划迁移到更现代的客户端,RestClient 可以作为一个很好的过渡步骤,逐步引入异步和非阻塞特性。
  • 简单用例: 对于简单的 HTTP 请求和同步操作,RestTemplate 仍然是一个合适的选择,特别是在性能和复杂性要求不高的情况下。
相关推荐
不脱发的猴子1 小时前
Wireshark使用教程
网络·测试工具·wireshark
EasyCVR2 小时前
EasyRTC嵌入式视频通话SDK的跨平台适配,构建web浏览器、Linux、ARM、安卓等终端的低延迟音视频通信
android·arm开发·网络协议·tcp/ip·音视频·webrtc
小羊在奋斗3 小时前
【Linux网络】NAT技术、DNS系统、五种IO模型
linux·网络·智能路由器
暴躁的小胡!!!5 小时前
Linux权限维持之协议后门(七)
linux·运维·服务器·网络·安全
车载测试工程师5 小时前
车载以太网测试-3【Wireshark介绍】
经验分享·功能测试·网络协议·车载系统
遇见火星6 小时前
2025年Linux 安全与运维指南
网络
苏格拉真没有底6 小时前
python实现mqtt消息转Tcp消息
网络·python·tcp/ip
dxaiofcu6 小时前
双网卡电脑,IP地址漂移
linux·服务器·网络
煲冬瓜的程序猿8 小时前
BGP(三)联盟、反射器
网络·网络协议
Joeysoda8 小时前
JavaEE进阶(2) Spring Web MVC: Session 和 Cookie
java·前端·网络·spring·java-ee