使用 Spring Rest 模板处理超时和其他 IO 异常的常用方法
Common approach for handling of timeout and other IO exceptions with Spring Rest Template
问题
我有大约 40 种使用 RestTemplate 进行 HTTP 调用的方法。此时我决定创建一个错误处理程序,它将 RestTemplateException 映射到我自己的异常(例如 MyApplicationRestException)。
考虑的方法
用try/catch
包装所有调用
1.1 缺点:应该更新所有 40 个方法。在新方法中很容易忘记那些try/catch
org.springframework.web.client.ResponseErrorHandler
2.1 缺点:出于某种原因,它只捕获 statusCode != null 的异常。所以它不能处理超时。
引入一个新的方面,它将捕获所有 RestTemplateException 并正确处理它们。它解决了以前解决方案的所有缺点,但我总是将方面作为最后的选择。
有没有更好的解决方案?
最后我想出了一个方面:
@Aspect
@Component
public class RestCallsExceptionHandlingAspect {
@AfterThrowing(pointcut = "execution(* eu.mypackage.RestClient.*(..))", throwing = "e")
public void handle(Exception e) throws Throwable {
if (e instanceof RestClientException) {
if (e instanceof HttpStatusCodeException) {
if (((HttpStatusCodeException)e).getStatusCode().is4xxClientError()) {
throw new TranslatableException(e, ValidationErrorGroup.COMMUNICATION_ERROR, CommonErrorCode.CLIENT_ERROR.name());
} else {
throw new TranslatableException(e, ValidationErrorGroup.COMMUNICATION_ERROR, CommonErrorCode.SERVER_ERROR.name());
}
} else {
throw new TranslatableException(e, ValidationErrorGroup.COMMUNICATION_ERROR, CommonErrorCode.CORE_IO_ERROR.name());
}
}
throw e;
}
}
问题
我有大约 40 种使用 RestTemplate 进行 HTTP 调用的方法。此时我决定创建一个错误处理程序,它将 RestTemplateException 映射到我自己的异常(例如 MyApplicationRestException)。
考虑的方法
用try/catch
包装所有调用1.1 缺点:应该更新所有 40 个方法。在新方法中很容易忘记那些try/catch
org.springframework.web.client.ResponseErrorHandler
2.1 缺点:出于某种原因,它只捕获 statusCode != null 的异常。所以它不能处理超时。
引入一个新的方面,它将捕获所有 RestTemplateException 并正确处理它们。它解决了以前解决方案的所有缺点,但我总是将方面作为最后的选择。
有没有更好的解决方案?
最后我想出了一个方面:
@Aspect
@Component
public class RestCallsExceptionHandlingAspect {
@AfterThrowing(pointcut = "execution(* eu.mypackage.RestClient.*(..))", throwing = "e")
public void handle(Exception e) throws Throwable {
if (e instanceof RestClientException) {
if (e instanceof HttpStatusCodeException) {
if (((HttpStatusCodeException)e).getStatusCode().is4xxClientError()) {
throw new TranslatableException(e, ValidationErrorGroup.COMMUNICATION_ERROR, CommonErrorCode.CLIENT_ERROR.name());
} else {
throw new TranslatableException(e, ValidationErrorGroup.COMMUNICATION_ERROR, CommonErrorCode.SERVER_ERROR.name());
}
} else {
throw new TranslatableException(e, ValidationErrorGroup.COMMUNICATION_ERROR, CommonErrorCode.CORE_IO_ERROR.name());
}
}
throw e;
}
}