Recently, when using RestTemplate to access external resources, an interesting problem was found. Because the permission verification fails, the http code of 401 returned by the other party will also contain some exception prompt information in the returned data. However, when using RestTemplate to access, the following exception of 401 prompt is thrown directly, and the prompt information cannot be obtained
So what can RestTemplate do if you want to get non-200 status code return data?
<!-- more -->
1. Exception capture
1. Problem analysis
The exception handling of RestTemplate is done with the help of org.springframework.web.client.ResponseErrorHandler. First, look at the two core methods
- The following code is from spring-web.5.0.7.RELEASE
public interface ResponseErrorHandler { // Judge whether there is abnormality boolean hasError(ClientHttpResponse response) throws IOException; // If there is a problem, enter this method and deal with it void handleError(ClientHttpResponse response) throws IOException; }
In short, when the RestTemplate sends out a request and obtains the corresponding response of the other party, it will give it to the ResponseErrorHandler to determine whether the returned result is ok or not
So next, target the default exception handler of RestTemplate: org.springframework.web.client.DefaultResponseErrorHandler
a. Determine whether the returned result is ok
From the source, it is mainly based on the returned http code to determine whether it is ok
// Judge whether there is a problem according to the returned http code @Override public boolean hasError(ClientHttpResponse response) throws IOException { HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode()); return (statusCode != null && hasError(statusCode)); } // The specific decision logic is simply that the returned http code is standard 4xx and 5xx, so it is considered that there is a problem protected boolean hasError(HttpStatus statusCode) { return (statusCode.series() == HttpStatus.Series.CLIENT_ERROR || statusCode.series() == HttpStatus.Series.SERVER_ERROR); }
Please note that in the above implementation, some custom HTTP codes will not be considered as exceptions because they cannot be converted to corresponding HttpStatus (described in the following example)
b. Exception handling
When the above hasError returns ture, it will enter the exception handling logic
@Override public void handleError(ClientHttpResponse response) throws IOException { HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode()); if (statusCode == null) { throw new UnknownHttpStatusCodeException(response.getRawStatusCode(), response.getStatusText(), response.getHeaders(), getResponseBody(response), getCharset(response)); } handleError(response, statusCode); } protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException { switch (statusCode.series()) { case CLIENT_ERROR: throw new HttpClientErrorException(statusCode, response.getStatusText(), response.getHeaders(), getResponseBody(response), getCharset(response)); case SERVER_ERROR: throw new HttpServerErrorException(statusCode, response.getStatusText(), response.getHeaders(), getResponseBody(response), getCharset(response)); default: throw new UnknownHttpStatusCodeException(statusCode.value(), response.getStatusText(), response.getHeaders(), getResponseBody(response), getCharset(response)); } }
It can also be seen from the above that the exception handling logic is very simple, and the exception is thrown directly
2. Exception capture
After locating the problem of raw surface, it's relatively easy to solve the problem again. You can customize an exception handling class and think it's normal no matter what the status code returns
RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){ @Override protected boolean hasError(HttpStatus statusCode) { return super.hasError(statusCode); } @Override public void handleError(ClientHttpResponse response) throws IOException { } });
3. measurement
First, write two results. The returned http status code is not 200. There are many ways to write case s that return non 200 status code. Here are two common ways to write
@RestController public class HelloRest { @GetMapping("401") public ResponseEntity<String> _401(HttpServletResponse response) { ResponseEntity<String> ans = new ResponseEntity<>("{\"code\": 401, \"msg\": \"some error!\"}", HttpStatus.UNAUTHORIZED); return ans; } @GetMapping("525") public String _525(HttpServletResponse response) { response.setStatus(525); return "{\"code\": 525, \"msg\": \"Custom error code!\"}"; } }
First, let's take a look at the custom 525 and standard 401 http code, which are directly accessed through the RestTemplate
@Test public void testCode() { RestTemplate restTemplate = new RestTemplate(); HttpEntity<String> ans = restTemplate.getForEntity("http://127.0.0.1:8080/525", String.class); System.out.println(ans); ans = restTemplate.getForEntity("http://127.0.0.1:8080/401", String.class); System.out.println(ans); }
It can also be seen from the above output results that non-standard http code does not throw exceptions (the reasons are analyzed above). Next, let's look at the case s where even standard http code does not want to throw exceptions
@Test public void testSend() { String url = "http://127.0.0.1:8080/401"; RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){ @Override protected boolean hasError(HttpStatus statusCode) { return super.hasError(statusCode); } @Override public void handleError(ClientHttpResponse response) throws IOException { } }); HttpEntity<String> ans = restTemplate.getForEntity(url, String.class); System.out.println(ans); }
II. other
0. project
1. A grey Blog
The best letter is not as good as the above. It's just a one-of-a-kind remark. Due to the limited personal ability, there are inevitably omissions and mistakes. If you find a bug or have better suggestions, you are welcome to criticize and correct. Thank you very much
Here is a grey personal blog, recording all the blogs in study and work. Welcome to visit
- A grey Blog personal Blog https://blog.hhui.top
- A grey blog spring special blog http://spring.hhui.top