[英]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.