SpringBoot如何優雅的進行參數校驗
一.爲什麼要進行參數校驗
在日常的開發過程中,我們常常需要對傳入的參數進行校驗,比如在web前後端分離項目中,參數校驗有兩個方面:
-
前端進行參數校驗
-
後端進行參數校驗
那這兩種有什麼區別呢?只完成一個可不可以呢?
答案是不可以的!
-
前端校驗
前端校驗主要是針對用戶輸入時,一些基礎的錯誤進行提示,提升用戶體驗。比如:必填的選項,郵箱,網址的規則,如果前端校驗不通過的話就不需要將請求轉到後端。
但是:對於某些不走尋常路的用戶,前端校驗其實形同虛設。
-
後端校驗
後端校驗是針對整個系統的業務邏輯進行校驗,包含用戶的權限,請求的參數等,校驗的範圍要大於前端.如果不做後端的校驗會怎麼樣呢?比如前端向後端提交了一個只包含郵箱的請求,然後一些心術不正的人將該請求拷貝,改變參數爲任意一段字符,然後重新發送請求,那麼請求仍然能被處理,數據庫就會有一條髒數據,藉助此操作,可以完成一些對系統危害性更大的操作.
前端校驗是輔助,後端校驗是核心。後端校驗必不可少。
二.後端參數校驗方式
傳統的參數校驗一般採用大量的if else代碼對參數進行一個一個的校驗
傳統的參數校驗方式:
public String checkUserDTO(UserDTO user) {
if (StringUtils.isEmpty(user.getName())) {
return "用戶名不能爲空";
}
if(StringUtils.isEmpty(user.getEmail())) {
return "郵箱不能爲空";
}
if(StringUtils.isEmpty(user.getAccount())) {
return "賬號不能爲空";
}
if (user.getAccount().length() < 6 || user.getAccount().length() > 11) {
return "賬號長度必須是6-11個字符";
}
if (!Pattern.matches("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", user.getEmail())) {
return "郵箱格式不正確";
}
return "success";
}
這樣的方式的話,如果參數多了那光參數校驗就是一大堆,給人的感覺就是:不優雅,不專業,代碼可讀性也很差.
那麼怎麼能簡單快捷的進行參數校驗呢?
其實在SpringBoot項目中我們可以引入spring-boot-starter-validation來簡單的進行參數校驗.
三.spring-validation使用
引入依賴
粘貼請去除其中多餘空格
< !--參數校驗 -- >
< dependency >
< groupId>org.springframework.boot < /groupId>
< artifactId>spring-boot-starter-validation< /artifactId>
< /dependency>
參數註解列表
spring-validation是以註解的方式完成參數的校驗的,而根據springboot官網的介紹,只要有JSR-303實現,例如Hibernate驗證器,那麼就能進行參數的校驗.
這裏列一下常用的註解:
-
-
說明:被註釋的元素必須爲
null
-
適用範圍:
Object
-
-
-
說明:被註釋的元素必須不爲
null
-
適用範圍:
Object
-
-
@AssertTrue
-
說明:被註釋的元素必須爲
true
-
適用範圍:
boolean
、Boolean
-
-
-
說明:被註釋的元素必須爲
false
-
適用範圍:
boolean
、Boolean
-
-
@Min(value)
-
說明:被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
-
適用範圍:
BigDecimal
、BigInteger
、byte
、Byte
、short
、Short
、int
、Integer
、long
、Long
-
-
@Max(value)
-
說明:被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
-
適用範圍:
BigDecimal
、BigInteger
、byte
、Byte
、short
、Short
、int
、Integer
、long
、Long
-
-
@DecimalMin(value)
-
說明:被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
-
適用範圍:
BigDecimal
、BigInteger
、CharSequence
、byte
、Byte
、short
、Short
、int
、Integer
、long
、Long
-
-
@DecimalMax(value)
-
說明:被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
-
適用範圍:
BigDecimal
、BigInteger
、CharSequence
、byte
、Byte
、short
、Short
、int
、Integer
、long
、Long
-
-
@Size(max, min)
-
說明:被註釋的元素的大小必須在指定的範圍內
-
適用範圍:
CharSequence
、Collection
、Map
、Array
-
-
@Digits (integer, fraction)
-
說明:被註釋的元素必須是一個數字,其值必須在可接受的範圍內
-
適用範圍:
BigDecimal
、BigInteger
、CharSequence
、byte Byte
、short Short
、int Integer
、long Long
-
-
@Past
-
說明:被註釋的元素必須是一個過去的日期
-
適用範圍:
Date
、Calendar
、Instant
、LocalDate
、LocalDateTime
、LocalTime
、MonthDay
、OffsetDateTime
、OffsetTime
、Year
、YearMonth
、ZonedDateTime
、HijrahDate
、JapaneseDate
、MinguoDate
、ThaiBuddhistDate
-
-
@Future
-
說明:被註釋的元素必須是一個將來的日期
-
適用範圍:
Date
、Calendar
、Instant
、LocalDate
、LocalDateTime
、LocalTime
、MonthDay
、OffsetDateTime
、OffsetTime
、Year
、YearMonth
、ZonedDateTime
、HijrahDate
、JapaneseDate
、MinguoDate
、ThaiBuddhistDate
-
-
@Pattern(value)
-
說明:被註釋的元素必須符合指定的正則表達式
-
適用範圍:
CharSequence
、null
-
-
@Email
-
說明:被註釋的元素必須是電子郵箱地址
-
適用範圍:
CharSequence
-
-
@Length
-
說明:被註釋的字符串的大小必須在指定的範圍內
-
-
@NotEmpty
-
說明:被註釋的字符串的必須非空
-
-
@Range
-
說明:被註釋的元素必須在合適的範圍內
-
具體使用
對於web
服務來說,爲防止非法參數對業務造成影響,在Controller
層一定要做參數校驗的!大部分情況下,請求參數分爲如下兩種形式:
-
POST
、PUT
請求,使用requestBody
傳遞參數; -
GET
請求,使用requestParam/PathVariable
傳遞參數。
下面我們簡單介紹下requestBody
和requestParam/PathVariable
的參數校驗
requestBody
參數校驗
POST
、PUT
請求一般會使用requestBody
傳遞參數,這種情況下,後端使用DTO對象進行接收。只要給DTO對象加上@Validated
註解就能實現自動參數校驗。
requestBody
參數校驗需要兩個步驟:
-
在
DTO
字段上聲明約束註解public class UserDTO { private Long Id; @NotNull @Length(min = 2, max = 10) private String name; @NotNull @Length(min = 6, max = 20) private String account; @NotNull @Email private String email; }
-
在
方法
參數上聲明校驗註解
public Result addUser(@RequestBody @Validated UserDTO userDTO) {
// 校驗通過,纔會執行業務邏輯處理
return Result.ok();
}
requestParam/PathVariable
參數校驗
GET
請求一般會使用requestParam/PathVariable
傳參
將一個個參數平鋪到方法入參中。在這種情況下,必須在Controller
類上標註@Validated
註解,並在入參上聲明約束註解(如@Min
等)。
@Validated
@RestController
public class UserController {
// 路徑變量
@GetMapping("{userId}")
public Result detail(@PathVariable("userId") @Min(10000000000000000L) Long userId) {
// 校驗通過,纔會執行業務邏輯處理
UserDTO userDTO = new UserDTO();
userDTO.setId(userId);
return Bizmessage.success(userDTO);
}
// 查詢參數
@GetMapping("getByAccount")
public BizMessage getByAccount(@Length(min = 6, max = 11) @NotNull String account) {
// 校驗通過,纔會執行業務邏輯處理
UserDTO userDTO = new UserDTO();
userDTO.setAccount(account);
return Bizmessage.success(userDTO);
}
}
如果校驗失敗,則會拋出異常,通常會有統一異常處理
Hibernate Validator
的功能是非常強大的,它還支持分組校驗
,嵌套校驗
,集合校驗
,自定義校驗
等多種校驗方式,功能非常強大.