1. Overview
1.概述
It’s often helpful to use the status code from an HTTP response to determine what an application should do next with the given response.
使用HTTP响应的状态代码来确定应用程序对给定的响应接下来应该做什么,往往是有帮助的。
In this tutorial, we’ll look at how to access the status code and response body returned from a REST request using WebFlux’s WebClient.
在本教程中,我们将了解如何使用WebFlux的WebClient.访问REST请求返回的状态代码和响应体。
WebClient was introduced in Spring 5, and can be used for asynchronous I/O while calling RESTful services.
WebClient是在Spring 5中引入的,它可以在调用RESTful服务时用于异步I/O。
2. Use Case
2.使用案例
When making RESTful calls to other services, applications typically use the returned status code to trigger different functionality. Typical use cases include graceful error handling, triggering retries of the request, and determining user error.
在对其他服务进行RESTful调用时,应用程序通常使用返回的状态代码来触发不同的功能。典型的用例包括优雅的错误处理、触发请求的重试以及确定用户错误。
As such, when making REST calls, it’s often not enough to get just the response code. Sometimes we want the response body, too.
因此,在进行REST调用时,仅仅获得响应代码往往是不够的。有时我们也想得到响应的主体。
In the following examples, we’ll see how we can parse the response body from the REST client WebClient. We’ll link our behavior to the status code returned, and make use of two methods of status code extraction provided by WebClient, onStatus and ExchangeFilterFunction.
在下面的例子中,我们将看到我们如何解析来自REST客户端WebClient的响应体。我们将把我们的行为与返回的状态代码联系起来,并利用WebClient提供的两种状态代码提取方法,onStatus和ExchangeFilterFunction。
3. Using onStatus
3.使用onStatus
onStatus is a built-in mechanism that can be used to handle a WebClient response. This allows us to apply finely grained functionality based on specific responses (such as 400, 500, 503, etc.), or on categories of statuses (such as 4XX, and 5XX, etc.):
onStatus是一个内置机制,可用于处理WebClient响应。这允许我们根据特定的响应(如400、500、503等)或状态的类别(如4XX和5XX等)来应用细化的功能。
WebClient
.builder()
.build()
.post()
.uri("/some-resource")
.retrieve()
.onStatus(
HttpStatus.INTERNAL_SERVER_ERROR::equals,
response -> response.bodyToMono(String.class).map(Exception::new))
The onStatus method requires two parameters. The first is a predicate that takes in a status code. Execution of the second parameter is based on the output of the first. The second is a function that maps the response to a Mono or an Exception.
onStatus方法需要两个参数。第一个是一个谓词,接收一个状态代码。第二个参数的执行是基于第一个参数的输出。第二个参数是一个函数,用于将响应映射为Mono或Exception.。
In this case, if we see an INTERNAL_SERVER_ERROR (i.e., 500), we’ll take the body, using bodyToMono, and then map that to a new Exception.
在这种情况下,如果我们看到一个INTERNAL_SERVER_ERROR(即500),我们将使用bodyToMono,获取主体,然后将其映射到一个新的Exception。
We can chain onStatus calls to be able to provide functionality for different status conditions:
我们可以将onStatus调用连锁起来,以便能够为不同的状态条件提供功能。
Mono<String> response = WebClient
.builder()
.build()
.post()
.uri("some-resource")
.retrieve()
.onStatus(
HttpStatus.INTERNAL_SERVER_ERROR::equals,
response -> response.bodyToMono(String.class).map(CustomServerErrorException::new))
.onStatus(
HttpStatus.BAD_REQUEST::equals,
response -> response.bodyToMono(String.class).map(CustomBadRequestException::new))
...
.bodyToMono(String.class);
// do something with response
Now onStatus calls map to our custom exceptions. We defined exception types for each of the two error statuses. The onStatus method allows us to use any type we choose.
现在onStatus调用映射到我们的自定义异常。我们为两种错误状态中的每一种定义了异常类型。onStatus方法允许我们使用任何我们选择的类型。
4. Using ExchangeFilterFunction
4.使用ExchangeFilterFunction
An ExchangeFilterFunction is another way to handle specific status codes and get response bodies. Unlike onStatus, the exchange filter is flexible, and applies to filter functionality based on any boolean expression.
ExchangeFilterFunction是处理特定状态代码和获取响应体的另一种方式。与onStatus不同,交换过滤器很灵活,适用于基于任何布尔表达式的过滤功能。
We can benefit from the flexibility of an ExchangeFilterFunction to cover the same categories as the onStatus function.
我们可以从ExchangeFilterFunction的灵活性中获益,以涵盖与onStatus函数相同的类别。
First, we’ll define a method to handle the returned logic based on the status code given a ClientResponse:
首先,我们将定义一个方法,根据给定的状态代码处理返回的逻辑,ClientResponse。
private static Mono<ClientResponse> exchangeFilterResponseProcessor(ClientResponse response) {
HttpStatus status = response.statusCode();
if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
return response.bodyToMono(String.class)
.flatMap(body -> Mono.error(new CustomServerErrorException(body)));
}
if (HttpStatus.BAD_REQUEST.equals(status)) {
return response.bodyToMono(String.class)
.flatMap(body -> Mono.error(new CustomBadRequestException(body)));
}
return Mono.just(response);
}
Next, we’ll define the filter and use a method reference to our handler:
接下来,我们将定义过滤器,并使用方法引用到我们的处理程序。
ExchangeFilterFunction errorResponseFilter = ExchangeFilterFunction
.ofResponseProcessor(WebClientStatusCodeHandler::exchangeFilterResponseProcessor);
Similar to the onStatus calls, we’re mapping to our Exception types on error. However, using Mono.error will wrap this Exception in a ReactiveException. This nesting should be kept in mind when handling the error.
与onStatus调用类似,我们在错误时映射到我们的Exception类型。然而,使用Mono.error将把这个Exception包裹在ReactiveException中。在处理错误时,应该记住这种嵌套方式。
Now we’ll apply this to an instance of a WebClient to achieve the same effect as the onStatus chained call:
现在我们将应用于WebClient的一个实例,以达到与onStatus链式调用相同的效果。
Mono<String> response = WebClient
.builder()
.filter(errorResponseFilter)
.build()
.post()
.uri("some-resource")
.retrieve()
.bodyToMono(String.class);
// do something with response
5. Conclusion
5.总结
In this article, we covered a couple of the methods to get the response body based on the HTTP status header. Based on the status code, the onStatus method allows us to plug specific functionality. In addition, we can use the filter method to plug in a general-purpose method to handle post-processing on all responses.
在这篇文章中,我们介绍了几个基于HTTP状态头获取响应体的方法。基于状态代码,onStatus方法允许我们插入特定功能。此外,我们可以使用filter方法来插入一个通用的方法来处理所有响应的后处理。
As always, all the code in this article can be found over on GitHub.
一如既往,本文中的所有代码都可以在GitHub上找到。