Пользовательская обработка исключений шаблона Rest
Я использую некоторые конечные точки REST из внешнего API, и для этой цели я использую интерфейс шаблона Rest. Я хотел бы иметь возможность создавать пользовательские исключения приложений, когда я получаю определенные коды состояния HTTP от этих вызовов. Чтобы достичь этого, я реализую интерфейс ResponseErrorHandler следующим образом:
public class MyCustomResponseErrorHandler implements ResponseErrorHandler {
private ResponseErrorHandler myErrorHandler = new DefaultResponseErrorHandler();
public boolean hasError(ClientHttpResponse response) throws IOException {
return myErrorHandler.hasError(response);
}
public void handleError(ClientHttpResponse response) throws IOException {
String body = IOUtils.toString(response.getBody());
MyCustomException exception = new MyCustomException(response.getStatusCode(), body, body);
throw exception;
}
}
public class MyCustomException extends IOException {
private HttpStatus statusCode;
private String body;
public MyCustomException(String msg) {
super(msg);
// TODO Auto-generated constructor stub
}
public MyCustomException(HttpStatus statusCode, String body, String msg) {
super(msg);
this.statusCode = statusCode;
this.body = body;
}
public HttpStatus getStatusCode() {
return statusCode;
}
public void setStatusCode(HttpStatus statusCode) {
this.statusCode = statusCode;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
наконец, это код клиента (не относящийся к делу код опущен):
public LoginResponse doLogin(String email, String password) {
HttpEntity<?> requestEntity = new HttpEntity<Object>(crateBasicAuthHeaders(email,password));
try{
ResponseEntity<LoginResponse> responseEntity = restTemplate.exchange(myBaseURL + "/user/account/" + email, HttpMethod.GET, requestEntity, LoginResponse.class);
return responseEntity.getBody();
} catch (Exception e) {
//Custom error handler in action, here we're supposed to receive a MyCustomException
if (e instanceof MyCustomException){
MyCustomException exception = (MyCustomException) e;
logger.info("An error occurred while calling api/user/account API endpoint: " + e.getMessage());
} else {
logger.info("An error occurred while trying to parse Login Response JSON object");
}
}
return null;
}
контекст моего приложения:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:spring="http://camel.apache.org/schema/spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<!-- Rest template (used in bridge communication) -->
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="errorHandler" ref="myCustomResponseErrorHandler"></property>
</bean>
<!-- Bridge service -->
<bean id="myBridgeService" class="a.b.c.d.service.impl.MyBridgeServiceImpl"/>
<!-- Bridge error handler -->
<bean id="myCustomResponseErrorHandler" class="a.b.c.d.service.handlers.MyCustomResponseErrorHandler"/>
</beans>
Я подозреваю, что я я неправильно понимаю поведение этой пользовательской обработки ошибок. Каждый метод шаблона rest может вызвать исключение RestClientException, которое после иерархии исключений является подклассом RuntimeException, а не IOException, которое создается в обработчике ошибок пользовательского ответа, т. е.: я не могу поймать свое пользовательское исключение в вызовах метода шаблона rest.
любые подсказки о том, как я мог бы поймать эти исключения? Spring RestTemplate вызывает веб-сервис с ошибками и проанализируйте код состояния очень связан, но с моей точки зрения испытывает ту же проблему, хотя она была предложена в качестве решения.
[1]:
2 ответов
вы сделали свой заказ Exception
продлить от IOException
public class MyCustomException extends IOException {
на ResponseErrorHandler#handleError()
метод вызывается из RestTemplate#handleResponseError(..)
которая вызывается RestTemplate#doExecute(..)
. Этот корневой вызов обернут в try-catch
блок, который ловит IOException
и переосмысливает его, завернутый в ResourceAccessException
, который является RestClientException
.
одна из возможностей-поймать RestClientException
и cause
.
еще одна возможность сделать свой заказ Exception
быть подтипом RuntimeException
.
вы можете создать контроллер с помощью аннотации @ControllerAdvice
Если вы используете springmvc. В контроллере пишем:
@ExceptionHandler(HttpClientErrorException.class)
public String handleXXException(HttpClientErrorException e) {
log.error("log HttpClientErrorException: ", e);
return "HttpClientErrorException_message";
}
@ExceptionHandler(HttpServerErrorException.class)
public String handleXXException(HttpServerErrorException e) {
log.error("log HttpServerErrorException: ", e);
return "HttpServerErrorException_message";
}
...
// catch unknown error
@ExceptionHandler(Exception.class)
public String handleException(Exception e) {
log.error("log unknown error", e);
return "unknown_error_message";
}
и DefaultResponseErrorHandler
кидаем эти два вида исключений:
@Override
public void handleError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = getHttpStatusCode(response);
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 RestClientException("Unknown status code [" + statusCode + "]");
}
}
и вы можете получить через:e.getResponseBodyAsString();
,e.getStatusCode();
blabla для получения ответного сообщения при возникновении исключений.