使用@Constraint配合自定義註解開發

前言

通常我們在開發的過程中,需要對前端傳入的數據進行校驗,儘管這一步已經在前端進行了一次校驗,雖然現在已經有了很多校驗的註解,@NotNull、@NotBlank、@URL等一系列註解幫助我們進行校驗,但是在實際的業務開發過程中,這些可能不足以滿足我們的需求,這時候我們就需要自己來定義註解了。

可能需要用到的依賴按需導入:

		<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.logging</groupId>
            <artifactId>jboss-logging</artifactId>
            <version>3.3.0.Final</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml</groupId>
            <artifactId>classmate</artifactId>
            <version>1.3.3</version>
        </dependency>

@Constraint

這個註解的主要作用就是幫助我們來處理驗證邏輯的,根據根據自己的業務需求來完成這一塊驗證的邏輯。下面我們就來簡單測試一下。

**場景 **:假設我們一個實體類的屬性如下解釋,我們需要對前端傳入的數字是不是0或1。

/**
     * 顯示狀態[0-不顯示;1-顯示]
     */
    private Integer showStatus;

定義註解

@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class})
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER,ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValue {
   
    String message() default "{com.atguigu.common.valid.ListValue.message}";

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

    
}

message():錯誤信息,如果我們沒有在註解中定義錯誤信息的話,他會默認去尋找com.atguigu.common.valid.ListValue.message爲key的錯誤信息
groups():這個主要是來進行分組驗證的。
** vals() ** :自行定義的值

我們可以看到@Constraint中
@Constraint(validatedBy = {ListValueConstraintValidator.class})
這段意思是我們將此註解的驗證邏輯交給ListValueConstraintValidator來處理,這裏是一個數組,我們可以傳入多個處理邏輯。

ConstraintValidator接口,它有兩個泛型,第一個是自定義的註解類,第二個就是要驗證的數據的類型,這兩個類裏面都有兩個方法,initialize和isValid,第一個是初始化方法,第二個是驗證的邏輯方法,返回true,則驗證通過,否則則不通過。

ListValueConstraintValidator自定義驗證邏輯

public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {

    private Set<Integer> set = new HashSet<>();
    /**
     * 初始化 加載註解的信息。也就是帶有此註解Bean上的vals值
     * @param constraintAnnotation
     */
    @Override
    public void initialize(ListValue constraintAnnotation) {
        int[] vals = constraintAnnotation.vals();
        for (int val : vals) {
            set.add(val);
        }
    }

    /**
     * 判斷是否校驗成功
     * @param value 需要校驗的值 實際傳入的值
     * @param context 上下文信息
     * @return
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {

        return set.contains(value);
    }
}

** ValidationMessages.properties **

規範(JSR303)說,我必須將ValidationMessages.properties放到我的類路徑根目錄中,我希望它應該是MyDeploymentUnit.war / WEB-INF / classes / ValidationMessages.properties,這就是我的應用程序的構建和部署方式。出於調試原因,我將此代碼添加到了自定義驗證器中,以確保文件存在並正確設置。

在這裏插入圖片描述
key就是我們在註解定義的默認 message的值。

測試

在Controller中需要進行校驗的Bean加上 ** @Validated ** 註解
在這裏插入圖片描述

需要驗證的 屬性
在這裏插入圖片描述
這裏的如果校驗不通過的話,他會拋出一個異常,我們只需要捕獲到這個錯誤信息即可。
在這裏插入圖片描述

如果我們去掉屬性聲明的message信息 他會去尋找默認的ValidationMessages.properties下的信息。

在這裏插入圖片描述

分組校驗

可能大家會注意到我在Controller中使用 @Validated 註解時會帶有一個value值,他的作用是對操作進行分組。比如請看如下

	@NotNull(message = "修改商品時請傳入商品id",groups = {UpdateGroup.class})
    @Null(groups = {AddGroup.class},message = "不能指定id")
    @TableId
    private Long brandId;

商品的數據表的對應的ID,我們可能在進行新增操作時無需我們來指定對應的ID,因爲我們一般設置都會默認自增的。而我們在查詢或者更新的時候可能會根據ID來查出這一條記錄。總的來說的就是在進行更新時需要ID,新增不需要。每一個註解都會帶有groups這個屬性來聲明自己的組。

如何使用呢?
很簡單:

定義對應的接口或者類。

public interface AddGroup {
}
// ------------------------------
public interface UpdateGroup {
}
//---------------------------------
public interface UpdateStatusGroup {
}

我們只需要定義三個接口來聲明組,無需任何操作。

在Controller中的@Validated 註解中聲明對那個組進行驗證。

@RequestMapping("/save")
    public R save(@Validated(value = {AddGroup.class}) @RequestBody BrandEntity brand) {
        brandService.save(brand);
        return R.ok();
    }

實體類進行分組邏輯

	@NotNull(message = "修改商品時請傳入商品id",groups = {UpdateGroup.class})
    @Null(groups = {AddGroup.class},message = "不能指定id")
    @TableId
    private Long brandId;

驗證: 新增時:傳入ID會失敗
在這裏插入圖片描述

更新時:不傳ID 會失敗
在這裏插入圖片描述

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