Spring Boot 使用 JSR303(@Validated) 實現參數校驗

一:簡介

1. JSR-303 是 JAVA EE 6 中的一項子規範,叫做 Bean Validation

2. 在任何時候,當你要處理一個應用程序的業務邏輯,數據校驗是你必須要考慮和麪對的事情。

3. Bean Validation 爲 JavaBean 驗證定義了相應的元數據模型和 API。

4. constraint 可以附加到字段getter 方法或者接口上面。

5. 對於一些特定的需求,用戶可以很容易的開發定製化的 constraint。

6. Bean Validation 是一個運行時的數據驗證框架,在驗證之後驗證的錯誤信息會被馬上返回

二:Bean Validation 規範內嵌的約束註解

限制 說明
@Null 限制只能爲null
@NotNull 限制必須不爲null
@AssertFalse 限制必須爲false
@AssertTrue 限制必須爲true
@DecimalMax(value) 限制必須爲一個不大於指定值的數字
@DecimalMin(value) 限制必須爲一個不小於指定值的數字
@Digits(integer,fraction) 限制必須爲一個小數,且整數部分的位數不能超過integer,小數部分的位數不能超過fraction
@Future 限制必須是一個將來的日期
@Max(value) 限制必須爲一個不大於指定值的數字
@Min(value) 限制必須爲一個不小於指定值的數字
@Past 限制必須是一個過去的日期
@Pattern(value) 限制必須符合指定的正則表達式
@Size(max,min) 限制字符長度必須在min到max之間
@Past 驗證註解的元素值(日期類型)比當前時間早
@NotEmpty 驗證註解的元素值不爲null且不爲空(字符串長度不爲0、集合大小不爲0)
@NotBlank 驗證註解的元素值不爲空(不爲null、去除首位空格後長度爲0),不同於@NotEmpty,@NotBlank只應用於字符串且在比較時會去除字符串的空格
@Email 驗證註解的元素值是Email,也可以通過正則表達式和flag指定自定義的email格式

三:基本應用

1、引入依賴

<!--引入validation的場景啓動器-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2、給參數對象添加校驗註解

private Integer id;
@NotBlank(message = "名稱不能爲空")
private String name;
private Date data;
@NotNull(message = "年齡不能爲空")
private Integer age;
@Pattern(regexp = "[0-9]" ,  message = "參數格式錯誤")
private String Telephone;

Controller 中需要校驗的參數Bean前添加 @Validated開啓校驗功能,緊跟在校驗的Bean後添加一個BindingResult,BindingResult封裝了前面Bean的校驗結果。

@GetMapping("/into")
public String into(@Validated Emp emp ,BindingResult bindingResult) {
    if(bindingResult.hasErrors()){
        Map<String,String> map = new HashMap<>();
        bindingResult.getFieldErrors().forEach((item) ->{
            String msg = item.getDefaultMessage();
            String fie = item.getField();
            map.put(fie,msg);
        });
        return map.toString();
    }
    return "200";
}

四:異常的統一處理

參數校驗不通過時,會拋出 BingBindException 異常,可以在統一異常處理中,做統一處理,這樣就不用在每個需要參數校驗的地方都用 BindingResult 獲取校驗結果了。

/**
 * 自定義驗證異常(參數傳值)
 */
@ExceptionHandler(BindException.class)
public String validatedBindException(BindException e) {
    String message = e.getAllErrors().get(0).getDefaultMessage();
    return message;
}
​
/**
 * 自定義驗證異常(json傳值)
 */
@ExceptionHandler(MethodArgumentNotValidException.class)
public String MethodArgumentNotValidException(MethodArgumentNotValidException e) {
    String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
    return message;
}

五:分組解決校驗

新增和修改對於實體的校驗規則是不同的,例如id是自增的時,新增時id要爲空,修改則必須不爲空;新增和修改,若用的恰好又是同一種實體,那就需要用到分組校驗;

 

校驗註解都有一個groups屬性,可以將校驗註解分組,我們看下@NotNull的源碼

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(NotNull.List.class)
@Documented
@Constraint( validatedBy = {} )
public @interface NotNull {
    String message() default "{javax.validation.constraints.NotNull.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        NotNull[] value();
    }
}

從源碼可以看出 groups 是一個Class<?>類型的數組,那麼就可以創建一個Groups.

public class Groups {
    public interface Add {
    }
    public interface Update {
    }
}

給參數對象的校驗註解添加分組

private Integer id;
@NotBlank(message = "名稱不能爲空" ,groups = Groups.Add.class)
private String name;
private Date data;
@NotNull(message = "年齡不能爲空",groups = {Groups.Add.class,Groups.Update.class})
private Integer age;
@Pattern(regexp = "[0-9]" ,  message = "電話格式錯誤")
private String Telephone;

在Controller 添加分組;多個可用@Validated({Groups.Update.class,Groups.Add.class})

@GetMapping("/into")
public String into(@Validated({Groups.Update.class})  Emp emp ) {
    return "200";
}

六:配置文件配置massage錯誤信息

在resource 目錄下新建提示信息配置文件“ValidationMessages.properties“

注意:名字必須爲“ValidationMessages.properties“ 因爲SpringBoot自動讀取classpath中的ValidationMessages.properties裏的錯誤信息

@NotBlank(message = "{emp.name}" ,groups = Groups.Add.class)
private String name;
emp.name=參數錯誤
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章