詳解SpringBoot中的引數校驗(專案實戰)
Java後端發工作中經常會對前端傳遞過來的引數做一些校驗,在業務中還要丟擲異常或者不斷的返回異常時的校驗資訊,充滿了if-else這種校驗程式碼,在程式碼中相當冗長。例如說,使用者註冊時,會校驗手機格式的正確性,使用者名稱的長度等等。雖說前端也可以做引數校驗,但是為了保證我們API介面的可靠性,以保證最終資料入庫的正確性,後端進行引數校驗不可忽視。 Hibernate Validator
提供了一種統一方便的方式,讓我們快速的實現引數校驗。
Hibernate Validator
使用註解,實現宣告式校驗。而在實現原理上,也是基於 Spring AOP 攔截,實現校驗相關的操作。 javax.validation.constraints
spring-boot-starter-web
中已經包含了 Hibernate-validator
的依賴( 版本<2.3 )。 2.3
以後的版本中 spring-boot-starter-web
已經去除了這個依賴,需要手動引入 Hibernate-validator
依賴,並且有一些變化,因此 2.3.x 的版本暫不研究。本文使用的版本是 2.2.8
。
實戰
1、建立實體類
package com.yese.pojo; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.*; @Data @Builder @AllArgsConstructor @NoArgsConstructor public class User { /** * 使用者ID */ @NotNull(message = "使用者id不能為空") private Long userId; /** * 使用者名稱 */ @NotBlank(message = "使用者名稱不能為空") @Length(max = 20,message = "使用者名稱不能超過10個字元") @Pattern(regexp = "^[\\u4E00-\\u9FA5A-Za-z0-9\\*]*$",message = "使用者名稱限制:最多10字元,包含文字、字母和數字") private String username; /** * 密碼 */ @NotBlank(message = "密碼不能為空") private String password; /** * 手機號 */ @NotBlank(message = "手機號不能為空") @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$",message = "手機號格式有誤") private String mobile; /** * 性別 */ @NotNull(message = "性別不能為空") private Integer sex; /** * 年齡 */ @NotNull(message = "年齡不能為空") @Min(value = 1,message = "年齡最小為1歲") @Max(value = 120,message = "年齡最大為120歲") private Integer age; /** * 郵箱 */ @NotBlank(message = "郵箱不能為空") @Email(message = "郵箱格式錯誤") private String email; }
2、建立controller
package com.yese.controller; import com.yese.pojo.User; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j public class UserController { /** * controller方法的入參裡面在實體類前面加上@Validated */ @PostMapping("/user") public void add(@RequestBody @Validated User user) { log.info("user====={}",user); } }
3、建立全域性異常處理器
package com.yese.config; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.validation.ConstraintViolationException; import java.util.HashMap; import java.util.Map; import java.util.StringJoiner; /** * 全域性異常處理器 */ @RestControllerAdvice public class GlobalExceptionHandler { /** * post方式提交json資料,引數校驗失敗後,會丟擲一個MethodArgumentNotValidException */ @ExceptionHandler(MethodArgumentNotValidException.class) public Map<String,Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { // 獲取所有的錯誤 // List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors(); // 獲取錯誤提示 // System.out.println(fieldErrors.get(0).getDefaultMessage()); // 獲取錯誤欄位 // System.out.println(fieldErrors.get(0).getField()); // 將所有的錯誤提示使用";"拼接起來並返回 StringJoiner sj = new StringJoiner(";"); e.getBindingResult().getFieldErrors().forEach(x -> sj.add(x.getDefaultMessage())); // 此處通常定義一個全域性相應物件返回 Map<String,Object> map = new HashMap<>(); // 此處狀態碼可以通過列舉或者常量定義 map.put("code",1001); map.put("msg",sj.toString()); return map; } /** * get方式提交引數,會丟擲一個ConstraintViolationException */ @ExceptionHandler(ConstraintViolationException.class) public Map<String,Object> handleConstraintViolationException(ConstraintViolationException e) { StringJoiner sj = new StringJoiner(";"); e.getConstraintViolations().forEach(x -> sj.add(x.getMessage())); Map<String,Object> map = new HashMap<>(); map.put("code",sj.toString()); return map; } }
4、測試
效果符合預期!
@Valid和@Validated
絕大多數場景下,我們使用 @Validated 註解即可。
而在有巢狀校驗的場景,我們使用 @Valid 註解新增到成員屬性上。
附常用註解
javax.validation.constraints
包下
註解 | 驗證的資料型別 | 說明 |
---|---|---|
@Null | 任意型別 | 驗證註解的元素值必須是null |
@NotNull | 任意型別 | 驗證註解的元素值不是null |
@NotBlank | 字串 | 驗證註解的元素值不為空(不為null、去除首位空格後長度大於0) |
@NotEmpty | CharSequence子型別、Collection、Map、陣列 | 驗證註解的元素值不為null且不為空(字串長度不為0、集合大小不為0) |
@Min(value=值) | 數值型別 | 驗證註解的元素值大於等於@Min指定的value值 |
@Max(value=值) | 和@Min要求一樣 | 驗證註解的元素值小於等於@Max指定的value值 |
@DecimalMin(value=值) | 和@Min要求一樣 | 驗證註解的元素值大於等於@ DecimalMin指定的value值 |
@DecimalMax(value=值) | 和@Min要求一樣 | 驗證註解的元素值小於等於@ DecimalMax指定的value值 |
@Digits(integer=整數位數,fraction=小數位數) | 和@Min要求一樣 | 驗證註解的元素值的整數位數和小數位數上限 |
@Size(min=下限,max=上限) | 字串、Collection、Map、陣列等 | 驗證註解的元素值的在min和max(包含)指定區間之內,如字元長度、集合大小 |
@Positive | 判斷正數 | |
@PositiveOrZero | 判斷正數或 0 。 | |
@Negative | 判斷負數。 | |
@NegativeOrZero | 判斷負數或 0 。 | |
@Past | 日期型別 | 驗證註解的元素值(日期型別)比當前時間早 |
@Future | 與@Past要求一樣 | 驗證註解的元素值(日期型別)比當前時間晚 |
@AssertFalse | Boolean | 驗證註解的元素值是false |
@AssertTrue | Boolean | 驗證註解的元素值是true |
@Range(min=最小值,max=最大值) | BigDecimal,BigInteger,CharSequence,byte,short,int,long等原子型別和包裝型別 | 驗證註解的元素值在最小值和最大值之間 |
字串 | 驗證註解的元素值是Email,也可以通過regexp和flag指定自定義的email格式 | |
@Pattern(regexp=正則表示式,flag=標誌的模式) | 字串 | 驗證註解的元素值與指定的正則表示式匹配 |
@Valid | 任何非原子型別 | 指定遞迴驗證關聯的物件如使用者物件中有個地址物件屬性,如果想在驗證使用者物件時一起驗證地址物件的話,在地址物件上加@Valid註解即可級聯驗證 |
org.hibernate.validator.constraints
包下,定義了一系列的約束( constraint )註解。如下:
@Range(min=,max=)
:被註釋的元素必須在合適的範圍內。
@Length(min=,max=)
:被註釋的字串的大小必須在指定的範圍內。
@URL(protocol=,host=,port=,regexp=,flags=)
:被註釋的字串必須是一個有效的 URL 。
@SafeHtml
:判斷提交的 HTML 是否安全。例如說,不能包含 javascript 指令碼等等。
到此這篇關於詳解SpringBoot中的引數校驗(專案實戰)的文章就介紹到這了,更多相關SpringBoot 引數校驗內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!