SpringBoot如何優雅的進行參數校驗(一)

SpringBoot如何優雅的進行參數校驗

一.爲什麼要進行參數校驗

在日常的開發過程中,我們常常需要對傳入的參數進行校驗,比如在web前後端分離項目中,參數校驗有兩個方面:

  • 前端進行參數校驗

  • 後端進行參數校驗

那這兩種有什麼區別呢?只完成一個可不可以呢?

答案是不可以的!

  1. 前端校驗

    前端校驗主要是針對用戶輸入時,一些基礎的錯誤進行提示,提升用戶體驗。比如:必填的選項,郵箱,網址的規則,如果前端校驗不通過的話就不需要將請求轉到後端。

    但是:對於某些不走尋常路的用戶,前端校驗其實形同虛設。

  2. 後端校驗

    後端校驗是針對整個系統的業務邏輯進行校驗,包含用戶的權限,請求的參數等,校驗的範圍要大於前端.如果不做後端的校驗會怎麼樣呢?比如前端向後端提交了一個只包含郵箱的請求,然後一些心術不正的人將該請求拷貝,改變參數爲任意一段字符,然後重新發送請求,那麼請求仍然能被處理,數據庫就會有一條髒數據,藉助此操作,可以完成一些對系統危害性更大的操作.

    前端校驗是輔助,後端校驗是核心。後端校驗必不可少

二.後端參數校驗方式

傳統的參數校驗一般採用大量的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

    • 說明:被註釋的元素必須爲 null

    • 適用範圍:Object

  • @NotNull

    • 說明:被註釋的元素必須不爲 null

    • 適用範圍:Object

  • @AssertTrue

    • 說明:被註釋的元素必須爲 true

    • 適用範圍:booleanBoolean

  • @AssertFalse

    • 說明:被註釋的元素必須爲 false

    • 適用範圍:booleanBoolean

  • @Min(value)

    • 說明:被註釋的元素必須是一個數字,其值必須大於等於指定的最小值

    • 適用範圍:BigDecimalBigIntegerbyteByteshortShortintIntegerlongLong

  • @Max(value)

    • 說明:被註釋的元素必須是一個數字,其值必須小於等於指定的最大值

    • 適用範圍:BigDecimalBigIntegerbyteByteshortShortintIntegerlongLong

  • @DecimalMin(value)

    • 說明:被註釋的元素必須是一個數字,其值必須大於等於指定的最小值

    • 適用範圍:BigDecimalBigIntegerCharSequencebyteByteshortShortintIntegerlongLong

  • @DecimalMax(value)

    • 說明:被註釋的元素必須是一個數字,其值必須小於等於指定的最大值

    • 適用範圍:BigDecimalBigIntegerCharSequencebyteByteshortShortintIntegerlongLong

  • @Size(max, min)

    • 說明:被註釋的元素的大小必須在指定的範圍內

    • 適用範圍:CharSequenceCollectionMapArray

  • @Digits (integer, fraction)

    • 說明:被註釋的元素必須是一個數字,其值必須在可接受的範圍內

    • 適用範圍:BigDecimalBigIntegerCharSequencebyte Byteshort Shortint Integerlong Long

  • @Past

    • 說明:被註釋的元素必須是一個過去的日期

    • 適用範圍:DateCalendarInstantLocalDateLocalDateTimeLocalTimeMonthDayOffsetDateTimeOffsetTimeYearYearMonthZonedDateTimeHijrahDateJapaneseDateMinguoDateThaiBuddhistDate

  • @Future

    • 說明:被註釋的元素必須是一個將來的日期

    • 適用範圍:DateCalendarInstantLocalDateLocalDateTimeLocalTimeMonthDayOffsetDateTimeOffsetTimeYearYearMonthZonedDateTimeHijrahDateJapaneseDateMinguoDateThaiBuddhistDate

  • @Pattern(value)

    • 說明:被註釋的元素必須符合指定的正則表達式

    • 適用範圍:CharSequencenull

  • @Email

    • 說明:被註釋的元素必須是電子郵箱地址

    • 適用範圍:CharSequence

  • @Length

    • 說明:被註釋的字符串的大小必須在指定的範圍內

  • @NotEmpty

    • 說明:被註釋的字符串的必須非空

  • @Range

    • 說明:被註釋的元素必須在合適的範圍內

具體使用

對於web服務來說,爲防止非法參數對業務造成影響,在Controller層一定要做參數校驗的!大部分情況下,請求參數分爲如下兩種形式:

  1. POSTPUT請求,使用requestBody傳遞參數;

  2. GET請求,使用requestParam/PathVariable傳遞參數。

下面我們簡單介紹下requestBodyrequestParam/PathVariable的參數校驗

requestBody參數校驗

POSTPUT請求一般會使用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的功能是非常強大的,它還支持分組校驗,嵌套校驗,集合校驗,自定義校驗等多種校驗方式,功能非常強大.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章