1. 程式人生 > >@Constraint註解配合自定義驗證型別註解的開發

@Constraint註解配合自定義驗證型別註解的開發

前言:雖然現在有很多很有用的驗證註解,如@not null,@not blank,@not [email protected]等等。但是我們可能有時候根據專案的拓展這些驗證註解不夠用,那怎麼辦,解決的辦法就是自定義驗證註解

 

1,@Constraint註解

說到自定義驗證型別的註解,那就要說說@Constraint這個官方註解了,我們既然自定義了註解,那麼註解的邏輯在哪裡處理呢?沒錯,就是這個@Constraint幫我們處理。

2,程式碼講解:

/**
 * uid是否屬於當前上下文租戶
 * 注:當被校驗物件為空時,校驗為通過,所以如果需要校驗物件必填,請自行結合相關校驗註解
 * Created by Zhang JinLong(150429) on 2016-09-18.
 */
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {SameTenant.StringChecker.class, SameTenant.LongChecker.class})
@Documented
public @interface SameTenant {

    String message() default "使用者不存在或者不屬於當前組織";

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

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

    class StringChecker implements ConstraintValidator<SameTenant, String> {

        @Override
        public void initialize(SameTenant arg0) {
        }

        @Override
        public boolean isValid(String uid, ConstraintValidatorContext context) {

            System.out.print("到註解裡面了"+uid);
            if (StringUtils.isBlank(uid)) {

                return true;
            }
            return false;
        }
    }

    class LongChecker implements ConstraintValidator<SameTenant, Long> {

        @Override
        public void initialize(SameTenant arg0) {
        }

        @Override
        public boolean isValid(Long uid, ConstraintValidatorContext context) {
            if (null == uid) {
                return true;
            }
            return false;
        }
    }
}

在上面的這個自定義驗證註解中,

@Constraint(validatedBy = {SameTenant.StringChecker.class, SameTenant.LongChecker.class}) 

這段代表註解的處理邏輯是SameTenant.StringChecker.class和SameTenant.LongChecker.class這兩個類,也可以只定義一個,多個用逗號分開。

(本程式碼中這兩個類一個處理傳遞string型別和傳遞long型別時分別呼叫不同的處理邏輯)

 

而從上面程式碼可以看出,我們類的內部定義了兩個類,也可以在外部定義,這裡為了方便。這兩個類就是分別處理兩種資料型別的邏輯方法。那麼它是怎麼區分的呢?

class StringChecker implements ConstraintValidator<SameTenant, String> {   和     class LongChecker implements ConstraintValidator<SameTenant, Long> {    看出有什麼不同嗎?沒錯,在最後面一個是String,一個是Long。而這兩個都要實現

ConstraintValidator介面,它有兩個泛型,第一個是自定義的註解類,第二個就是要驗證的資料的型別(例如寫了String型別的資料,那麼這個註解就要放在String型別的欄位上才會起作用,也可以向我上面那樣寫兩個,自動識別String和Long, 最簡便的寫成Object,那麼它可以接收任何資料型別的資料)。而這兩個類裡面都有兩個方法,initialize

isValid,第一個是初始化方法,第二個是驗證的邏輯方法,返回true,則驗證通過,否則則不通過。

 

3,贈言(很重要):

這個自定義註解邏輯處理類由於實現了ConstraintValidator介面,所以它預設被spring管理成bean,所以可以在這個邏輯處理類裡面用@Autowiredu或者@Resources注入別的服務,而且不用在類上面用@Compent註解成spring的bean.

 

自定義驗證型別註解類裡面由於是用於驗證資料,一般在裡面加上

String message() default "使用者不存在或者不屬於當前組織";

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

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

如上面程式碼也加上了。你也可以檢視官方驗證註解,也有這三行。