要正確處理驗證錯誤,您可以使用JSR-303附帶Spring網絡。例如,假設您有一個控制器,它有兩個參數postalCode
和email
。你可以創建一個名爲ApiParameters
對象:
public class ApiParameters {
@NotNull(message = "is empty")
@Email(message = "is not an email")
private String email;
@NotNull(message = "is required")
private String postalCode;
public ApiParameters() {
}
// Getters + Setters
}
的@NotNull
和@Email
註解驗證註解(@Email
是從休眠雖然)。現在
,在你的控制器,你現在可以把:
@GetMapping
public String doStuff(@Valid ApiParameters parameters) {
// ...
}
由於@Valid
註釋,如果任何參數是錯誤的,那麼BindException
被拋出,你可以在一個catch控制器諮詢類,像這樣:
@ControllerAdvice
public class ErrorHandler {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(BindException.class)
@ResponseBody
public ErrorResponse errorResponse(BindException ex) {
return new ErrorResponse("Validation failed", ex.getFieldErrors()
.stream()
.map(err -> new SpecificError(err.getField(), err.getDefaultMessage()))
.collect(Collectors.toList()));
}
}
這裏發生的是,我所說的BindException
的getFieldErrors()
方法,它包含了所有錯誤的列表。然後映射那些類似於你想要的響應(ErrorResponse
和SpecificErorr
)響應類:
public class ErrorResponse {
@JsonProperty("general_errors")
private String generalErrors;
private List<SpecificError> errors;
public ErrorResponse(String generalErrors, List<SpecificError> errors) {
this.generalErrors = generalErrors;
this.errors = errors;
}
public String getGeneralErrors() {
return generalErrors;
}
public List<SpecificError> getErrors() {
return errors;
}
}
public class SpecificError {
private String key;
private String value;
public SpecificError(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
}
如果你打電話給你的API與參數不夠,你現在將得到下面的JSON響應:
{
"errors": [
{
"key": "postalCode",
"value": "is required"
},
{
"key": "email",
"value": "is empty"
}
],
"general_errors": "Validation failed"
}
這個類似,您可以趕上RuntimeException
S以及:
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public ErrorResponse errorResponse(RuntimeException ex) {
return new ErrorResponse(ex.getMessage(), null);
}
但是,如果你想兩者結合起來,你會甲肝e手動調用驗證器,因爲這種方式的作用是一旦拋出異常,它將停止處理該方法。
這意味着如果您的方法會拋出RuntimeException
,如果驗證錯誤已被拋出,則不會發生。
難道你不能只使用標準的JSR303驗證。示例https://www.mkyong.com/spring-mvc/spring-3-mvc-and-jsr303-valid-example/ BindingResult包含所有發現的錯誤。 – StanislavL