簡體   English   中英

如何確定解析期間的異常導致與針對驗證失敗返回的(自定義)響應相同的響應?

[英]How can I make sure exceptions during parsing lead to the same kind of response as the (custom) response returned for validation failures?

我正在使用Spring創建一個API,但是在請求正文驗證(的一部分)中引入自定義錯誤報告時遇到了一些麻煩。

發生解析/驗證錯誤時,我想將自定義響應返回給用戶。
這對於使用@Valid注釋的字段以及@javax.validation.constraints.NotNull的驗證器(通過使用@ControllerAdvice注釋的自定義ResponseEntityExceptionHandler
但是,如果在解析請求正文時拋出異常(甚至在驗證運行之前),它將不起作用。 在這種情況下,我得到一個狀態為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嘗試將其用於指定異常類型的異常處理(在注釋的value字段或方法的參數中)。 該方法可以放在控制器中,甚至可以放在我用於其他驗證響應處理的ResponseEntityExceptionHandler

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

注意您要處理的異常類型:

這里的問題是,解析時拋出的異常被包裝在JsonMappingException該包裝的某些子類型),而JsonMappingException又被包裝在HttpMessageConversionException

e instanceof HttpMessageConversionException
e.getCause() instanceof JsonMappingException
e.getCause().getCause() // == your original exception

因此, @ExceptionHandler應該接受HttpMessageConversionException而不是最初引發的異常(在我的情況下是HttpMessageNotReadableException

如果您編寫僅接受原始Exception的@ExceptionHandler ,它將不起作用!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM