spring - 如何确保解析期间的异常导致与验证失败返回的(自定义)响应相同类型的响应?

标签 spring validation error-handling request-mapping custom-error-handling

我正在使用 Spring 创建一个 API,但是我在引入关于请求正文验证(的一部分)的自定义错误报告时遇到了一些麻烦。

当发生解析/验证错误时,我想将自定义响应返回给用户。
这适用于用 @Valid 注释的字段。以及像 @javax.validation.constraints.NotNull 这样的验证器通过使用自定义 ResponseEntityExceptionHandler@ControllerAdvice 注释.
但是,如果在解析请求正文时抛出异常(甚至在验证运行之前),它就不起作用。在这种情况下,我会得到一个状态为 500 (Server Error) 的 html 错误页面

如何确保解析过程中的异常导致与我因验证失败而返回的(自定义)响应相同类型的响应?

我的端点代码如下所示:

@RequestMapping(value= "/endpoint"
    produces = { "application/json" }, 
    consumes = { "application/json" },
    method = RequestMethod.POST)
default ResponseEntity<Object> postSomething(@Valid @RequestBody MyRequestBody requestData){
    // ...
}

MyRequestBody 类如下所示:
@Validated
public class MyRequestData {

    @JsonProperty("stringValue")
    private String stringValue = null;

    @NotNull
    @Valid
    public String getStringValue() {
        return stringValue;
    }

    // ...

    public enum EnumValueEnum {
        VALUE_1("value 1"),
        VALUE_1("value 2");

        private String value;

        EnumValueEnum(String value) {
            this.value = value;
        }

        @Override
        @JsonValue
        public String toString() {
            return String.valueOf(value);
        }

        @JsonCreator
        public static EnumValueEnum fromValue(String text) {
          if(text == null){
            return null;
          }
          for (EnumValueEnum b : EnumValueEnum.values()){
            if (String.valueOf(b.value).equals(text)) {
              return b;
            }
          }
          throw new HttpMessageNotReadableException("EnumValueEnum \"" + text + "\" does not exist");
        }

    }

    @JsonProperty("enumValue")
    private EnumValueEnum enumValue = null;
}

自定义验证错误处理(和报告)如下所示:
@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class MyValidationHandler extends ResponseEntityExceptionHandler {
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // return status(BAD_REQUEST).body(new ValidationResponse(ex.getBindingResult().getFieldErrors()));
    }

    @Override
    protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        // return status(BAD_REQUEST).body(new ValidationResponse((JsonMappingException) ex.getCause()));
    }
}

在此代码中,如果用户使用不存在的枚举值发送请求,则会引发 HttpMessageNotReadableException。我想在某处捕获它并将其替换为与我所做的其他异常处理一致的自定义响应。我在哪里/如何做到这一点?

最佳答案

我找到了解决我自己问题的方法。

您实际上可以使用 Spring MVC 的正常异常处理:

使用 @ExceptionHandler 注释方法将使 Spring 尝试使用它来处理指定的异常类型(在注释的值字段或方法的参数中)。这个方法可以放在 Controller 中,甚至可以放在ResponseEntityExceptionHandler我用于其他验证响应处理。

@ExceptionHandler
public ResponseEntity handle(HttpMessageConversionException e){
    // return status(BAD_REQUEST).body(new ValidationResponse((JsonMappingException) e.getCause()));
}

请注意您处理哪种类型的异常:

这里的问题是解析时抛出的异常包含在(的某些子类型)中 JsonMappingException反过来又被包裹在 HttpMessageConversionException 中.
e instanceof HttpMessageConversionException
e.getCause() instanceof JsonMappingException
e.getCause().getCause() // == your original exception
@ExceptionHandler因此应该接受HttpMessageConversionException而不是最初抛出的异常(在我的情况下是 HttpMessageNotReadableException )

如果你写一个 @ExceptionHandler 它将不起作用只接受你原来的异常!

关于spring - 如何确保解析期间的异常导致与验证失败返回的(自定义)响应相同类型的响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52425015/

相关文章:

java - Spring Web Flow - 页面上的多个表单 - 验证正确的表单

java - 涉及属性和元素的自定义 JSP TLD

java - 带有编码参数的 RestTemplate

.net - 强大的插件/插件管理的良好架构/库

java - 有没有办法根据参数值使 MySQL 查询行为不同?

ruby-on-rails - NoMethodError(未定义的方法 `validate' 为真 :TrueClass)

html - 类型 'nameFormControl' 上不存在属性 'ContactComponent'

java - 使用 Struts 2 进行客户端验证时出现问题。无法识别基于 Xml 的验证规则

javascript - 如何在 Node js中记录特定的错误消息?

asp.net-mvc-3 - 页面出现错误时向网站管理员发送电子邮件