最近開始由原來的Android工程師Java Web向轉型了,廢話不多說,上圖
背景
JSR 303 – Bean Validation 是一個資料驗證的規範,2009 年 11 月確定最終方案。 Hibernate Validator 是 Bean Validation 的參考實現 . Hibernate Validator 提供了 JSR 303 規範中所有內建 constraint 我們通常寫介面時會對傳來的引數進行校驗判斷,比如字串非空判斷,值在多少返回等,這些就要用到Spring 的引數校驗,這裡我們使用在spring-boot-starter-web包裡面有hibernate-validator包, 引數校驗有幾種方式,如下
- 1.使用@Valid+BindingResult
- 2.註解使用@Valid +全域性異常捕捉處理
下面來介紹這兩種方式的使用
使用@Valid+BindingResult 引數驗證
1.符合國際JSP 303規範,先定義個Bean,別人在欄位名上新增驗證的註解,@NotBlank 欄位名不能為null,同時長度大於0常有的校驗型別有
Constraint 詳細資訊
@Null 被註釋的元素必須為 null
@NotNull 被註釋的元素必須不為 null
@AssertTrue 被註釋的元素必須為 true
@AssertFalse 被註釋的元素必須為 false
@Min(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
@Max(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
@DecimalMin(value) 被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
@DecimalMax(value) 被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
@Size(max, min) 被註釋的元素的大小必須在指定的範圍內
@Digits (integer, fraction) 被註釋的元素必須是一個數字,其值必須在可接受的範圍內
@Past 被註釋的元素必須是一個過去的日期
@Future 被註釋的元素必須是一個將來的日期
@Pattern(value) 被註釋的元素必須符合指定的正規表示式
複製程式碼
/**
* @author Lang.Chen
* @date 2018/6/20 下午4:39
*/
public class User {
//賬號
@NotBlank(message = "賬號不能為空")
private String phone;
//密碼
@NotBlank(message = "密碼不能為空")
private String password;
public void setPhone(String phone) {
this.phone = phone;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public String getPassword() {
return password;
}
}
複製程式碼
2.在Controller類裡面對相應的介面新增@Valid+BindingResult驗證,加完以後,如果引數驗證不通過,那就直接進入if語句裡面,在語句裡面做相應的返回結果
if(bindingResult.hasErrors()){
}
複製程式碼
@RestController
@RequestMapping(value = "/user")
public class UserController implements IUser {
@Override
@RequestMapping(value = "/login", method = RequestMethod.POST)
public User login( @Valid User userInfo, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
System.out.print(bindingResult.getFieldError().getDefaultMessage());
return null;
}
return userInfo;
}
}
複製程式碼
好了,第一種驗證我們已經說完了,但你仔細想想,如果我有多個介面,是不是每次有要寫@Valid+BindgResult bingingResult,然後再到If語句裡面進行判斷,如果僅僅是錯誤資訊不一致,但返回的客戶端結構是一致的,比如
{"code":"1002","message":"parameters are missing","data":"{}"}
複製程式碼
不同的驗證只要改變message,那麼是不是可以統一處理,來減少程式碼量,於是下面介紹第二種方式
使用@Valid+全域性異常捕捉 引數校驗
簡單點說,由第一種方式去掉BindingResult,然後再定義一個全域性異常類,同樣的
1.還是定義POJO
/**
* @author Lang.Chen
* @date 2018/6/20 下午4:39
*/
public class User {
//賬號
@NotBlank(message = "賬號不能為空")
private String phone;
//密碼
@NotBlank(message = "密碼不能為空")
private String password;
public void setPhone(String phone) {
this.phone = phone;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public String getPassword() {
return password;
}
}
複製程式碼
2.在Controller裡面的方法定義要驗證的@Valid
public class UserController implements IUser {
@Override
@RequestMapping(value = "/login2", method = RequestMethod.POST)
public User login2(@RequestBody @Valid User userInfo) {
return null;
}
}
複製程式碼
3.定義全域性異常類
所有驗證失敗的結果都會在GlobleExceptionHandler的defultExcepitonHandler方法裡面捕捉到
@RestControllerAdvice
@Component
public class GlobleExceptionHandler {
@ResponseBody
@ExceptionHandler(Exception.class)
public String defultExcepitonHandler(Exception ex) {
ex.printStackTrace();
if(ex instanceof BindException){
//處理返回的錯誤資訊
StringBuffer errorMsg = new StringBuffer();
BindException c = (BindException) ex;
List<ObjectError> errors = c.getBindingResult().getAllErrors();
for (ObjectError error : errors) {
errorMsg.append(error.getDefaultMessage()).append(";");
}
return errorMsg.toString();
}
return "";
}
}
複製程式碼
有關於自定義驗證和分組驗證,就不一一介紹了,會使用以上2個就可以了。
Q&A
1.如何使用單個引數驗證,並且進入全域性異常捕捉,返回?
有時候只傳入少數驗證時,我們不可能都是新建一個物件來接受,這時候如何使用單個引數驗證呢,看到網上使用在類上新增 @Validated引數,然後通過全域性異常捕捉方式
@RestController
@RequestMapping("/order")
@Validated
public class OrderController implements IOrder {
@RequestMapping(value = "/byId",method = RequestMethod.POST)
public OrderInfo byId( @Max(value = 50) int orderId) {
return null;
}
}
複製程式碼
但每次訪問介面時,都是報同一個錯誤,就沒用這個方式了,如果有人找到解決方案,請指教,謝謝
{
"timestamp": "2018-06-24T07:09:14.235+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/order/byId"
}
複製程式碼
@Valid和@Validated的區別
@Valid是javax.validation裡的 @Validated是@Valid 的一次封裝,是Spring提供的校驗機制使用。@Validated 提供分組功能