前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring WebClient vs RestTemplate——比较和特点

Spring WebClient vs RestTemplate——比较和特点

作者头像
用户4235284
发布2023-10-14 15:59:20
4500
发布2023-10-14 15:59:20
举报
文章被收录于专栏:后端学习之道后端学习之道

介绍

Spring 5 引入了一个名为 WebClient 的新反应式 Web 客户端。在这篇文章中,我将展示何时以及如何使用 Spring WebClient 与 RestTemplate。我还将描述 WebClient 提供的功能。

什么是 RestTemplate?

RestTemplate是一个central Spring 类,它允许从客户端进行 HTTP 访问。RestTemplate 提供 POST、GET、PUT、DELETE、HEAD 和 OPTIONS HTTP 方法。RestTemplate 的简单用例是使用 Restful Web 服务。

您可以创建一个提供 RestTemplate 实例的 bean。然后,您可以@autowire在计划调用 REST 服务的任何类中使用此 bean。RestTemplate 是实现接口的类RestOperations

以下代码显示了 bean 的声明:

代码语言:javascript
复制
    @Bean
    public RestOperations restOperations()
    {
        return new RestTemplate();
    }

以下代码显示了一个 REST 客户端YelpClient调用 Yelp 的 REST API 来获取出租物业评论。

代码语言:javascript
复制
   @Autowired
   private final RestOperations restOperations;

   public List getRentalPropertyReviews(String address)
   {
        String url = buildRestUrl(businessId);
        HttpHeaders httpHeaders = new HttpHeaders();
        String apiKey = getApiKey(YELP);
        httpHeaders.add("Authorization","Bearer " + apiKey);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity entity = new HttpEntity("parameters", httpHeaders);
        ResponseEntity response;

        try
        {
            response = restOperations.exchange(url, HttpMethod.GET,entity, String.class);
        }
        catch(RestClientException e)
        {
            throw new RuntimeException("Unable to retrieve reviews", e);
        }

    }

在上面的代码中,我们通过添加 Yelp 的 REST API 密钥作为授权的一部分来构建 HTTP 标头。我们调用 GET 方法来获取评论数据。

基本上,一个人必须做

  • 自动装配 RestTemplate 对象
  • 使用授权和内容类型构建 HTTP 标头
  • 使用 HttpEntity 包装请求对象
  • 提供 URL、Http 方法和交换方法的返回类型。

什么是WebClient?

Spring 5 引入了一个名为 WebClient 的响应式 Web 客户端。它是执行网络请求的接口。它是 Spring Web 反应模块的一部分。WebClient 最终将取代 RestTemplate。

最重要的是,WebClient 是反应式的、非阻塞的、异步的,并且在 HTTP 协议 Http/1.1 上工作。

要使用 WebClient,必须要满足以下条件

  • 创建 WebClient 的实例
  • 向 REST 端点发出请求
  • 处理响应
代码语言:javascript
复制
WebClient webClient = WebClient
       .builder()
       .baseUrl("https://localhost:8443")
       .defaultCookie("cookieKey", "cookieValue")
       .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) 
       .defaultUriVariables(Collections.singletonMap("url", "https://localhost:8443"))
       .build();

上面的代码显示了一种实例化 WebClient 的方法。您还可以通过简单地使用创建一个实例WebClient webClient = WebClient.create();

WebClient 提供了两种方法exchangeretrieve. exchange 方法通常会获取响应以及状态和标头。retrieve 方法直接获取响应体。它更容易使用。

此外,根据您是尝试获取单个对象作为响应还是对象列表,您可以使用monoor flux

代码语言:javascript
复制
this.webClient =
                webClientBuilder.baseUrl("http://localhost:8080/v1/betterjavacode/").build();

this.webClient.get()
                .uri("users")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve().bodyToFlux(UserDto.class).collectList();

上面的代码主要用于webClient从 REST API 获取用户列表。

Spring WebClient 与 RestTemplate

我们已经知道这两个功能之间的一个关键区别。WebClient 是一个非阻塞客户端,而 RestTemplate 是一个阻塞客户端。

RestTemplate 在底层使用 Java Servlet API。Servlet API 是一个同步调用者。因为是同步的,线程会阻塞,直到webclient响应请求。

因此,等待结果的请求将会增加。这将导致内存增加。

另一方面,WebClient 是一个异步非阻塞客户端。它在底层使用 Spring 的反应式框架。WebClient 是 Spring-WebFlux 模块的一部分。

Spring WebFlux 使用反应器库。它提供 Mono 和 Flux API 来处理数据序列。Reactor 是一个反应流库。而且,它的所有运营商都支持非阻塞背压。

如何在 Spring Boot 应用程序中使用 WebClient 的示例

我们可以结合 Spring Web MVC 和 Spring WebFlux 的功能。在本节中,我将创建一个示例应用程序。此应用程序将使用 WebFlux 调用 REST API,我们将构建响应以显示包含用户列表的网页。

RestController此示例是一个获取用户列表的 API:

代码语言:javascript
复制
package com.betterjavacode.webclientdemo.controllers;

import com.betterjavacode.webclientdemo.dto.UserDto;
import com.betterjavacode.webclientdemo.managers.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("v1/betterjavacode")
public class UserController
{
    @Autowired
    public UserManager userManager;

    @GetMapping(value = "/users")
    public List getUsers()
    {
        return userManager.getAllUsers();
    }
}

Controller使用 WebClient 调用 REST API 的类如下所示:

代码语言:javascript
复制
package com.betterjavacode.webclientdemo.controllers;

import com.betterjavacode.webclientdemo.clients.UserClient;
import com.betterjavacode.webclientdemo.dto.UserDto;
import com.betterjavacode.webclientdemo.managers.UserManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

@Controller
public class MainController
{
    @Autowired
    UserClient userClient;

    @GetMapping(value = "/")
    public String home()
    {
        return "home";
    }

    @GetMapping(value = "/users")
    public String getUsers(Model model)
    {
        List users = userClient.getUsers().block();

        model.addAttribute("userslist", users);
        return "users";
    }
}

现在,UserClient 的重要代码段是我们将使用 WebClient 调用 REST API 的地方。

代码语言:javascript
复制
package com.betterjavacode.webclientdemo.clients;

import com.betterjavacode.webclientdemo.dto.UserDto;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.List;

@Service
public class UserClient
{

    private WebClient webClient;

    public UserClient(WebClient.Builder webClientBuilder)
    {
        this.webClient =
                webClientBuilder.baseUrl("http://localhost:8080/v1/betterjavacode/").build();
    }

    public Mono<List> getUsers()
    {
        return this.webClient.get()
                .uri("users")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve().bodyToFlux(UserDto.class).collectList();
    }
}

上面的代码显示首先构建 WebClient,然后使用它retrieve从 REST API 响应。retrieve 方法提供了 mono 或 flux 两种选择。由于我们要获取多个用户,因此我们使用的是 flux。

这表明我们可以使用响应式、非阻塞的 WebClient,它是 Spring Web MVC 框架中 WebFlux 的一部分。

Spring WebClient 中还有什么?

Spring WebClient 是Spring WebFlux框架的一部分。这个 API 的主要优点是开发人员不必担心并发或线程。WebClient 负责这个。

WebClient 有一个内置的 HTTP 客户端库支持来执行请求。这包括 Apache HttpComponents、Jetty Reactive HttpClient 或 Reactor Netty。

WebClient.builder()提供以下选项:

uriBuilderFactory– 自定义 uriBuilderFactory 以使用基本 URL defaultHeader– 每个请求的标头 defaultCookie– 每个请求的 Cookie defaultRequest– 自定义每个请求 filter– 每个请求的客户端过滤器 exchangeStrategies– HTTP 消息读取器/写入器自定义 我已经retrieve在上面的代码演示中展示了方法。

WebClient 还提供了一种带有变量的方法,exchange例如exchangeToMono andexchangeToFlux`。

使用attribute(),我们还可以向请求添加属性。

或者,也可以使用 WebClient 进行同步使用。在我上面的 MainController 示例中,我使用它block来获取最终结果。这基本上会阻止并行调用,直到我们得到结果。

WebClient 提供的一项关键功能是retryWhen(). 对于更具弹性的系统,这是一个很棒的功能,您可以在使用 WebClient 时添加它。

代码语言:javascript
复制
     webClient
        .get()
        .uri(String.join("", "/users", id))
        .retrieve()
        .bodyToMono(UserDto.class)
        .retryWhen(Retry.fixedDelay(5, Duration.ofMillis(100)))
        .block();

retryWhen将重试类作为参数。

WebClient 还提供错误处理功能。doOnError()允许您处理错误。当单声道以错误结束时触发。onErrorResume()是基于错误的回退。

结论

在这篇文章中,我展示了什么是 Spring WebClient,我们如何使用 Spring WebClient 与 RestTemplate,以及它提供的不同功能。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 什么是 RestTemplate?
  • 什么是WebClient?
  • Spring WebClient 与 RestTemplate
  • 如何在 Spring Boot 应用程序中使用 WebClient 的示例
  • Spring WebClient 中还有什么?
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档