Spring WebClient vs RestTemplate——比较和特点

介绍

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 的声明:

@Bean public RestOperations restOperations() { return new RestTemplate(); }

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

``` @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 端点发出请求
  • 处理响应

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

``` 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:

```

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 的类如下所示:

``` 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 的地方。

``` 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 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 时添加它。

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,以及它提供的不同功能。

你可能感兴趣的:(spring,java,后端,spring,boot,开发语言)