我正在构建一个简单的REST api用于集成目的,我希望响应尽可能一致(无论错误如何都一样)。
我过去使用过@ExceptionHandler
方法 - 所以如果我没记错的话,我很可能会选择这个类的版本... @ControllerAdvice
。
我知道它有效,我之前用过SO来帮助我,它只需要设置。这不是我的问题......
API允许创建消息和搜索消息(两个单独的请求),因此,接受内部验证的日期值。经过测试,我收到了一个非常好的格式化和令人难以置信的详细错误响应:
{
"timestamp": "2018-08-31T10:35:10.748+0000",
"status": 400,
"error": "Bad Request",
"errors": [
{
"codes": [
"typeMismatch.IntegrationMessageFilter.fromDate",
"typeMismatch.fromDate",
"typeMismatch.java.util.Date",
"typeMismatch"
],
"arguments": [
{
"codes": [
"IntegrationMessageFilter.fromDate",
"fromDate"
],
"arguments": null,
"defaultMessage": "fromDate",
"code": "fromDate"
}
],
"defaultMessage": "Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'fromDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@com.fasterxml.jackson.annotation.JsonFormat java.util.Date] for value '213-456-45'; nested exception is java.lang.IllegalArgumentException",
"objectName": "IntegrationMessageFilter",
"field": "fromDate",
"rejectedValue": "213-456-45",
"bindingFailure": true,
"code": "typeMismatch"
}
],
"message": "Validation failed for object='IntegrationMessageFilter'. Error count: 1",
"path": "/Integration/get"
}
我想要做的是拦截这个错误并将其包装在我自己的响应对象中,该对象对于每个可用的API方法都是相同的响应对象:例如
{
"success": Boolean,
"messageId": Integer, (null on search, int on successful create)
"messages": Array, (searched IntegrationMessage objects)
"errorMessage": String, (error message during manual validation (e.g. range validation depending on the field))
"error" [SPRING DEFAULT ERROR] (this is what i want to intercept from spring-boot and include in this response object)
}
当系统已经完成它时,手动提示有关创建详细错误消息的意义有点毫无意义...我不知道它用于创建上面的第一个JSON消息的对象,或者即使我可以拦截它。
注意:这纯粹是为了方便API用户不必区分不同的响应对象,以及方便我,而不必重新开发轮子(可以这么说)。
好的,所以我已经找到了如何实现(某种程度)我想要的东西。
我的印象是,我可以拦截完整的异常响应消息,并将其放在我的对象中,无论异常类型如何。事实证明,我可以获得大多数默认信息,但它特定于每种错误类型(显然)。
第一次尝试:
我的第一次尝试是使用以下内容简单地“测试”默认错误响应。这是为了确定春天正在做什么(它正在使用哪个错误 - 我认为它本来就是handleTypeMismatch
例外) - 下面的方法只是类中的一个(我正在处理的那个):
@ControllerAdvice
public class IntegrationExceptionHandler extends ResponseEntityExceptionHandler
{
@Override
public ResponseEntity<Object> handleBindException(final BindException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request)
{
return super.handleBindException(ex, headers, status, request);
}
}
我期望与默认错误消息完全相同的错误消息,但这没有产生响应(或空响应?)。
我的“解决方案”: 虽然我不需要重新开发轮子,但我必须做一些箍跳:
@Override
public ResponseEntity<Object> handleBindException(final BindException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request)
{
IntegrationResponse response = new IntegrationResponse(ex.getMessage());
response.setErrors(ex.getBindingResult().getAllErrors());
return new ResponseEntity<Object>(response, headers, status);
}
错误是private List<ObjectError> errors;
(org.springframework.validation.ObjectError
)
因此,我将不得不尝试复制ResponseEntityExceptionHandler
中的每个可覆盖错误(这适用于我的情况)并稍微区别对待它,您现在可以看到为什么我只想包装现有的响应。
正如旁注,我确实尝试添加:private Object error;
和private BindingResult error;
作为我的响应对象中的变量,但是两次尝试似乎都拒绝我的响应对象并显示JUST默认消息(好像没有控制器建议)没有提示为什么。
如果有人确实发现如何跳过ResponseEntityExceptionHandler
步骤并只包装默认的异常响应对象,我将很乐意接受这个答案。