Contents

FeignErrordeCoder检索原始消息

1. 概述

RESTful 服务可能因多种原因而失败。在本教程中,我们将了解如果集成的 REST 服务抛出错误,如何从Feign客户端检索原始消息

2. Feign 客户端

Feign 是一个可插拔的声明式 Web 服务客户端,它使编写 Web 服务客户端变得更加容易。此外,对于 Feign 注解,它还支持JAX-RS ,并且它支持编码器和解码器以提供更多的自定义

3. 从ErrorDecoder 中检索消息

当发生错误时,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]

为了处理这个错误,我们将创建一个简单的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
}

让我们通过在我们自定义的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);
        }
    }
}

在我们的实现中,我们添加了基于可能错误的逻辑,因此我们可以自定义它们以满足我们的要求。在我们的 switch 块的默认情况下,我们使用ErrorDecoder的默认 实现。

当状态不在 2xx 范围内时,默认实现会解码 HTTP 响应。当throwableretryable 时,它应该是RetryableException 的子类型,并且我们应该尽可能引发特定于应用程序的异常。

要配置我们自定义的ErrorDecoder,我们将在 Feign 配置中添加我们的实现作为 bean:

@Bean
public ErrorDecoder errorDecoder() {
    return new RetreiveMessageErrorDecoder();
}

现在,让我们看看原始消息的异常:

com.blogdemo.cloud.openfeign.exception.NotFoundException: Page Not found
	at com.blogdemo.cloud.openfeign.fileupload.config.RetreiveMessageErrorDecoder.decode(RetreiveMessageErrorDecoder.java:30) ~[classes/:na]
	at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:96) ~[feign-core-11.7.jar:na]