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" 转载请保留原文链接及作者。