【问题标题】:HttpClientErrorException 400 null using RestTemplate in microServicesHttpClientErrorException 400 null 在微服务中使用 RestTemplate
【发布时间】:2018-08-07 15:02:13
【问题描述】:

我有两个微服务。第一个接收来自前端的调用,然后调用第二个 uService 以接收一些数据。最后一个是返回错误响应(错误请求,这没关系 - 这是一个用例)。但是,我丢失了从第二个微服务返回的正文(消息),因为第一个在调用中抛出了 HttpClientErrorException 400 null

这是我的代码:

ResponseEntity<MyEntity> entityResponse = restTemplate.getForEntity(url, MyEntity.class, id);

我无法执行entityResponse.getStatusCode(),因为抛出了异常。

在 ControllerAdvice 中处理它,即使我从服务返回自定义消息,我的异常消息也是“400 null”。

所以,我想得到被调用的uservice中发送的响应消息来管理它。

提前致谢。

【问题讨论】:

    标签: java spring rest spring-mvc


    【解决方案1】:

    这里解释如何捕获异常和访问主体的答案是正确的。但是,您可以使用不同的方法。您可以使用发送 Http 请求并处理响应的 3-d 方库。众所周知的产品之一是 Apache commons HTTPClient:HttpClient javadocHttpClient Maven artifact。有一个鲜为人知但简单得多的 HTTPClient(我编写的开源 MgntUtils 库的一部分):MgntUtils HttpClient javadocMgntUtils maven artifactMgntUtils Github。使用这些库中的任何一个,您都可以发送 REST 请求并独立于 Spring 作为业务逻辑的一部分接收响应

    【讨论】:

    • 谢谢!我将使用 OkHttpClient。
    【解决方案2】:

    我在我的项目中正在做的事情如下。

    MicroService_2 调用 MicroService_1。

    微服务_1

    如果未找到实体,MicroService_1 会返回例如 HTTP 404 异常。

    @RestController
    @RequestMapping(value = "/api/v1/")
    public class Service1Controller {
    
    
        @RequestMapping(value = "/{id}", method = RequestMethod.GET)
        public @ResponseBody MyEntity getMyEntity(@PathVariable String id) throws NotFoundException {
            MyEntity result = ...
            if(result == null) {
                throw new NotFoundException("MyEntity [id: "+id+"] not found");
            }
    
            return result;
        }
    
    
        @ControllerAdvice
        public class RestEndpointExceptionHandler extends RestExceptionHandler {
    
            @ExceptionHandler(NotFoundException.class)
            public ResponseEntity<String> handleNotFoundException(HttpServletRequest req, NotFoundException ex) throws NotFoundException {
                return new ResponseEntity<String>(ex.getMessage(), HttpStatus.NOT_FOUND);
            }
        }
    }
    

    微服务_2

    MicroService_2调用MicroService_1并通过HTTP代码捕获异常并重新生成NotFoundException

    @Override
    public MyEntity getMyEntity(Principal principal) {
        try {
            ResponseEntity<MyEntity> entityResponse = restTemplate.getForEntity(url, MyEntity.class, id);
    
            return entityResponse.getBody();
    
        } catch(HttpClientErrorException e) {
            HttpStatus status = e.getStatusCode();
            if (status == HttpStatus.NOT_FOUND) { 
                throw new NotFoundException(e.getResponseBodyAsString()); // should be "MyEntity [id: {id}] not found"
            } else {
                throw new UnexpectedServerException(e.getResponseBodyAsString());
            }
        }
    }
    

    【讨论】:

    • 感谢您的示例,我认为它非常有用。
    【解决方案3】:

    Spring RestTemplate 在状态码为 500 或 400 的情况下会引发错误。因此,如果您的第二个服务响应错误,则第一个服务中的 RestTemplate 调用将引发异常。

    • HttpClientErrorException:在 HTTP 状态 4xx 的情况下
    • HttpServerErrorException:在 HTTP 状态 5xx 的情况下
    • UnknownHttpStatusCodeException:在 HTTP 状态未知的情况下

    要获取响应消息,您可以捕获异常。例如:

    try {
        ResponseEntity<MyEntity> entityResponse = restTemplate.getForEntity(url, MyEntity.class, id);
    } catch(HttpStatusCodeException e) {
        // e.getResponseBodyAsString();
    }
    

    或定义ResponseErrorHandlerResponseErrorHandler 可以在RestTemplate 的实例化期间设置。在handleError 方法中,您还可以访问响应消息。

    @Override
    public void handleError(ClientHttpResponse httpResponse) 
        throws IOException {
    
    }
    

    【讨论】:

    • 谢谢!我不知道 RestTemplate 在这些情况下会引发异常;)
    猜你喜欢
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    • 2016-09-06
    • 2020-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多