1. Overview
1.概述
A RESTful service can fail for any number of reasons. In this tutorial, we’ll look at how to retrieve the original message from the Feign client if the integrated REST service throws an error.
一个RESTful服务可能会因为任何原因而失败。在本教程中,我们将研究如何在集成的REST服务出现错误时从Feign客户端检索原始消息。
2. Feign Client
2.假装是客户
Feign is a pluggable and declarative web service client that makes writing web service clients easier. In addition, to Feign annotations, it also supports JAX-RS, and it supports encoders and decoders to provide more customization.
Feign是一个可插拔的、声明式的Web服务客户端,它使编写Web服务客户端变得更加容易。此外,除了Feign注释,它还支持JAX-RS,它还支持编码器和解码器,以提供更多的定制功能。
3. Retrieving Message From ErrorDecoder
3.从ErrorDecoder中检索信息
When errors occur, the Feign client suppresses the original message, and to retrieve it, we require to write a custom ErrorDecoder. In the absence of such customization, we’ll get the following error:
当错误发生时,Feign客户端会抑制原始信息,为了检索它,我们需要编写一个自定义的ErrorDecoder。如果没有这种自定义,我们会得到如下错误。
feign.FeignException$NotFound: [404] during [POST] to [http://localhost:8080/upload-error-1] [UploadClient#fileUploadError(MultipartFile)]: [{"timestamp":"2022-02-18T13:25:22.083+00:00","status":404,"error":"Not Found","path":"/upload-error-1"}]
at feign.FeignException.clientErrorStatus(FeignException.java:219) ~[feign-core-11.7.jar:na]
at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-11.7.jar:na]
To handle this error, we’ll create a simple ExceptionMessage Java bean representing the error message:
为了处理这个错误,我们将创建一个简单的ExceptionMessage Java Bean,代表错误信息。
public class ExceptionMessage {
private String timestamp;
private int status;
private String error;
private String message;
private String path;
// standard getters and setters
}
Let’s retrieve the original message by extracting it in our customized implementation of ErrorDecoder:
让我们通过在我们定制的ErrorDecoder的实现中提取原始信息来检索它。
public class RetreiveMessageErrorDecoder implements ErrorDecoder {
private ErrorDecoder errorDecoder = new Default();
@Override
public Exception decode(String methodKey, Response response) {
ExceptionMessage message = null;
try (InputStream bodyIs = response.body()
.asInputStream()) {
ObjectMapper mapper = new ObjectMapper();
message = mapper.readValue(bodyIs, ExceptionMessage.class);
} catch (IOException e) {
return new Exception(e.getMessage());
}
switch (response.status()) {
case 400:
return new BadRequestException(message.getMessage() != null ? message.getMessage() : "Bad Request");
case 404:
return new NotFoundException(message.getMessage() != null ? message.getMessage() : "Not found");
default:
return errorDecoder.decode(methodKey, response);
}
}
}
In our implementation, we’ve added the logic based on possible errors, and hence we can customize them to meet our requirements. In our switch block’s default case, we’re using Default implementation of ErrorDecoder.
在我们的实现中,我们已经根据可能的错误添加了逻辑,因此我们可以定制它们以满足我们的要求。在我们开关块的默认情况下,我们使用Default实现ErrorDecoder。
Default implementation decodes the HTTP response when the status is not in the 2xx range. When throwable is retryable, it should be a subtype of RetryableException, and we should raise application-specific exceptions whenever possible.
Default实现对状态不在2xx范围内的HTTP响应进行解码。当throwable是retryable时,它应该是RetryableException的一个子类型,并且我们应该尽可能地引发应用特定的异常。
To configure our customized ErrorDecoder, we’ll add our implementation as a bean in the Feign configuration:
为了配置我们定制的 ErrorDecoder,我们将把我们的实现作为一个bean添加到Feign配置中。
@Bean
public ErrorDecoder errorDecoder() {
return new RetreiveMessageErrorDecoder();
}
Now, let’s see the exception with the original message:
现在,让我们看看原始信息的例外情况。
com.baeldung.cloud.openfeign.exception.NotFoundException: Page Not found
at com.baeldung.cloud.openfeign.fileupload.config.RetreiveMessageErrorDecoder.decode(RetreiveMessageErrorDecoder.java:30) ~[classes/:na]
at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:96) ~[feign-core-11.7.jar:na]
4. Conclusion
4.结论
In this article, we’ve demonstrated how to customize ErrorDecoder so we can catch Feign errors to fetch the original message.
在这篇文章中,我们演示了如何定制ErrorDecoder,以便我们可以捕捉Feign错误来获取原始消息。
As usual, all code samples used in this tutorial are available over on GitHub.
像往常一样,本教程中使用的所有代码样本都可以在GitHub上找到。