前言
Spring框架的validator 組件,是個輔助組件,在進行數據的完整性和有效性非常有用,通過定義一個某個驗證器,即可在其它需要的地方,使用即可,非常通用。
應用在執行業務邏輯之前,必須通過校驗保證接受到的輸入數據是合法正確的,但很多時候同樣的校驗出現了多次,在不同的層,不同的方法上,導致代碼冗餘,浪費時間,違反DRY原則。
可以考慮把校驗的代碼封裝起來,來解決出現的這些問題。
JSR-303
JSR-303是Java為Bean數據合法性校驗提供的標準框架,它定義了一套可標註在成員變量,屬性方法上的校驗註解。
Hibernate Validation提供了這套標準的實現,在我們引入Spring Boot web starter或者Spring boot starter validation的時候,默認會引入Hibernate Validation。
用法實例
說了這麼多廢話,上代碼。
1、引入SpringBoot項目
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> </dependency> <!-- 引入lomhok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
2、編寫校驗對象
@Datapublic class User { // 名字不允許為空,並且名字的長度在2位到30位之間// 如果名字的長度校驗不通過,那麼提示錯誤信息@NotNull @Size(min=2, max=30,message = "請檢查名字的長度是否有問題") private String name; // 不允許為空,並且年齡的最小值為18 @NotNull @Min(18) private Integer age;}3、創建控制器
@SpringBootApplication@RestControllerpublic class UserApplication{ public static void main(String[] args) { SpringApplication.run(UserApplication.class,args); } // 1. 要校驗的參數前,加上@Valid註解// 2. 緊隨其後的,跟上一個BindingResult來存儲校驗信息@RequestMapping("/test1") public Object test1( @Valid User user, BindingResult bindingResult ) { //如果檢驗出了問題,就返回錯誤信息// 這裡我們返回的是全部的錯誤信息,實際中可根據bindingResult的方法根據需要返回自定義的信息。 // 通常的解決方案為:JSR-303 + 全局ExceptionHandler if (bindingResult.hasErrors()){ return bindingResult.getAllErrors(); } return "OK"; } } 4、運行應用
稍作演示下運行的結果,可以看出校驗框架已經生效了。
校驗年齡
校驗名稱
校驗通過
常見的校驗註解
@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(regex=,flag=) 被註釋的元素必須符合指定的正則表達式
Hibernate Validator提供的校驗註解:
@NotBlank(message =) 驗證字符串非null,且長度必須大於0
@Email 被註釋的元素必須是電子郵箱地址
@Length(min=,max=) 被註釋的字符串的大小必須在指定的範圍內
@NotEmpty 被註釋的字符串的必須非空
@Range(min=,max=,message=) 被註釋的元素必須在合適的範圍內
自定義校驗註解
有時候,第三方庫中並沒有我們想要的校驗類型,好在系統提供了很好的擴展能力,我們可以自定義檢驗。
比如,我們想校驗用戶的手機格式,寫手機號碼校驗器
1、編寫校驗註解
// 我們可以直接拷貝系統內的註解如@Min,複製到我們新的註解中,然後根據需要修改。 @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})@Retention(RUNTIME)@Documented//註解的實現類。 @Constraint(validatedBy = {IsMobileValidator.class})public @interface IsMobile { //校驗錯誤的默認信息String message() default "手機號碼格式有問題"; //是否強制校驗boolean isRequired() default false; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {};} 2、編寫具體的實現類
我們知道註解只是一個標記,真正的邏輯還要在特定的類中實現,上一步的註解指定了實現校驗功能的類為IsMobileValidator。
// 自定義註解一定要實現ConstraintValidator接口奧,裡面的兩個參數// 第一個為具體要校驗的註解// 第二個為校驗的參數類型public class IsMobileValidator implements ConstraintValidator<IsMobile, String> { private boolean required = false; private static final Pattern mobile_pattern = Pattern.compile("1//d{10}"); //工具方法,判斷是否是手機號public static boolean isMobile(String src) { if (StringUtils.isEmpty(src)) { return false; } Matcher m = mobile_pattern.matcher(src); return m.matches(); } @Override public void initialize(IsMobile constraintAnnotation) { required = constraintAnnotation.isRequired(); } @Override public boolean isValid(String phone, ConstraintValidatorContext constraintValidatorContext) { //是否為手機號的實現if (required) { return isMobile(phone); } else { if (StringUtils.isEmpty(phone)) { return true; } else { return isMobile(phone); } } }} 3、測試自定義註解的功能
@Datapublic class User { @NotNull @Size(min=2, max=30,message = "請檢查名字的長度是否有問題") private String name; @NotNull @Min(18) private Integer age; //這裡是新添加的註解奧@IsMobile private String phone;}4、測試
通過
手機號有問題
可以看出自定義的註解已經生效了。
我們還可以繼續優化的地方,新建一個全局的異常,如果校驗失敗的話,拋出全局的業務異常,捕獲業務異常,然後返回用戶友好的提示信息。
額外
也可以通過方法的校驗。
1、控制器上添加@Validated註解
2、在控制器的方法上添加校驗註解,@Min,@Max等。
@Validated@RestController@SpringBootApplicationpublic class UserApplication{ public static void main(String[] args) { SpringApplication.run(UserApplication.class,args); } @RequestMapping("/test2") public String test2( @IsMobile String phone ){ return phone + "ok"; } @ExceptionHandler(ConstraintViolationException.class) @ResponseBody public Object handleConstraintViolationException(ConstraintViolationException cve){ HashSet<String> messageSet = new HashSet(); for (ConstraintViolation constraintViolation : cve.getConstraintViolations()) { messageSet.add(constraintViolation.getMessage()); } return messageSet; }}類的校驗規則
最後
通過使用校驗器,所有的控制器,我們都不用再去做校驗啦,代碼再回看是不是清爽很多。我們寫代碼很簡答,但是一定要想到如何把代碼寫的更簡單,更清晰,更利於維護,寫重複的代碼是在浪費自己的時間奧。
以後再碰到參數校驗的情況,首先想到的不是直接就去校驗,可以查找自己是否寫過某一類的驗證器,可以直接拿來即用。
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。