Я пытаюсь переопределить интерфейс ResponseErrorHandler, чтобы иметь возможность вернуть весь запрос (код состояния, тело и т. д.) в случае любого ответа, отличного от 2xx.
Я заметил, что Spring (RestTemplate) по умолчанию возвращает исключение в случае ответа, отличного от 2xx. Я не хочу возвращать исключение, я просто хочу иметь возможность вернуть:
new ResponseEntity(HttpStatus.STATUS_CODE)
Следуя некоторым учебникам, я нашел следующий код:
@Component
public class LoginErrorHandler
implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse httpResponse)
throws IOException {
return (
httpResponse.getStatusCode().series() == CLIENT_ERROR
|| httpResponse.getStatusCode().series() == SERVER_ERROR);
}
@Override
public void handleError(ClientHttpResponse httpResponse)
throws IOException {
if (httpResponse.getStatusCode()
.series() == SERVER_ERROR) {
// handle SERVER_ERROR
} else if (httpResponse.getStatusCode()
.series() == CLIENT_ERROR) {
// handle CLIENT_ERROR
}
}
(Ссылка)
Но я не понял, как я могу вернуть ResponseEntity без изменения возврата метода (чего я не могу реализовать, реализуя метод).
Реализация:
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new LoginErrorHandler());
return restTemplate.postForEntity(url, request, String.class);




Вы можете использовать аннотации Spring ControllerAdvice и ExceptionHandler для обработки исключений в вашем приложении. Код ниже возвращает код состояния 500 http, если в вашем запросе встречается какое-либо исключение. Вы можете добавить другие классы исключений или свой собственный пользовательский класс для обработки определенных случаев и возврата определенных кодов состояния клиенту.
Редактировать
Обработка каждого кода не будет хорошей идеей. Скорее вы можете обернуть их в свое собственное исключение и предоставить правильное сообщение своей клиентской службе. Тем не менее вы можете попробовать что-то вроде ниже.
@Component
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(HttpClientErrorException.BadRequest.class)
@ResponseStatus(code=HttpStatus.BAD_REQUEST, reason = "Bad Request", value=HttpStatus.BAD_REQUEST)
public void handleBadRequest(HttpClientErrorException.BadRequest e) {
//handle bad request exception
}
@ExceptionHandler(HttpClientErrorException.NotFound.class)
@ResponseStatus(code=HttpStatus.NOT_FOUND, reason = "Not Found", value=HttpStatus.NOT_FOUND)
public void handleNotFound(HttpClientErrorException.NotFound e) {
//handle Not Found
}
@ExceptionHandler(HttpServerErrorException.InternalServerError.class)
@ResponseStatus(code=HttpStatus.INTERNAL_SERVER_ERROR, reason = "Internal Server Error", value=HttpStatus.INTERNAL_SERVER_ERROR)
public void handleInternalServerError(HttpServerErrorException.InternalServerError e) {
//handle internal server error
}
//more methods for each code.
}
Затем обработайте коды из вашего шаблона отдыха, как показано ниже. Здесь вы не сможете вернуть тело ответа клиенту.
@Component
public class LoginErrorHandler
implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse httpResponse)
throws IOException {
return (httpResponse.getStatusCode() != HttpStatus.OK);
}
@Override
public void handleError(ClientHttpResponse httpResponse)
throws IOException {
if (httpResponse.getRawStatusCode() >=400 && httpResponse.getRawStatusCode()<500 ) {
throw HttpClientErrorException.create(httpResponse.getStatusCode(), httpResponse.getStatusText(), httpResponse.getHeaders(), null, null);
}else if (httpResponse.getRawStatusCode() >=500){
throw HttpServerErrorException.create(httpResponse.getStatusCode(), httpResponse.getStatusText(), httpResponse.getHeaders(), null, null);
}else {
//throw some other exceptions for other codes and catch them in controller advice.
}
}
}
Вам нужно использовать другие методы для других исключений. Вы не можете вернуть несколько кодов состояния для одного и того же исключения.
Я понимаю. Должен ли я что-то делать с методами «hasError» и «handleError», которые исходят от ResponseErrorHandler?
Поэтому мне не нужно использовать restTemplate.setErrorHandler(); ?
Ты можешь это сделать:
@Component
@ControllerAdvice
public class LoginErrorHandler{
@ExceptionHandler(HttpClientErrorException.class)
@ResponseBody
public void handleError(HttpClientErrorException e, HttpServletResponse response) throws IOException {
response.sendError(e.getRawStatusCode(), e.getStatusText());
}
}
Это вы генерируете весь код состояния, который должен отбрасывать исключение, и он возвращается в теле.
Существует два широко используемых и очень удобных обработчика исключений, предоставляемых средой Spring для централизованного управления исключениями в приложениях Spring Boot.
Исключение ResponseEntityExceptionHandler:, вызванное нашими методами конечной точки (методы, аннотированные @RequestMapping)
A convenient base class for
@ControllerAdviceclasses that wish to provide centralized exception handling across all@RequestMappingmethods through@ExceptionHandlermethods.
ResponseErrorHandler: Spring предоставляет хук ResponseErrorHandler, который можно реализовать для обработки исключений, создаваемых внешними службами. Для вызова любой внешней службы, скорее всего, вы будете использовать RestTemplate. RestTemplate может генерировать три типа исключений, перечисленных ниже:
HttpClientErrorException : For 4xx series status codes or Client errors.
HttpServerErrorException : For 5xx series status codes or server errors
RestClientException : Any other status codes like 3xx series
Для упрощения мы можем обрабатывать эти исключения как блок catch отдельно, но это приведет к тому, что в нашем сервисе будет разбросано много шаблонного кода. Интерфейс стратегии, используемый RestTemplate, чтобы определить, есть ли ошибка в конкретном ответе.
Есть два шага к использованию ResponseErrorHandler:
Шаг 1. Создайте собственный класс обработчика ошибок, реализуя ResponseErrorHandler и реализуя его методы hasError и handleError
Шаг 2: Нам нужно внедрить реализацию ResponseErrorHandler в экземпляр RestTemplate следующим образом:
По умолчанию в RestTemplate errorHandler указывает на DefaultResponseErrorHandler.
Привет, Нитин. Должен ли я добавить @ResponseStatus для каждого кода состояния в одном и том же методе? Или я должен использовать один метод для одного исключения? Кроме того, как мне использовать его в RestTemplate, если он не является подклассом ResponseErrorHandler?