Java validate 注解验证工具类及自定义验证注解

1.基本注解

JAVA注解参考 https://blog.csdn.net/briblue/article/details/73824058

看到这里你可能会想到注解只有成员变量,没有方法。那么我们应该怎样通过只有成员变量的注解来达到类似java validate注解的功能呢。我们的注解只是用于验证字段,所以注解的属性应该是

  • 只作用于成员变量
  • 是要在运行中使用的
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotBlankA {
    String message() default "字段为空";
    //NotBlank.class bean内有相关的验证方法
    //继承 Ival,抽象编程,减少代码量
    Class<? extends IVal> valClass() default NotBlank.class;
}

2.验证方法类

注解中不能写方法,但是可以有class类型,来以此达到注解和验证类绑定的目的。(valClass返回验证类的class类型,我们就可以实例出验证类

//注解成员
Class<? extends IVal> valClass() default NotBlank.class;

其中 Ival 为接口,通过抽象编程、向上转型,这样我们写验证的时候可以减少很大的代码量。

public interface IVal {
    //初始化注解
    public boolean init(Annotation a);
    //验证方法
    public String isValid(String v);
}

NotBlank 类内容如下,提供了验证方法

public class NotBlank implements IVal {

    private NotBlankA a;

    @Override
    public boolean init(Annotation a) {
       this.a = (NotBlankA) a;
        return true;
    }

    @Override
    public String isValid(String v) {
        if (v == null || "".equals(v)) {
            return a.message();
        } else {
            return "";
        }
    }
}

3.验证

到这里,我们就需要写类验证相关的类了。接下来验证Util做的就是找到待验证bean内字段上的注解,判断注解是否为注解类,初始化并验证了。

得到字段get方法,以便取值

//循环字段
for (Field field : bean.getClass().getDeclaredFields()) {
    Method getMethod;
    try {
        PropertyDescriptor pd = new PropertyDescriptor(field.getName(), bean.getClass());
        getMethod = pd.getReadMethod();
    } catch (Exception e) {
        log.info("处理失败:" + field.getName() + "@" + bean.getClass().getName(), e);
        continue;
    }
}

得到注解,得到验证类实例

for (Field field : bean.getClass().getDeclaredFields()) {
    for (Annotation anno : field.getAnnotations()) {
        //此处的 anno 即为注解,然后做判断,
        Method clazzMethod;
        try {
            //valClass 有此方法即为验证注解,因为是咱们自己写的嘛
            clazzMethod = anno.getClass().getDeclaredMethod("valClass");
            if (clazzMethod != null) {
                //得到注解绑定的 class
                Class valClazz = (Class) clazzMethod.invoke(anno);
                //得到实例,此处 向上转型统一调用接口方法,不关心实现
                IVal val= (IVal) valClazz.newInstance();
            }
        } catch (Exception e) {
            log.info("绑定消息处理协议时失败:", e);
        }
    }
}

验证,并返回结果,最终的代码如下

@Slf4j
public class ValFactoryUtil {
    /**
     * @param bean 请求对象
     * @return
     */
    public static String validate(Object bean) {
        //遍历一个类的成员变量
        for (Field field : bean.getClass().getDeclaredFields()) {
            Method getMethod;
            try {
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), bean.getClass());
                getMethod = pd.getReadMethod();
            } catch (Exception e) {
                log.info("绑定消息处理协议时失败:" + field.getName() + "@" + bean.getClass().getName(), e);
                continue;
            }
            if (getMethod != null) {
                for (Annotation anno : field.getAnnotations()) {
                    try {
                        //得到注解绑定的验证类实例
                        IVal validator = genValidator(anno);
                        if (validator != null) {
                            //初始化,主要是为了得到注解中的提示信息 message,反馈给方法
                            validator.init(anno);
                            String result = validator.isValid((String) getMethod.invoke(bean));
                            if (StringUtils.isNotBlank(result)) {
                                return result;
                            }
                        }
                    } catch (Exception e) {
                        log.info("处理时失败:" + field.getName() + "@" + bean.getClass().getName(), e);
                    }
                }
            }
        }
        //这个是递归去找父类的字段并验证
        if (!bean.getClass().getSuperclass().equals(Object.class)) {
            validate(bean.getClass().getSuperclass());
        }
        return "";
    }
    private static IVal genValidator(Annotation anno) {
        Method clazzMethod;
        try {
            clazzMethod = anno.getClass().getDeclaredMethod("valClass");
            if (clazzMethod != null) {
                Class valClazz = (Class) clazzMethod.invoke(anno);
                IVal val = (IVal) valClazz.newInstance();
            }
        } catch (Exception e) {
            log.info("绑定消息处理协议时失败:", e);
        }
        return null;
    }
}

4.注解用法

@Data
public class TestBean {
    @NotBlankA(message = "name 为空")
    private String name;
}

public static void main(String[] args) {
    TestBean bean = new TestBean();
    String res = ValFactoryUtil.validate(bean);
    System.out.println(res);
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 rockeycui@163.com

文章标题:Java validate 注解验证工具类及自定义验证注解

文章字数:884

本文作者:崔石磊(RockeyCui)

发布时间:2018-08-07, 21:32:16

原始链接:https://cuishilei.com/Java-validate-注解验证.html

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏