在自定义对象中包装默认 REST 错误响应

Wrapping default REST error response in custom object

我正在构建一个简单的 REST api 用于集成目的,我希望响应尽可能一致(无论错误如何都相同)。

我过去使用过 @ExceptionHandler 方法 - 所以我很可能会使用此方法的 class 版本...@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用户不用区分不同的响应对象,也方便我,不用重新-开发轮子(可以这么说)。

好的,我已经找到了实现(某种程度上)我想要的东西的方法。

我的印象是我可以拦截完整的异常响应消息并将其放入我的对象中,而不管异常的类型。事实证明,我可以获得 大多数 的默认信息,但它特定于每种错误类型(显然)。

第一次尝试:
我的第一次尝试是简单地 "test" 带有以下内容的默认错误响应。这是为了确定 spring 在做什么(它使用了哪个错误 - 我真的认为它会是 handleTypeMismatch 异常) - 下面的方法只是 class 中的一个(我目前正在处理的那个):

@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);
    }
}

我预计会出现与默认错误消息完全相同的错误消息,但是这没有产生任何响应(或空响应?)。

我的"Solution":
虽然我不必重新开发轮子,但我确实需要做一些跳环运动:

    @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; 作为我的响应对象中的变量,但是这两种尝试似乎都拒绝了我的响应对象并仅显示默认消息(好像没有控制器建议),没有提示为什么。

如果有人确实发现了如何跳过 ResponseEntityExceptionHandler 步骤并只包装默认的异常响应对象,我会很乐意接受这个答案。