RestTemplate custom exception handling (rpm)

Transfer: https://ethendev.github.io/2018/11/06/RestTemplate-error-handler/

Some API error message is returned by the body Response. HttpClient can use to get the normal error in the StatusCode and body. However, the use RestTemplate, directly throw the following exception. If you want to get the raw information and further treatment would be more trouble.

org.springframework.web.client.HttpClientErrorException: 404 null
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94)
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:79)
    at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:777)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:730)
    at org.springframework.web.client.RestTemplate.execute (RestTemplate.java: 704 ) 
    at org.springframework.web.client.RestTemplate.exchange (RestTemplate.java: 621 )

RestTemplate exception handling process

The following look at the reasons, RestTemplate in getForObject, getForEntity and exchange and other commonly used methods are ultimately call doExecute method. The following is a method of source doExecute

public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {

    private ResponseErrorHandler errorHandler;
    ......
    
    @Nullable
    protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
        Assert.notNull(url, "'url' must not be null");
        Assert.notNull(method, "'method' must not be null");
        ClientHttpResponse response = null;

        String resource;
        try {
            ClientHttpRequest request = this.createRequest(url, method);
            if (requestCallback != null) {
                requestCallback.doWithRequest(request);
            }

            response = request.execute();
            // 处理 Response
            this.handleResponse(url, method, response);
            if (responseExtractor != null) {
                Object var14 = responseExtractor.extractData(response);
                return var14;
            }

            resource = null;
        } catch (IOException var12) {
            resource = url.toString();
String query = url.getRawQuery(); resource = query != null ? resource.substring(0, resource.indexOf(63)) : resource; throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + var12.getMessage(), var12); } finally { if (response != null) { response.close(); } } return resource; } protected void handleResponse(URI url, HttpMethod method, ClientHttpResponse response) throws IOException { ResponseErrorHandler errorHandler = this.getErrorHandler(); boolean hasError = errorHandler.hasError(response); if (this.logger.isDebugEnabled()) { try { this.logger.debug(method.name() + " request for \"" + url + "\" resulted in " + response.getRawStatusCode() + " (" + response.getStatusText() + ")" + (hasError ? "; invoking error handler" : "")); } catch (IOException var7) { ; } } // 异常处理 if (hasError) { errorHandler.handleError(url, method, response); } } }

As can be seen from the following code, DefaultResponseErrorHandler captured and throws an exception.

public class DefaultResponseErrorHandler implements ResponseErrorHandler {
    ...
    
    protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException {
        switch(statusCode.series()) {
        case CLIENT_ERROR:
            throw new HttpClientErrorException(statusCode, response.getStatusText(), response.getHeaders(), this.getResponseBody(response), this.getCharset(response));
        case SERVER_ERROR:
            throw new HttpServerErrorException(statusCode, response.getStatusText(), response.getHeaders(), this.getResponseBody(response), this.getCharset(response));
        default:
            throw new UnknownHttpStatusCodeException(statusCode.value(), response.getStatusText(), response.getHeaders(), this.getResponseBody(response), this.getCharset(response));
        }
    }
}

If you want to own capture anomalies, abnormal deal with their own words can be achieved by implementing ResponseErrorHandler class. Its source code is as follows:

 

public  interface ResponseErrorHandler { 

    // indicate Response if there are any errors. Implementation class will usually check Response of HttpStatus. 
    hasError boolean (ClientHttpResponse var1) throws IOException; 

    // processing Response errors when HasError Returns true if this method is invoked. 
    void handleError (ClientHttpResponse var1) throws IOException; 

    // alternative handleError provide access requesting additional information and the URL of the HTTP method. 
    default  void the handleError (the URI URL, HttpMethod Method, ClientHttpResponse Response) throws IOException {
         the this .handleError (Response); 
    } 
}

Custom exception handling RestTemplate

If you imagine HttpClient get the same error message HttpStatus and body directly from the Response without throwing an exception, can be achieved through the following code:

public class CustomErrorHandler implements ResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        return true;
    }

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

    }
}

Exception class is provided RestTemplate

restTemplate.setErrorHandler(new CustomErrorHandler());
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, null, String.class);
System.out.println(response.getBody());

Output

{"code":404,"result":null,"message":"Resources not found"

Guess you like

Origin www.cnblogs.com/guanbin-529/p/11489264.html