您好,登錄后才能下訂單哦!
這篇文章主要介紹了SpringBoot服務端數據校驗過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
對于任何一個應用而言,客戶端做的數據有效性驗證都不是安全有效的,而數據驗證又是一個企業級項目架構上最為基礎的功能模塊,這時候就要求我們在服務端接收到數據的時候也對數據的有效性進行驗證。為什么這么說呢?往往我們在編寫程序的時候都會感覺后臺的驗證無關緊要,畢竟客戶端已經做過驗證了,后端沒必要在浪費資源對數據進行驗證了,但恰恰是這種思維最為容易被別人鉆空子。畢竟只要有點開發經驗的都知道,我們完全可以模擬 HTTP 請求到后臺地址,模擬請求過程中發送一些涉及系統安全的數據到后臺,后果可想而知....
驗證分兩種:對封裝的Bean進行驗證 或者 對方法簡單參數的驗證。
說明:SpringBoot 中使用了 Hibernate-validate 校驗框架作為支持
一、引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <!-- 這兩個springboot包里面都包含hibernate-validator包,只要引入一個即可 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
二、hibernate-validator常用注解
三、@Valid和@Validated的區別
@Valid是使用Hibernate validation的時候。
@Validated是使用Spring Validator校驗機制(在spring-context依賴下)。
java的JSR303聲明了@Valid這類接口,而Hibernate-validator對其進行了實現,@Validation對@Valid進行了二次封裝,在使用上并沒有區別,但在分組、注解位置、嵌套驗證等功能上有所不同。
1. 注解位置上
@Validated:用在類型、方法和方法參數上。但不能用于成員屬性(field)。
@Valid:可以用在方法、構造函數、方法參數和成員屬性(field)上。
如果@Validated注解在成員屬性上,則會報 不適用于field錯誤。
2. 分組校驗
@Validated:提供分組功能,可以在參數驗證時,根據不同的分組采用不同的驗證機制。
@Valid:沒有分組功能。
(1) 定義分組接口
public interface IGroupA { } public interface IGroupB { }
(2) 定義需要校驗的參數bean
public class Student implements Serializable { @NotBlank(message = "用戶名不能為空") private String name; //只在分組為IGroupB的情況下進行驗證 @Min(value = 18, message = "年齡不能小于18歲", groups = {IGroupB.class}) private Integer age; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機號格式錯誤") private String phoneNum; @Email(message = "郵箱格式錯誤") private String email; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getPhoneNum() { return phoneNum; } public void setPhoneNum(String phoneNum) { this.phoneNum = phoneNum; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
(3) 檢驗分組為IGroupA的情況
@RestController public class CheckController { @PostMapping("/stu") public String addStu(@Validated({IGroupA.class}) Student studentBean){ return "add student success"; } }
很明顯,這里對IGroupA是不起作用的,修改為@Validated({IGroupB.class})或@Validated({IGroupA.class, IGroupB.class})。
說明:
不分配groups,默認每次都要進行驗證
對一個參數需要多種驗證方式時,也可通過分配不同的組達到目的。
3. 組序列
默認情況下 不同級別的約束驗證是無序的,但是在一些情況下,順序驗證卻是很重要。
一個組可以定義為其他組的序列,使用它進行驗證的時候必須符合該序列規定的順序。在使用組序列驗證的時候,如果序列前邊的組驗證失敗,則后面的組將不再給予驗證。
(1) 定義組序列
@GroupSequence({Default.class, IGroupA.class, IGroupB.class}) public interface IGroup { }
(2) 需要校驗的Bean,分別定義IGroupA對age進行校驗,IGroupB對email進行校驗:
public class Student implements Serializable { @NotBlank(message = "用戶名不能為空") private String name; //只在分組為IGroupB的情況下進行驗證 @Min(value = 18, message = "年齡不能小于18歲", groups = {IGroupA.class}) private Integer age; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機號格式錯誤") private String phoneNum; @Email(message = "郵箱格式錯誤", groups = IGroupB.class) private String email; }
(3) 測試
@RestController public class CheckController { @PostMapping("/stu") public String addStu(@Validated({IGroup.class}) Student studentBean){ return "add student success"; } }
測試發現,如果age出錯,那么對組序列在IGroupA后的IGroupB不進行校驗。
4. 嵌套校驗
一個待驗證的pojo類,其中還包含了待驗證的對象,需要在待驗證對象上注解@Valid,才能驗證待驗證對象中的成員屬性,這里不能使用@Validated。
(1) 需要約束的bean
public class TeacherBean { @NotEmpty(message = "老師姓名不能為空") private String teacherName; @Min(value = 1, message = "學科類型從1開始計算") private int type; }
public class Student implements Serializable { @NotBlank(message = "用戶名不能為空") private String name; //只在分組為IGroupB的情況下進行驗證 @Min(value = 18, message = "年齡不能小于18歲") private Integer age; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機號格式錯誤") private String phoneNum; @Email(message = "郵箱格式錯誤") private String email; @NotNull(message = "任課老師不能為空") @Size(min = 1, message = "至少有一個老師") private List<TeacherBean> teacherBeans; }
上面這樣寫,對teacherBeans只校驗了NotNull, 和 Size,并沒有對teacher信息里面的字段進行校驗,如果需要多里面的屬性也進行校驗,可以在teacherBeans中加上 @Valid
@Valid @NotNull(message = "任課老師不能為空") @Size(min = 1, message = "至少有一個老師") private List<TeacherBean> teacherBeans;
四、驗證結果接收
可以Controller的方法入參上添加BindingResult參數,用于接收校驗后的驗證結果,如果多個校驗對象,那么每個@Validated
后面跟著的BindingResult就是這個@Validated的驗證結果,順序不能亂。
@Validated People p, BindingResult result, @Validated Person p2
可能用到的操作:
// result是BindingResult 實例 if(result.hasErrors()){ List<ObjectError> allErrors = result.getAllErrors(); for(ObjectError error : allErrors){ FieldError fieldError = (FieldError)error; // 屬性 String field = fieldError.getField(); // 錯誤信息 String message = fieldError.getDefaultMessage(); System.out.println(field + ":" + message); } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。