【问题标题】:RestTemplate - Handling response headers/body in Exceptions (RestClientException, HttpStatusCodeException)RestTemplate - 处理异常中的响应标头/正文(RestClientException,HttpStatusCodeException)
【发布时间】:2011-12-14 05:56:58
【问题描述】:

在我宁静的网络服务中,如果出现错误请求 (5xx) 或 4xx 响应代码,我会在响应中写入自定义标头“x-app-err-id”。

在客户端,我使用 RestTemplate 的交换方法进行 RestFul Web 服务调用。响应码为 2xx 时一切正常。

ResponseEntity<Component> response = restTemplate.exchange(webSvcURL,
    HttpMethod.POST, 
    requestEntity,
    Component.class);

但是如果有一个异常(HttpStatusCodeException),因为它是一个错误的请求(5xx)或 4xx,在 HttpStatusCodeException 的 catch 块中,我得到的响应(见上文)为空,所以我无法访问我的我在我的网络服务中设置的自定义标头。如果 RestTemplate 出现异常,如何从响应中获取自定义标头。

还有一个问题是,我在响应正文中设置了一个错误对象(json)以防出错,我想知道如何在 RestTemplate 出现异常时访问响应正文

【问题讨论】:

标签: response resttemplate


【解决方案1】:

我终于用 ResponseErrorHandler 做到了。

public class CustomResponseErrorHandler implements ResponseErrorHandler {

    private static ILogger logger = Logger.getLogger(CustomResponseErrorHandler.class);

    private ResponseErrorHandler errorHandler = new DefaultResponseErrorHandler();

    public void handleError(ClientHttpResponse response) throws IOException {

        List<String> customHeader = response.getHeaders().get("x-app-err-id");

        String svcErrorMessageID = "";
        if (customHeader != null) {
            svcErrorMessageID = customHeader.get(0);                
        }

        try {           

            errorHandler.handleError(response);

        } catch (RestClientException scx) {         

            throw new CustomException(scx.getMessage(), scx, svcErrorMessageID);
        }
    }

    public boolean hasError(ClientHttpResponse response) throws IOException {
        return errorHandler.hasError(response);
    }
}

然后通过如下所示的配置为 RestTemplate 使用这个自定义响应处理程序

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
   <property name="messageConverters">
       <list>
           <ref bean="jsonConverter" />
       </list>
   </property>    
   <property name="errorHandler" ref="customErrorHandler" />
</bean>

<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
   <property name="supportedMediaTypes" value="application/json" />
</bean>

<bean id="customErrorHandler " class="my.package.CustomResponseErrorHandler">
</bean>

【讨论】:

  • 您可以扩展 DefaultResponseErrorHandler 而不是实现 ResponseErrorHandler 并创建 DefaultResponseErrorHanlder 的实例。
  • 您是否设法从错误请求中读取正文(例如来自 401,403,404 等)?
【解决方案2】:

您不必创建自定义错误处理程序。您可以从抛出的 HttpStatusCodeException 中获取正文和标头。

try {
    ResponseEntity<Component> response = restTemplate.exchange(webSvcURL,
        HttpMethod.POST, 
        requestEntity,
        Component.class);
} catch (HttpStatusCodeException e) {
    List<String> customHeader = e.getResponseHeaders().get("x-app-err-id");
    String svcErrorMessageID = "";
    if (customHeader != null) {
        svcErrorMessageID = customHeader.get(0);                
    }
    throw new CustomException(e.getMessage(), e, svcErrorMessageID);
    // You can get the body too but you will have to deserialize it yourself
    // e.getResponseBodyAsByteArray()
    // e.getResponseBodyAsString()
}

【讨论】:

    【解决方案3】:

    如果您使用全局异常处理程序,请添加以下方法或检查此

    https://www.javaguides.net/2018/09/spring-boot-2-exception-handling-for-rest-apis.html 在 GlobalExceptionHandler 类中添加下面的方法

    @ExceptionHandler({HttpClientErrorException.class, HttpStatusCodeException.class, HttpServerErrorException.class})
        @ResponseBody
        public ResponseEntity<Object> httpClientErrorException(HttpStatusCodeException e) throws IOException {
            BodyBuilder bodyBuilder = ResponseEntity.status(e.getRawStatusCode()).header("X-Backend-Status", String.valueOf(e.getRawStatusCode()));
            if (e.getResponseHeaders().getContentType() != null) {
                bodyBuilder.contentType(e.getResponseHeaders().getContentType());
            }
            return bodyBuilder.body(e.getResponseBodyAsString());
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-31
      • 2019-06-02
      • 2016-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多