Spring RestTemplate - 重写ResponseErrorHandler

时间:2014-05-23 21:45:36

标签: spring rest spring-mvc resttemplate

我通过ReST拨打RestTemplate服务,并尝试覆盖ResponseErrorHandler中的Spring 3.2来处理自定义错误代码。

CustomResponseErrroHandler

public class MyResponseErrorHandler implements ResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        boolean hasError = false;
        int rawStatusCode = response.getRawStatusCode();
        if (rawStatusCode != 200){
            hasError = true;
        }
        return hasError;
     }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        //String body = IOUtils.toString(response.getBody());
        throw new CustomServiceException(response.getRawStatusCode() , "custom Error");
   }
}

Spring框架调用hasError方法但不调用handleError,因此我无法抛出自定义异常。在深入研究Spring RestTemplate源代码后,我意识到handleResponseError方法中的代码导致了问题 - 它正在寻找response.getStatusCoderesponse.getStatusText并投掷异常(当Rest服务抛出异常时,statusCode / statusText为null)并且它从不在下一行调用自定义实现或默认handleError方法。

Spring RestTemplate handleResponse方法的源代码:

private void handleResponseError(HttpMethod method, URI url, ClientHttpResponse response) throws IOException {
    if (logger.isWarnEnabled()) {
        try {
            logger.warn(method.name() + " request for \"" + url + "\" resulted in " +
response.getStatusCode() + " (" + response.getStatusText() + "); invoking error handler");
        }
        catch (IOException e) {
            // ignore
        }
    }
    getErrorHandler().handleError(response);
}

仅供参考,当服务抛出异常时,我可以读取rawstatuscode而不是响应中的状态代码

如何绕过这个框架代码并调用我的自定义处理程序? 感谢您的帮助。

2 个答案:

答案 0 :(得分:16)

以下链接提供了有关Exception Flow for Spring ResponseErrorHandler的有用信息。

在这里添加代码,只是在博客关闭的情况下:

ErrorHandler的代码:

public class MyResponseErrorHandler implements ResponseErrorHandler {

    private static final Log logger = LogFactory.getLog(MyResponseErrorHandler.class);

    @Override
    public void handleError(ClientHttpResponse clienthttpresponse) throws IOException {

        if (clienthttpresponse.getStatusCode() == HttpStatus.FORBIDDEN) {
            logger.debug(HttpStatus.FORBIDDEN + " response. Throwing authentication exception");
            throw new AuthenticationException();
        }
    }

    @Override
    public boolean hasError(ClientHttpResponse clienthttpresponse) throws IOException {

        if (clienthttpresponse.getStatusCode() != HttpStatus.OK) {
            logger.debug("Status code: " + clienthttpresponse.getStatusCode());
            logger.debug("Response" + clienthttpresponse.getStatusText());
            logger.debug(clienthttpresponse.getBody());

            if (clienthttpresponse.getStatusCode() == HttpStatus.FORBIDDEN) {
                logger.debug("Call returned a error 403 forbidden resposne ");
                return true;
            }
        }
        return false;
    }
}

在RestTemplate中使用它的代码:

RestTemplate restclient = new RestTemplate();
restclient.setErrorHandler(new MyResponseErrorHandler());
ResponseEntity<String> responseEntity = clientRestTemplate.exchange(
                    URI,
                    HttpMethod.GET,
                    requestEntity,
                    String.class);
                response = responseEntity.getBody();

答案 1 :(得分:2)

我没有看到您的RestTemplate代码,但我假设您将ResponseErrorHandler RestTemplate设置为使用:

RestTemplate restClient = new RestTemplate();
restClient.setErrorHandler(new MyResponseErrorHandler());

handleError方法确实引发了异常。您可以找到如何使用one of my previous answers中的CustomException投放CustomResponseHandler