javascript
Spring Validation 校验
一、概述
在 Web 應用中,客戶端提交數據之前都會進行數據的校驗,比如用戶注冊時填寫的郵箱地址是否符合規范、用戶名長度的限制等等,不過這并不意味著服務端的代碼可以免去數據驗證的工作,用戶也可能使用 HTTP 工具直接發送違法數據。為了保證數據的安全性,服務端的數據校驗是必須的。
- 先理清概念:
JSR-303 是 JavaEE 6 中的一項子規范,又稱作 Bean Validation,提供了針對 Java Bean 字段的一些校驗注解,如@NotNull,@Min等。JSR-349 是其升級版本,添加了一些新特性。Hibernate Validator 是對這個規范的實現(與 ORM 框架無關),并在它的基礎上增加了一些新的校驗注解。Spring 本身也有一個校驗接口Validator,位于org.springframework.validation 包下,但是使用這個接口需要進行硬編碼,也就是手動校驗,沒有提供注解進行簡化。為了給開發者提供便捷,Spring 也全面支持 JSR-303、JSR-349 規范,對 Hibernate Validation 進行二次封裝,在 SpringMVC 模塊中添加了自動校驗機制,可以利用注解對 Java Bean 的字段的值進行校驗,并將校驗信息封裝進特定的類中。
下面將介紹如何在 Spring 應用中使用 JSR-303 校驗規范。
二、校驗注解
| @Null | 被注解元素必須為 null |
| @NonNull | 被注解元素必須不為 null |
| @AssertTrue | 被注解元素必須為 true |
| @AssertFalse | 被注解元素必須為 false |
| @Min(value) | 被注解元素必須是一個值,并且不能小于指定的值 |
| @Max(value) | 被注解元素必須是一個值,并且不能大于指定的值 |
| @DecimalMin(value) | 被注解元素必須是一個數字,并且不能小于指定的值 |
| @DecimalMax(value) | 被注解元素必須是一個數字,并且不能大于指定的值 |
| @Size(max=,min=) | 被注解元素的大小必須在指定范圍內 |
| @Digits(integer,fraction) | 被注解元素必須是一個數字,其值必須在指定范圍內 |
| @Past | 被注解元素必須是一個過去的日期 |
| @Future | 被注解元素必須是一個將來的日期 |
| @Pattern(regex=,flag=) | 被注解元素必須符合指定的正則表達式 |
| @NotBlank(message=) | 被注解的字符串必須非 null 且trim()后長度大于 0 |
| 被注解元素必須是電子郵箱地址 | |
| @Length(min=,max=) | 被注解的字符串的長度必須在指定范圍內 |
| @NotEmpty | 被注解元素(字符串、數組、集合等)必須非 null 且長度大于 0 |
| @Range(min=,max=,message=) | 被注解元素必須在合適的范圍內 |
| @URL | 被注解元素必須是合法的 URL |
三、用法
如果你使用的是 SpringBoot(spirngboot升級到2.3之后默認不再包含),那么只需引入spring-boot-starter-web即可,它的子依賴中包含了hibernate-validator和必要的數據綁定組件。
在pom.xml中引入 Hibernate Validator 需要的依賴包: <dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>6.0.10.Final</version> </dependency>springboot2.3后,使用以下:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>每一個注解都包含了message字段,用于校驗失敗時作為提示信息。
在處理器方法需要校驗的參數上添加 @Validated 注解,就可以“激活”對它的校驗操作,后面傳入一個 BindingResult 類型的參數,用于獲取校驗失敗情況下的反饋信息。
@Controller public class StudentController {@AutowiredStudentMapper studentMapper;@PostMapping("/student")@ResponseBodypublic String addStudent(@RequestBody @Validated Student student, BindingResult result) {if (result.hasErrors()) {return JSONObject.toJSONString(result.getAllErrors());}studentMapper.insert(student);return "success";} }@Validated 注解的參數和 BindingResult 參數必須是成對出現的,并且一前一后。
發送數據,進入上面的處理器:
控制臺輸出:
四、自定義校驗
假如現在有一個需求是學生名字的內部不能含有空格,我們要如何自定義一個滿足該要求的校驗呢?
@Constraint指定這個注解真正的校驗者類。
實現ConstraintValidator接口:
第一個泛型參數是表明校驗的注解類型,第二個泛型參數是需要被校驗的類型。
- initialize:初始化事件方法
- isValid:判斷是否合法的方法
ConstraintValidatorContext這個上下文包含了校驗中所有的信息,我們可以利用這個對象進行獲取默認錯誤提示信息,禁用錯誤提示信息,改寫錯誤提示信息等操作。
發送數據:
控制臺輸出:
可以看到NotContainSpaceValidator的執行是先于處理器方法的,并且禁用默認提示語、設置新的提示語等操作都是有效的。
五、分組校驗
如果對同一個類,在不同的使用場景下有不同的校驗規則,就可以使用分組校驗。比如更新一條學生記錄時,要求 id 不為 null 且大于 0:
public class Student {@Min(value = 1, groups = {Update.class}, message = "id錯誤")private Long id; // 只有在Update分組下,限制才會起作用public interface Update{} // 分組是接口形式// ... }我們上面在對方法參數添加自動校驗時用的是@Valid注解,它是由 javax 提供的,其實 Spring Validation 校驗框架還提供了@Validated注解。在檢驗 Controller 的入參是否符合規范時,它們的基本驗證功能并沒有多大區別。但是,現在要進行分組校驗,就必須使用@Validated:
@PutMapping("/student") public ApiResult updateStudent(@RequestBody @Validated({Student.Update.class}) Student student, BindingResult result) {if (result.hasErrors()) {for (ObjectError error : result.getAllErrors()) {// do stuff}return ApiResult.error();}studentService.update(student);return ApiResult.success(); }不過注意,在@Validated中指定了分組,那么其他未分組的校驗將會被忽略。
參考文章
關于更多 @Valid 和 @Validated 的區別
參考文章
總結
以上是生活随笔為你收集整理的Spring Validation 校验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IDEA 单元测试报错:Class no
- 下一篇: 不玩虚的!深入B端SaaS产品设计核心理