【问题标题】:Feign and undeclared throwable exception for 404 Not Found404 Not Found 的假装和未声明的可抛出异常
【发布时间】:2019-08-04 12:09:14
【问题描述】:

我正在尝试捕捉 Feign 响应并评估 404 Not Found 响应的异常,类似于下面的 REST 模板:

try {
  response = restTemplate.exchange(url, HttpMethod.GET, request, Foo.class);

} catch (HttpClientErrorException ex) {
     if (ex.getStatusCode() != HttpStatus.NOT_FOUND) {
       throw ex;
     }
}

但对于

Foo response = feignClient.getFoo(foo)

这可能会抛出 undeclaredThrowableresponseCode 404。

【问题讨论】:

    标签: java spring spring-boot spring-cloud-feign feign


    【解决方案1】:

    您可以设置一个自定义错误控制器来处理应用程序的所有错误并返回您想要的消息类型。我将以下实现与 ResponseBody 一起用于 Web 应用程序。根据您的需要配置以下实现:

    @Controller
    public class CustomErrorController implements ErrorController {
    
        @Override
        public String getErrorPath() {
            return "/error";
        }
    
        @ResponseBody
        @GetMapping("/error")
        public String handleError(HttpServletRequest request) {
    
            Enumeration<String> headerNames1 = request.getHeaderNames();
            Enumeration<String> headerNames2 = request.getHeaderNames();
    
            String headerJson = enumIterator(headerNames1, headerNames2, request);
            System.out.println(headerJson);
    
            Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
    
            if (status != null) {
                Integer statusCode = Integer.valueOf(status.toString());
    
                if (statusCode == HttpStatus.NOT_FOUND.value()) {
                    return "404 with other message";
    
                } else if (statusCode >= 500) {
                    return "500  with other message";
    
                } else if (statusCode == HttpStatus.FORBIDDEN.value()) {
                    return "403  with other message";
                }
            }
            return "miscellaneous error";
        }
    
    
        private String enumIterator(Enumeration<String> enumList1, Enumeration<String> enumList2, HttpServletRequest request) {
    
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("{");
            boolean status = false;
    
            while (enumList1.hasMoreElements()) {
    
                if (status) {
                    stringBuilder.append(",");
                }
                status = true;
    
                stringBuilder
                        .append("\"").append(enumList1.nextElement()).append("\"")
                        .append(":")
                        .append("\"").append(request.getHeader(enumList2.nextElement())).append("\"");
            }
            stringBuilder.append("}");
    
            return stringBuilder.toString();
        }
    }
    

    或者你可以试试这个实现:

    @Component
    public class MyErrorController extends BasicErrorController {
    
        public MyErrorController(ErrorAttributes errorAttributes) {
            super(errorAttributes, new ErrorProperties());
        }
    
        @RequestMapping(produces = MediaType.APPLICATION_XML_VALUE)
        public ResponseEntity<Map<String, Object>> xmlError(HttpServletRequest request) {
    
        // ...
    
        }
    }
    

    【讨论】:

    • 问题是关于客户端,而不是服务器。
    • 是的,我正在使用 Feign 客户端与基于 Feign 的微服务进行通信。我可以坚持使用 REST 模板,但主要项目需要使用微服务提供的内容。
    【解决方案2】:

    您也许可以使用错误解码器并检查 404 状态代码。例如

    public class MyErrorDecoder implements ErrorDecoder {
    
        @Override
        public Exception decode(String methodKey, Response response) {
            if (response.status() == 404) {
               ... 
               return new YourCustomException()
    
            }
    
            return errorStatus(methodKey, response);
        }
    }
    

    https://github.com/OpenFeign/feign/wiki/Custom-error-handling

    【讨论】:

    • 这是处理错误的推荐方法。
    【解决方案3】:

    在我的情况下,我已经解决了以下问题

    import java.lang.reflect.UndeclaredThrowableException;
    
        try {
          Foo response = feignClient.getFoo(foo)
    
        } catch (Exception ex) {
             if(((ServiceMethodException)((UndeclaredThrowableException) ex).getUndeclaredThrowable()).responseCode != 404){
               throw ex;
          }
        }
    

    Vlovato 提出了完美的解决方案

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-31
      • 1970-01-01
      • 2012-09-05
      相关资源
      最近更新 更多