我正在使用Spring Boot构建一个应用程序。此应用程序是分布式的,这意味着我有多个相互调用的API。
我的基础服务之一与数据库进行交互并以请求的数据进行响应。如果请求不存在的ID,我将返回404 HttpStatus:
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
(与某些操作上的400错误相同,或对于删除条目而言为204等)。
问题是我还有一些其他的Spring Boot应用程序调用这些API,org.springframework.web.client.HttpClientErrorException: 404 Not Found在它们请求不存在的条目时会抛出异常。但是404状态码是有意的,并且不应返回此异常(导致Hystrix断路器调用其后备功能)。
org.springframework.web.client.HttpClientErrorException: 404 Not Found
我怎么解决这个问题?
在我的代码中,对服务的调用是这样实现的: ResponseEntity<Object> data = restTemplate.getForEntity(url, Object.class);
ResponseEntity<Object> data = restTemplate.getForEntity(url, Object.class);
我的RestTemplate设置如下:
private RestTemplate restTemplate = new RestTemplate();
Spring RestTemplate使用ResponseErrorHandler来处理响应中的错误。此接口提供了一种确定响应是否有错误(ResponseErrorHandler#hasError(ClientHttpResponse))以及如何处理该错误(ResponseErrorHandler#handleError(ClientHttpResponse))的方式。
RestTemplate
ResponseErrorHandler
ResponseErrorHandler#hasError(ClientHttpResponse)
ResponseErrorHandler#handleError(ClientHttpResponse)
您可以设置RestTemplate的ResponseErrorHandler与RestTemplate#setErrorHandler(ResponseErrorHandler)它的javadoc状态
RestTemplate#setErrorHandler(ResponseErrorHandler)
默认情况下,RestTemplate使用DefaultResponseErrorHandler。
DefaultResponseErrorHandler
此默认实现
[…]检查以下代码上的状态代码 ClientHttpResponse:任何带有系列 HttpStatus.Series.CLIENT_ERROR或被HttpStatus.Series.SERVER_ERROR认为是错误的代码。可以通过重写hasError(HttpStatus)方法来更改此行为。
ClientHttpResponse
HttpStatus.Series.CLIENT_ERROR
HttpStatus.Series.SERVER_ERROR
hasError(HttpStatus)
如果发生错误,它将引发您所看到的异常。
如果您想更改此行为,则可以提供自己的ResponseErrorHandler实现(也许通过重写DefaultResponseErrorHandler),该实现不会将4xx视为错误或不会引发异常。
例如
restTemplate.setErrorHandler(new ResponseErrorHandler() { @Override public boolean hasError(ClientHttpResponse response) throws IOException { return false; // or whatever you consider an error } @Override public void handleError(ClientHttpResponse response) throws IOException { // do nothing, or something } });
然后,您可以检查ResponseEntity返回的状态码getForEntity并自行处理。
ResponseEntity
getForEntity