Java SpringBoot上的參數校驗JSR 303 Validation

最近開始由原來的Android工程師Java Web向轉型了,廢話很少說,上圖java

背景

JSR 303 – Bean Validation 是一個數據驗證的規範,2009 年 11 月肯定最終方案。 Hibernate Validator 是 Bean Validation 的參考實現 . Hibernate Validator 提供了 JSR 303 規範中全部內置 constraint 咱們一般寫接口時會對傳來的參數進行校驗判斷,好比字符串非空判斷,值在多少返回等,這些就要用到Spring 的參數校驗,這裏咱們使用在spring-boot-starter-web包裏面有hibernate-validator包, 參數校驗有幾種方式,以下git

  • 1.使用@Valid+BindingResult
  • 2.註解使用@Valid +全局異常捕捉處理

下面來介紹這兩種方式的使用web

使用@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,那麼是否是能夠統一處理,來減小代碼量,因而下面介紹第二種方式spring

使用@Valid+全局異常捕捉 參數校驗

簡單點說,由第一種方式去掉BindingResult,而後再定義一個全局異常類,一樣的bash

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方法裏面捕捉到app

@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個就能夠了。ide

Q&A

1.如何使用單個參數驗證,而且進入全局異常捕捉,返回?

有時候只傳入少數驗證時,咱們不可能都是新建一個對象來接受,這時候如何使用單個參數驗證呢,看到網上使用在類上添加 @Validated參數,而後經過全局異常捕捉方式spring-boot

@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;
   }

}
複製代碼

但每次訪問接口時,都是報同一個錯誤,就沒用這個方式了,若是有人找到解決方案,請指教,謝謝ui

{
    "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 提供分組功能

相關文章
相關標籤/搜索