對於任何一個應用而言,在客戶端做的數據有效性驗證主要目的是規範用戶的輸入,而真實的數據驗證工作都是在服務後端代碼當中實現的,但在實際的項目當中,也經常會因爲各種各樣的原因:懶得寫,覺得前端驗證了,後端沒有太多的必要等等沒有進行數據驗證,其實養成數據的有效性驗證是一個非常好的習慣。
1 可以避免很多數據有效性導致的BUG,防範其餘開發者的基礎攻擊
2 在前後端進行接口聯調的時候,不需要因爲參數的問題溝通很久。
springboot 參數驗證
JSR-303 是 JAVA EE 6 中的一項子規範,叫做 Bean Validation,官方參考實現是Hibernate Validator。JSR 303 用於對 Java Bean 中的字段的值進行驗證。 主要是 javax.validation 包下面的註解,用於進行參數的驗證。在 spring-boot當中存在 hibernate-validator 驗證包,這個包裏面包含了一些 javax.validation 沒有的註解。算是spring對於JSR驗證的的擴展吧!
常用驗證註解:
註解 | 用法 |
---|---|
@NotNull | 限制必須不爲null |
@Null | 限制必須爲null |
@NotEmpty | 驗證註解的元素值不爲 null 且不爲空(字符串長度不爲0、集合大小不爲0) |
@NotBlank | @NotBlank只應用於字符串且在比較時會去除字符串的空格 |
@Size(min,max) | 限制字符串或者集合長度必須在 min 到 max 之間 |
@Max(value) | 限制必須爲一個不大於指定值的數字 |
@Min(value) | 限制必須爲一個不小於指定值的數字 |
@Past | 限制必須是一個過去的日期 |
@Future | 限制必須是一個將來的日期 |
驗證註解的元素值是Email,可以通過正則表達式和flag指定自定義的email格式 | |
@Pattern(value) | 限制必須符合指定的正則表達式 |
參數驗證具體使用
1 創建需要驗證的實體類
/**
* @author 海加爾金鷹
*/
@Data
public class TestVo {
@NotNull(message = "id 不能爲空")
private Integer id;
@NotBlank(message = "name 不能爲空字符串")
private String name;
@NotEmpty(message = "empty不能爲空集合")
private List<String> empty;
@Max(value = 99,message = "排序最大值不能超過99")
private int sort;
}
2 創建對應的請求接口 在需要校驗的參數上加上@valid註解或者加上@Validated 註解 備註(由於是測試所有這裏不加上BindingResult 參數)
/**
* @author 海加爾金鷹
*/
@RestController
public class TestController {
@GetMapping("/id")
public TestVo getTestVo(@RequestBody @Valid TestVo vo){
return vo;
}
}
3 發送請求查詢返回的信息
GET http://localhost:8080/id
Content-Type: application/json
{
"name" : "content",
"sort": 55
}
"errors": [
{
"codes": [
"NotEmpty.testVo.empty",
"NotEmpty.empty",
"NotEmpty.java.util.List",
"NotEmpty"
],
"arguments": [
{
"codes": [
"testVo.empty",
"empty"
],
"arguments": null,
"defaultMessage": "empty",
"code": "empty"
}
],
"defaultMessage": "empty不能爲空集合",
"objectName": "testVo",
"field": "empty",
"rejectedValue": null,
"bindingFailure": false,
"code": "NotEmpty"
},
{
"codes": [
"NotNull.testVo.id",
"NotNull.id",
"NotNull.java.lang.Integer",
"NotNull"
],
"arguments": [
{
"codes": [
"testVo.id",
"id"
],
"arguments": null,
"defaultMessage": "id",
"code": "id"
}
],
"defaultMessage": "id 不能爲空",
"objectName": "testVo",
"field": "id",
"rejectedValue": null,
"bindingFailure": false,
"code": "NotNull"
}
]
springboot參數的驗證就成功的實現了。很簡單,不復雜。
注意事項
- @valid 這個註解是JSR-303 規範原生的驗證註解 @Validated 註解是spring針對@valid 進行的一個封裝,提供了一些額外的功能。
- 如果在接口上面加上了BindingResult 這個參數的話,驗證後的錯誤信息不會拋出來,會被封裝到這個類當中。 如果需要獲取到驗證的錯誤信息,需要從這個類手動當中獲取。
- @Max @Min 在對包裝類型進行驗證的時候,如果包裝類爲null,是可以通過驗證的,需要配合@NotNull註解一起使用
springboot參數通過切面進行統一驗證返回
在測試用例當中,返回的數據格式非常不友好,通常實際情況下都是通過切面的方式,獲取BindingResult 參數的數據,如果有驗證錯誤信息,就返回給前端參數相關的錯誤的信息
/**
* @author 海加爾金鷹
*/
@Aspect
@Component
public class BindingResultAspect {
@Around("execution(* cn.hjljy.springboot.validdemo.controller.*.*(..)) && args(..,bindingResult)")
public Object validateParam(ProceedingJoinPoint joinPoint, BindingResult bindingResult) throws Throwable {
Object obj = null;
if (bindingResult.hasErrors()) {
// 有校驗錯誤
System.out.println(bindingResult.getAllErrors().toString());
return "這裏返回錯誤的信息";
} else {
// 沒有錯誤方法繼續執行
obj = joinPoint.proceed();
}
return obj;
}
}