1. 程式人生 > >java中自定義註解@interface在自定義校驗器validator中的使用

java中自定義註解@interface在自定義校驗器validator中的使用

一,自定義註解中元註解

1,保留位置:Retention

    1.1 @Retention(RetentionPolicy.SOURCE) //僅存在於原始碼中,在class位元組碼檔案中不存在
    1.2 @Retention(RetentionPolicy.CLASS) // (預設)存在於class位元組碼檔案中,但執行時無法獲得
    1.3 @Retention(RetentionPolicy.RUNTIME) //存在於class位元組碼檔案中,執行時可以通過反射獲取到

2,作用目標:Targer

[email protected](ElementType.TYPE)   //介面、類、列舉、註解
    2.2 @Target(ElementType.FIELD) //欄位、列舉的常量
    2.3 @Target(ElementType.METHOD) //方法
    2.4 @Target(ElementType.PARAMETER) //方法引數
    2.5 @Target(ElementType.CONSTRUCTOR)  //建構函式
    2.6 @Target(ElementType.LOCAL_VARIABLE)//區域性變數
    2.7 @Target(ElementType.ANNOTATION_TYPE)//註解
    2.8 @Target(ElementType.PACKAGE) ///包 

3,@Document

    註解將被包含在javadoc中

4,@Inherited

    子類可以繼承父類中的該註解

舉個例子:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
public @interface InEnum {
    Class<? extends Enum> source();
String key() default "";
    boolean useGet() default false;
}
@Retention(RetentionPolicy.RUNTIME
) @Target({ElementType.FIELD, ElementType.PARAMETER}) public @interface InEnumStr { Class<? extends Enum> source(); String key(); boolean useGet() default false; String split(); }

二,自定義校驗器

1.校驗結果

public class ValidateResult {

    private int code;
    private boolean valid = false;
    private 
FailedReason failedReason; public static final ValidateResult SUCCESS = new ValidateResult(true); private ValidateResult() { } private ValidateResult(boolean valid) { this.valid = valid; } private ValidateResult(boolean valid, int code, FailedReason failedReason) { this.valid = valid; this.code = code; this.failedReason = failedReason; } public static ValidateResult ERROR(int code, FailedReason failedReason) { return new ValidateResult(false, code, failedReason); } public boolean isValid() { return valid; } public FailedReason getFailedReason() { return failedReason; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } }
public class FailedReason {

    private String fieldName;
    private Object fieldValue;
    private String reason;
    private String notice;
    public FailedReason() {
    }

    public FailedReason(String fieldName, String reason) {
        this.fieldName = fieldName;
        this.reason = reason;
}

    public FailedReason(String fieldName, Object fieldValue, String reason) {
        this.fieldName = fieldName;
        this.fieldValue = fieldValue;
        this.reason = reason;
}

    public FailedReason(String fieldName, Object fieldValue, String reason, String notice) {
        this.fieldName = fieldName;
        this.fieldValue = fieldValue;
        this.reason = reason;
        this.notice = notice;
}

    public String getFieldName() {
        return fieldName;
}

    public FailedReason setFieldName(String fieldName) {
        this.fieldName = fieldName;
        return this;
}

    public Object getFieldValue() {
        return fieldValue;
}

    public void setFieldValue(Object fieldValue) {
        this.fieldValue = fieldValue;
}

    public String getReason() {
        return reason;
}

    public FailedReason setReason(String reason) {
        this.reason = reason;
        return this;
}

    public String getNotice() {
        return notice;
}

    public FailedReason setNotice(String notice) {
        this.notice = notice;
        return this;
}

    @Override
public String toString() {
        return JSONObject.toJSONString(this);
}
}

2.支援型別

public class SupportEnumType {
    public static final Logger LOGGER = LoggerFactory.getLogger(SupportEnumType.class);
    static final Set<Class> set = new HashSet<>();
    static {
        set.add(Integer.TYPE);
set.add(Integer.class);
set.add(int.class);
set.add(Long.TYPE);
set.add(Long.class);
set.add(long.class);
set.add(Double.TYPE);
set.add(Double.class);
set.add(double.class);
set.add(Float.TYPE);
set.add(Float.class);
set.add(float.class);
set.add(String.class);
}

    public static boolean support(Class clazz) {
        return set.contains(clazz);
}

    public static Method getMethod(Class clazz, String methodName) {
        try {
            Method method = clazz.getDeclaredMethod(methodName);
            return method;
} catch (Exception e) {
            try {
                Method method = clazz.getMethod(methodName);
                return method;
} catch (Exception ex) {
            }
            LOGGER.error("列舉類{}中,方法{}不存在", clazz.getCanonicalName(), methodName);
LOGGER.error("列舉值獲取異常", e);
}
        return null;
}
}

3.匹配值

public enum MEMBER_TYPE_ENUM {
    PERSON(1, "個人使用者"),
SELLER(2, "商家使用者"),
ENTERPRISE(3, "企業使用者");
MEMBER_TYPE_ENUM(int code, String desc) {
        this.code = code;
        this.desc = desc;
}

    private int code;
    private String desc;
    public int code() {
        return this.code;
}

    public String desc() {
        return this.desc;
}

    public static boolean validate(int code){
        for(MEMBER_TYPE_ENUM item : MEMBER_TYPE_ENUM.values()){
            if(code == item.code()){
                return true;
}
        }
        return false;
}

    public static MEMBER_TYPE_ENUM convert(int code){
        for(MEMBER_TYPE_ENUM item : MEMBER_TYPE_ENUM.values()){
            if(code == item.code()){
                return item;
}
        }
        return null;
}
}

4.校驗器

@Component
public class InEnumValidator extends AbstractAnnotationValidator<InEnum> {

    public static final Logger LOGGER = LoggerFactory.getLogger(InEnumValidator.class);
    static Set<Class> set = new HashSet<>();
@Override
public ValidateResult validate(InEnum inEnum, String paramName, Object paramValue) {
        if (paramValue == null) {
            return ValidateResult.SUCCESS;
}
        if (!SupportEnumType.support(paramValue.getClass())) {
            LOGGER.warn("不支援的型別:{}", paramValue.getClass());
}

        Class<? extends Enum> clazz = inEnum.source();
StringBuilder sb = new StringBuilder();
        boolean validate = false;
String key = inEnum.key();
        if (StringUtils.isNotEmpty(key)) {
            boolean useGetter = inEnum.useGet();
Method method = null;
            if (useGetter) {
                String methodName = "get" + key.substring(0, 1).toUpperCase() + key.substring(1);
method = SupportEnumType.getMethod(clazz, methodName);
} else {
                method = SupportEnumType.getMethod(clazz, key);
}
            if (method == null) {
                throw new RuntimeException("載入列舉校驗器失敗");
}

            for (Object obj : clazz.getEnumConstants()) {
                try {
                    Object value = method.invoke(obj);
sb.append(value).append(",");
                    if (!validate) {
                        boolean result = paramValue.equals(value);
                        if (result) {
                            validate = true;
}
                    }
                } catch (Exception e) {
                    throw new RuntimeException("列舉校驗器執行失敗");
}
            }
        } else {
            Field[] fields = clazz.getFields();
            for (Field field : fields) {
                sb.append(field.getName()).append(",");
                if (field.getName().equals(paramValue)) {
                    validate = true;
                    break;
}
            }
        }

        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
}
        if (!validate) {
            String msg = "引數驗證不通過, " + paramName + "無效的值, 可接受的取值有:" + sb;
            return ValidateResult.ERROR(this.getErrorCode(), new FailedReason(paramName, paramValue, msg, ""));
}
        return ValidateResult.SUCCESS;
}

    @Override
public void afterPropertiesSet() throws Exception {
        register(InEnum.class, this);
}

}
public abstract class AbstractAnnotationValidator<T> implements InitializingBean {

    @Resource
private ValidateProperty validateProperty;
    private static final ConcurrentHashMap<Class<? extends Annotation>, AbstractAnnotationValidator> VALIDATOR_MAP = new ConcurrentHashMap<>();
    protected void register(Class<? extends Annotation> annotationType, AbstractAnnotationValidator validator) {
        VALIDATOR_MAP.putIfAbsent(annotationType, validator);
}

    public abstract ValidateResult validate(T t, String paramName, Object paramValue);
    public static AbstractAnnotationValidator getValidator(Annotation annotation) {
        if (annotation != null) {
            return getValidator(annotation.annotationType());
}
        return null;
}

    public static AbstractAnnotationValidator getValidator(Class<? extends Annotation> annotationType) {
        return VALIDATOR_MAP.get(annotationType);
}

    public static Set<Class<? extends Annotation>> getValidatorAnnotationSet() {
        return VALIDATOR_MAP.keySet();
}

    public boolean isValidAnnotation(Class<? extends Annotation> annotationType) {
        return VALIDATOR_MAP.containsKey(annotationType);
}

    public static boolean hasValidator(Annotation annotation) {
        return VALIDATOR_MAP.containsKey(annotation.annotationType());
}

    public int getErrorCode() {
        return validateProperty.getErrorCode();
}
}

5.校驗器使用

public class TestQueryRequest extends DateRequest {
    
    @ApiModelProperty(value = "1:個人使用者 2:商家使用者 3:企業使用者")
    @InEnum(source = MEMBER_TYPE_ENUM.class, key = "code", useGet = false)
    private Integer memberType;
    public String getMemberTypeStr() {
        return memberTypeStr;
}

    public void setMemberTypeStr(String memberTypeStr) {
        this.memberTypeStr = memberTypeStr;
}

}


相關推薦

java定義註解@interface定義validator的使用

一,自定義註解中元註解1,保留位置:Retention    1.1 @Retention(RetentionPolicy.SOURCE) //僅存在於原始碼中,在class位元組碼檔案中不存在    1.2 @Retention(RetentionPolicy.CLASS)

Java】——定義註解對引數進行、spring掃描定義註解

前提    上篇部落格中詳細介紹自定義註解的使用,本文主要是對自定義註解的進一步深入。會使用CGLIb進行動態代理來完成對方法引數是否為空的判斷,以及再spring中如何掃描自定義註解自定義註解對方法引數為空校驗為什麼要用動態代理?因為Java的反射拿不到引數的相關資訊,對方

java定義註解 @interface

       @interface是用來自定義註釋型別的,如果你不瞭解Java註釋,可以參閱上一篇文章:"JDK5.0註釋(Annotation)的用法"。        一般的應用程式開發人員可能從不需要定義一個註釋型別,但定義我們自己的註釋型別並不複雜。註釋型別的定義跟定義一個介面相似,我們需要在

定義@interface及groups

groups @interface一、自定義annotation摘自:http://elim.iteye.com/blog/1812584@Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME)

SpringMVC Hibernate validator使用以及定義註解

Hibernate validator使用以及自定義校驗器註解 Hibernate Validator常用註解 1.建立自定義校驗器 import javax.validation.Constraint; import javax.validation.Payloa

定義註解的實現

首先先學習一下註解,註解為我們在程式碼中新增資訊提供了一種形式化的方法,使得我們在稍後的某個時刻可以方便地使用這些資料。     在日常的編碼中我們一直都在使用註解,只是沒有特別關注過,Java中內建了三種註解:@Override,@SuppressWarnings @Deprecated。相信只要學習過J

定義一個--------------------------完成用戶註冊時候,對username是否符合規則以及時候已經存在於數據庫的

實例 check ajax -- value ava .cn java 數據 實例: <!-- 自定義校驗表單--> $.validator.addMethod( "checkusername", //校驗規則名稱,類似於required

定義例項

1.建立校驗器類MyValidator.java。該類繼承於FieldValidatortSupport類 package action; import com.opensymphony.xwork2.validator.ValidationException; impo

Excel定義函式_身份證號碼

先上校驗規則 身份證號碼校驗規則一般應有: 位數校驗:是否18位 性別校驗:號碼所反映的性別與登記的文字性別是否一樣 日期校驗:①年份 出生年份比當前系統年份晚為錯,早於100也記為錯,應核實;②月份數值 應在01-12之間;③日期數值 1/3/5/7/8/10/12

Bean Validation完結篇:你必須關注的邊邊角角(約束級聯、定義約束、定義、國際化失敗訊息...)

每篇一句 沒有任何技術方案會是一種銀彈,任何東西都是有利弊的 相關閱讀 【小家Java】深入瞭解資料校驗:Java Bean Validation 2.0(JSR303、JSR349、JSR380)Hibernate-Validation 6.x使用案例 【小家Spring】Spring方法級別資料校驗:

Java實現MD5演算法過程,並利用帶MD5函式進行對比

文章目錄 一、環境說明 二、演算法原理概述 三、程式設計 資料結構 重要模組步驟 四、執行結果 一、環境說明 作業系統:window10 程式語言:Java (J

學習LayUI時研的表單引數框架

開發背景&痛點:每次寫前端的表單的時候需要對錶單裡使用者填寫的內容進行校驗,減少伺服器壓力,提前對已知錯誤對使用者提示。每次會要寫很多的if else等等對輸入框中的內容進行判斷,並對為空、格式不正確等情況作出對應提示。需要寫大量重複的if else語句,實在太麻煩,所以自己寫了這個框架用於前端引數的

tcp/ip通信ip頭部結構iph->check計算

gis htm con tput must 保存 cnblogs har add 通過raw socket修改通信數據後,可通過該函數重新校驗計算iph->check值 在http://www.cnblogs.com/dpf-10/p/7899237.html查看實際

Element-ui的表單怎麽添加正則

手機號碼 cti func req mod blur trigge ret str 1. 以中國大陸手機號驗證為例 // 這是組價的代碼 <el-form-item prop="mobile"> <el-input type="text" v-mo

java 程式碼實現各資料的正則

最近公司的專案,關於excel匯入匯出,對資料要進行校驗,所以就對資料的正則校驗就用的比較多,自己也是一點點去查,現在專案完成了,就把所有用到的都做一個小結,或許以後還可以用到! package org.asyware.insurance.util; import java.util.reg

springmvc 註解開發之 validation

專案中使用較多的是前端的校驗,比如頁面中js校驗。對於安全要求較高的建議在服務端進行校驗。 服務端校驗:   控制層controller:校驗頁面請求的引數的合法性,在服務端控制層controller校驗,不區分客戶端型別(瀏覽器、手機客戶端、遠端呼叫)  業務層se

Java 驗證身份證號的合法性(只利用位)

import java.util.Scanner; public class E201_06_04_身份證驗證 { public static void main(String[] args)

20180929:終於大致搞清楚python flsak_wtf improt flaskform 是怎樣完成

一個簡單的Form表單(forms.py)大概如下:賬號+密碼+提交按鈕 from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField fr

Java——使用springboot2.0+kaptcha進行驗證碼

pom檔案 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/200

java&javaScript常見

身份證號校驗: java 實現 package validator; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Cale