簡體   English   中英

Spring Bean Validation @Valid 處理

[英]Spring Bean Validation @Valid handling

我使用 Bean Validation 1.2 創建了一個 Spring MVC REST 服務,方法如下:

@RequestMapping(value = "/valid")
public String validatedMethod(@Valid ValidObject object) {

}

如果對象無效,Tomcat 會通知我The request sent by the client was syntactically incorrect. 並且我的validatedMethod方法永遠不會被調用。

如何獲取在ValidObject bean 中定義的消息? 我應該使用一些過濾器或攔截器嗎?

我知道我可以像下面這樣重寫,從注入的Validator獲取一組ConstraintViolation ,但上面看起來更整潔......

@RequestMapping(value = "/valid")
public String validatedMethod(ValidObject object) {
    Set<ConstraintViolation<ValidObject>> constraintViolations = validator
            .validate(object);
    if (constraintViolations.isEmpty()) {
        return "valid";
    } else {
        final StringBuilder message = new StringBuilder();
        constraintViolations.forEach((action) -> {
            message.append(action.getPropertyPath());
            message.append(": ");
            message.append(action.getMessage());
        });
        return message.toString();
    }
}

我相信這樣做的更好方法是使用ExceptionHandler

在您的Controller您可以編寫ExceptionHandler來處理不同的異常。 下面是相同的代碼:

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ValidationFailureResponse validationError(MethodArgumentNotValidException ex) {
    BindingResult result = ex.getBindingResult();
    final List<FieldError> fieldErrors = result.getFieldErrors();

    return new ValidationFailureResponse((FieldError[])(fieldErrors.toArray(new FieldError[fieldErrors.size()])));
}

當您向 Controller 發送錯誤請求時,驗證器會拋出MethodArgumentNotValidException類型的異常。 所以理想的方法是編寫一個異常處理程序來專門處理這個異常。

在那里你可以創建一個漂亮的響應來告訴用戶出了什么問題。 我提倡這樣做,因為您只需編寫一次即可,許多Controller方法都可以使用它。 :)

更新

當您對Controller的方法參數使用 @Valid 注釋時,將自動調用驗證器並嘗試驗證對象,如果對象無效,則拋出MethodArgumentNotValidException

如果 Spring 找到此異常的ExceptionHandler方法,它將執行此方法中的代碼。

您只需要確保上述方法存在於您的控制器中。

現在還有另一種情況,當您有多個Controller想要驗證方法參數時。 在這種情況下,我建議您創建一個ExceptionResolver類並將此方法放在那里。 讓你的Controller擴展這個類,你的工作就完成了。

嘗試這個

@RequestMapping(value = "/valid")
public String validatedMethod(@Valid ValidObject object, BindingResult result) {
    StringBuilder builder = new StringBuilder();
    List<FieldError> errors = result.getFieldErrors();
    for (FieldError error : errors ) {
       builder.append(error.getField() + " : " + error.getDefaultMessage());
    } 
    return builder.toString();
}

@dharam 的答案有效。 對於 Spring v4.3 的用戶,這是一個很好的實現,它使用自定義異常類按類型處理異常。

@RestControllerAdvice
public class CustomExceptionClass extends ResponseEntityExceptionHandler{
   @ExceptionHandler(value = MethodArgumentNotValidException.class)
   public ResponseEntity<Object> handleException(MethodArgumentNotValidException ex, WebRequest req){
   // Build your custom response object and access the exception message using ex.getMessage()
}
}

此方法將啟用以統一方式處理所有@Controller方法中的所有@Valid異常

當您使用 @Valid 並且做不好的請求主體時 Spring 處理 MethodArgumentNotValidException 您必須創建特殊類並擴展 ResponseEntityExceptionHandler 並覆蓋 handleMethodArgumentNotValid 示例

@ControllerAdvice 公共類 ControllerExceptionHandler 擴展 ResponseEntityExceptionHandler {

@ExceptionHandler(UserExistException.class)
public ResponseEntity<Object> handleUserExistException(
        UserExistException e, WebRequest request) {

    Map<String, Object> body = new LinkedHashMap<>();
    body.put("timestamp", LocalDateTime.now());
    body.put("status", HttpStatus.BAD_REQUEST.value());
    body.put("error", HttpStatus.BAD_REQUEST.getReasonPhrase());
    body.put("message", e.getMessage());
    body.put("path", request.getDescription(false).replace("uri=", ""));


    return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
}

@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

    Map<String, Object> body = new LinkedHashMap<>();
    body.put("timestamp", LocalDateTime.now());
    body.put("status", HttpStatus.BAD_REQUEST.value());
    body.put("error", HttpStatus.BAD_REQUEST.getReasonPhrase());
    body.put("path", request.getDescription(false).replace("uri=", ""));
    return new ResponseEntity<>(body, headers, status);
}

}

暫無
暫無

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

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