更加靈活的參數校驗,Spring-boot自定義參數校驗註解

上文測試開發專題:如何在spring-boot中進行參數校驗,我們討論了如何使用@Min、@Max等註解進行參數校驗,主要是針對基本數據類型和級聯對象進行參數校驗的演示,但是在實際中我們往往需要更為複雜的校驗規則,比如註冊用戶的密碼和確認密碼進行校驗,這個時候基本的註解就無法滿足我們的要求了,需要去按照業務需求去自定義註解進行校驗

元註解

在自定義註解之前我們有必要了解一些元註解,元註解就是在註解上的註解,可以對一個註解進行配置,元註解包括@Retention、@Target、@Document、@Inherited四種

  • @Retention,表示註解保留到什麼時候,有以下三種模式

    • @Retention(RetentionPolicy.SOURCE) 表示註解僅存在於源碼中,在class位元組碼文件中不包含
    • @Retention(RetentionPolicy.CLASS) 表示 默認的保留策略,註解會在class位元組碼文件中存在,但運行時無法獲得
    • @Retention(RetentionPolicy.RUNTIME) 表示註解會在class位元組碼文件中存在,在運行時可以通過反射獲取到 
  • @Target表示註解的作用目標是什麼,只列出下面幾個,剩餘的大家自行Google把

    • @Target(ElementType.TYPE) 表示註解可以應用於介面、類、枚舉、註解
    • @Target(ElementType.FIELD) 表示可以應用於欄位、成員變數、枚舉的常量等
    • @Target(ElementType.METHOD)表示可以作用於方法
  • @Document表示註解包含在javadoc中

  • @Inherited表示註解可以被繼承

自定義校驗註解

就以用戶註冊為例,我們需要校驗密碼和確認密碼是否一致以及是否符合密碼的規則,先新建一個PasswordEqual註解類

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Constraint(validatedBy = PasswordValidator.class)
public @interface PasswordEqual {

    String message() default "密碼不一樣";

    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

下面我們來解釋一下上面的註解,在PasswordEqual註解上,又標記了四個註解,前三個我們上面已經說過了。

這裡說一下@Constraint註解,它表示這個註解是一個驗證註解,並且通過validatedBy指定自定義校驗註解的關聯類,PasswordValidator類就是我們自定義的註解關聯的類。

註解裡面的groups和payload方法是模板方法,實現自定義註解必須寫這麼兩個方法。

定義驗證類

驗證類裡面包含具體的驗證邏輯了,下面是一個簡版的:

public class PasswordValidator implements ConstraintValidator<PasswordEqual, BannerCreateDto> {

    @Override
    public boolean isValid(BannerCreateDto dto, ConstraintValidatorContext constraintValidatorContext) {
        
        return false;
    }
}

這裡需要對上面的程式碼進行一下說明,實現自定義校驗類必須實現

ConstraintValidator介面,它是一個泛型介面,需要指定兩個類型參數,第一個是自定義註解類型,第二個類型指定自定義註解修飾目標的類型,就是準備把自定義註解標記到什麼類型上面。

必須重寫isValid方法,所有的校驗邏輯都在這個方法裡面,下面我們簡單寫一下:

@Override
public boolean isValid(UserDto dto, ConstraintValidatorContext constraintValidatorContext) {
    if (dto.getPassword().equals(dto.getConfirmPassword())){
        return true;
    }
    return false;
}

然後我們將自定義的註解類標記到UserDto類上:

@Builder
@Getter
@Setter
@PasswordEqual
public class UserDto {

    @Length(min = 4, max = 10, message = "用戶名長度必須在4-10個字元之間")
    private String name;

    private String password;

    private String confirmPassword;
}

接下來我們在寫一個簡單的創建用戶的介面:

@RestController
public class UserController {


    @PostMapping("/v2/user/create")
    @ResponseBody
    public UserDto createUser(@RequestBody @Validated UserDto dto){
        return dto;
    }
}

注意這裡有要使用@ResponseBody能夠返回自動序列化自定義對象,並且要寫上 @Validated開啟校驗機制。

我們先輸入正確的密碼和確認密碼一下:

image-20200514233442583

可以看到能夠正常的返回數據,這時再把兩個密碼改的不一樣,試試:

image-20200514233522345

這個時候就拋出了異常,這裡的異常資訊是因為進了全局異常處理器,不清楚的童鞋可以看下之前的文章。我們再來看一下控制台的輸出:

image-20200514233648244

控制台已經輸出了校驗的錯誤資訊。

總結

我們今天介紹了自定義參數校驗,並編寫了校驗註解和校驗類,但是最後返回給用戶的資訊非常不友好,需要針對參數校驗錯誤,能夠返回定義的message,能夠讓有用戶明白是哪裡錯了,下篇文章我們將介紹這塊的內容,敬請關注!!

歡迎大家去 我的部落格 瞅瞅,裡面有更多關於測試實戰的內容哦!!