Spring RestTemplate 与任何非 200 OK 响应交换 POST HttpClientException
Spring RestTemplate exchange POST HttpClientException with any non 200 OK response
所以我目前遇到的问题是
Servlet.service() for servlet [dispatcherServlet] in context with path
[] threw exception [Request processing failed; nested exception is
org.springframework.web.client.HttpClientErrorException: 404 null]
with root cause
org.springframework.web.client.HttpClientErrorException 404 null
当我的服务器代码响应 OK 200 响应以外的任何内容时,在我的客户端代码中。所以在这种情况下,我故意在我的服务器代码中返回一个 404 响应,使用 header 和 body,并且没有 header 和 body,但我仍然得到我在服务器代码中响应的 HTTP 状态代码和 null 的相同异常,在这种情况下,我假设是响应的 body。最初在我的服务器代码中我总是返回一个 ResponseEntity<>("Sent", HttpStatus.OK)
但是因为在我的服务器代码中我在其他地方发出了一个 HTTP 请求如果响应不是 200 OK 那么我的客户端代码将不知道它因此我是将从我的服务器代码中的 HTTP 请求返回的实际响应返回到我的客户端代码,这就是我 运行 遇到此问题的时候。
客户代码
public String callFruitBasket(Fruit fruitRequest) {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Fruit> fruit = new HttpEntity<>(fruitRequest, requestHeaders);
System.out.println("Fruit headers: " + fruit.getHeaders());
ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
System.out.println("Full response: " + response);
return response.getBody();
}
服务器代码
@PostMapping("/fruitBasket/send")
public ResponseEntity<String> sendFruitBasket(@RequestBody Fruit fruit) {
// works fine, old response
// return new ResponseEntity<>("Sent", HttpStatus.OK);
return new ResponseEntity<>("Baaad Request", HttpStatus.BAD_REQUEST);
}
所以目前在我的服务器代码中我没有在我的响应中添加任何 headers 但我已经尝试添加 Content-Type 但是我发现我仍然得到相同的结果我的客户端代码中出现异常,所以我 100% 确定问题出在我的客户端代码中的某个地方。最初,当我通过 200 OK 响应时,完整响应的打印输出在客户端代码中显示为:
Full Response: <200 OK,Sent,{Content-Type=[text/plain;charset=UTF-8], Content-Length=[4], Date=[Sat, 19 May 2018 09:10:21 GMT]}>
我对任何其他 Http 状态代码(如 400 和 404)的期望是相同的,但响应中是 400 或 404 而不是 200 OK。
我试过在客户端和服务器代码中使用 headers,正如我在这里的各种帖子中读到的那样,这通常是导致出现此类异常的原因,这让我相信可能存在某些问题我的客户端代码中基本缺失,或者这是 exchange() 的预期行为,我误解了它。
这里没有任何问题。如果您收到错误的状态代码,将抛出此异常。
您只需要将客户端代码包装在 try-catch
中并捕获异常,然后用它做任何您想做的事情。
try {
ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
} catch (HttpStatusCodeException e) {
e.getMessage();
}
RestTemplate 在遇到错误响应代码时的默认行为是抛出异常。如果是 4xx,它是 HttpClientErrorException
,如果是 5xx:HttpServerErrorException
(都扩展 HttpStatusCodeException
)。 Spring 通过使用 ResponseErrorHandler (and it's default imlpementation - DefaultResponseErrorHandler)
实现
处理这种情况的一种方法是抓住它们:
try {
ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
} catch(HttpClientErrorException e) {
//handle 4xx errors
} catch(HttpServerErrorException e) {
//handle 5xx errors
}
如果您需要自定义此行为(其他一些 API 在向某些请求发送合法响应时使用这些代码,然后您可能希望像处理 2xx 响应一样进行处理),您可以创建您自己的 ResponseErrorHandler
实现,方法是实现它或扩展 DefaultResponseHandler
,然后在初始化期间向 RestTemplate 注册您的处理程序:
public class MyResponseErrorHandler extends DefaultResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
// check if response code is an error in here or just use default implementation
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// handle different response codes
// (default spring behaviour is throwing an exception)
}
}
并注册:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new MyResponseErrorHandler());
// now RestTemplate's behaviour for error status codes is customized
所以我目前遇到的问题是
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 404 null] with root cause org.springframework.web.client.HttpClientErrorException 404 null
当我的服务器代码响应 OK 200 响应以外的任何内容时,在我的客户端代码中。所以在这种情况下,我故意在我的服务器代码中返回一个 404 响应,使用 header 和 body,并且没有 header 和 body,但我仍然得到我在服务器代码中响应的 HTTP 状态代码和 null 的相同异常,在这种情况下,我假设是响应的 body。最初在我的服务器代码中我总是返回一个 ResponseEntity<>("Sent", HttpStatus.OK)
但是因为在我的服务器代码中我在其他地方发出了一个 HTTP 请求如果响应不是 200 OK 那么我的客户端代码将不知道它因此我是将从我的服务器代码中的 HTTP 请求返回的实际响应返回到我的客户端代码,这就是我 运行 遇到此问题的时候。
客户代码
public String callFruitBasket(Fruit fruitRequest) {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Fruit> fruit = new HttpEntity<>(fruitRequest, requestHeaders);
System.out.println("Fruit headers: " + fruit.getHeaders());
ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
System.out.println("Full response: " + response);
return response.getBody();
}
服务器代码
@PostMapping("/fruitBasket/send")
public ResponseEntity<String> sendFruitBasket(@RequestBody Fruit fruit) {
// works fine, old response
// return new ResponseEntity<>("Sent", HttpStatus.OK);
return new ResponseEntity<>("Baaad Request", HttpStatus.BAD_REQUEST);
}
所以目前在我的服务器代码中我没有在我的响应中添加任何 headers 但我已经尝试添加 Content-Type 但是我发现我仍然得到相同的结果我的客户端代码中出现异常,所以我 100% 确定问题出在我的客户端代码中的某个地方。最初,当我通过 200 OK 响应时,完整响应的打印输出在客户端代码中显示为:
Full Response: <200 OK,Sent,{Content-Type=[text/plain;charset=UTF-8], Content-Length=[4], Date=[Sat, 19 May 2018 09:10:21 GMT]}>
我对任何其他 Http 状态代码(如 400 和 404)的期望是相同的,但响应中是 400 或 404 而不是 200 OK。 我试过在客户端和服务器代码中使用 headers,正如我在这里的各种帖子中读到的那样,这通常是导致出现此类异常的原因,这让我相信可能存在某些问题我的客户端代码中基本缺失,或者这是 exchange() 的预期行为,我误解了它。
这里没有任何问题。如果您收到错误的状态代码,将抛出此异常。
您只需要将客户端代码包装在 try-catch
中并捕获异常,然后用它做任何您想做的事情。
try {
ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
} catch (HttpStatusCodeException e) {
e.getMessage();
}
RestTemplate 在遇到错误响应代码时的默认行为是抛出异常。如果是 4xx,它是 HttpClientErrorException
,如果是 5xx:HttpServerErrorException
(都扩展 HttpStatusCodeException
)。 Spring 通过使用 ResponseErrorHandler (and it's default imlpementation - DefaultResponseErrorHandler)
处理这种情况的一种方法是抓住它们:
try {
ResponseEntity<String> response = restTemplate.exchange(fruitBasketUrl, HttpMethod.POST, fruit, String.class);
} catch(HttpClientErrorException e) {
//handle 4xx errors
} catch(HttpServerErrorException e) {
//handle 5xx errors
}
如果您需要自定义此行为(其他一些 API 在向某些请求发送合法响应时使用这些代码,然后您可能希望像处理 2xx 响应一样进行处理),您可以创建您自己的 ResponseErrorHandler
实现,方法是实现它或扩展 DefaultResponseHandler
,然后在初始化期间向 RestTemplate 注册您的处理程序:
public class MyResponseErrorHandler extends DefaultResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
// check if response code is an error in here or just use default implementation
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
// handle different response codes
// (default spring behaviour is throwing an exception)
}
}
并注册:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new MyResponseErrorHandler());
// now RestTemplate's behaviour for error status codes is customized