使用注解校验参数
Posted 格物致知
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用注解校验参数相关的知识,希望对你有一定的参考价值。
一:为什么使用注解
在项目开发中,参数的校验是不可避免的,通常情况下,我们会使用if条件判断,如果
前台传递很多参数过来,那么需要写很多累赘的if代码来校验参数,而使用注解可以避免
这个问题,注解需要依赖javaBean,在字段上我们可以绑定一些元数据,然后在校验的
使用使用,下面是一个简单的实例:
自定义注解:NotNull
package com.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * */ /** * @author Administrator * 校验非空字段 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface NotNull { String value(); }
javaBean:Person,在字段上面我们可以绑定一些元数据
/** * */ package com.hlcui.entity; import com.annotation.NotNull; /** * @author Administrator * */ public class Person { @NotNull(value="身份证号不能为空") private String id; @NotNull(value="姓名不能为空") private String name; private String salary; private String mgr; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getSalary() { return salary; } public void setSalary(String salary) { this.salary = salary; } public String getMgr() { return mgr; } public void setMgr(String mgr) { this.mgr = mgr; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", salary=" + salary + ", mgr=" + mgr + "]"; } }
自定义异常类:
/** * */ package com.hlcui.exception; /** * @author Administrator * */ public class CustBusinessException extends RuntimeException{ /** * */ private static final long serialVersionUID = 1L; public CustBusinessException() { } public CustBusinessException(String s) { super(s); } public CustBusinessException(String s, Throwable throwable) { super(s, throwable); } public CustBusinessException(Throwable throwable) { super(throwable); } }
我们还需要一个注解解析器,也可以叫做控制器,通常是通过反射得到注解信息:
/** * */ package com.hlcui.util; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; import com.annotation.NotNull; import com.hlcui.exception.CustBusinessException; /** * @author Administrator * */ public class CommonUtils { /** * 通过反射来获取javaBean上的注解信息,判断属性值信息,然后通过注解元数据 * 来返回 * @param t */ public static <T> void doValidator(T t){ Class<?> clazz = t.getClass(); Field[] fields = clazz.getDeclaredFields(); for(Field field:fields){ NotNull notNull = field.getDeclaredAnnotation(NotNull.class); if(null!=notNull){ Object value = getValue(t,field.getName()); if(!notNull(value)){ throwExcpetion(notNull.value()); } } } } public static <T> Object getValue(T t,String fieldName){ Object value = null; try { BeanInfo beanInfo = Introspector.getBeanInfo(t.getClass()); PropertyDescriptor[] props = beanInfo.getPropertyDescriptors(); for(PropertyDescriptor property:props){ if(fieldName.equals(property.getName())){ Method method = property.getReadMethod(); value = method.invoke(t,new Object[]{}); } } } catch (Exception e) { e.printStackTrace(); } return value; } public static boolean notNull(Object value){ if(null==value){ return false; } if(value instanceof String && isEmpty((String)value)){ return false; } if(value instanceof List && isEmpty((List<?>)value)){ return false; } return null!=value; } public static boolean isEmpty(String str){ return null==str || str.isEmpty(); } public static boolean isEmpty(List<?> list){ return null==list || list.isEmpty(); } public static void throwExcpetion(String msg){ if(null!=msg){ throw new CustBusinessException(msg); } } public static void handlerExcpetion(Exception e){ if(e instanceof CustBusinessException){ System.out.println(((CustBusinessException)e).getMessage()); }else{ System.out.println("调用失败"); } } }
然后我们可以测试校验情况:
/** * */ package com.hlcui.test; import org.junit.Test; import com.hlcui.entity.Person; import com.hlcui.util.CommonUtils; /** * @author Administrator * */ public class TestAnnotation { @Test public void testNotNull() { try { Person person = new Person(); person.setId("1"); person.setName("李白"); CommonUtils.doValidator(person); } catch (Exception e) { CommonUtils.handlerExcpetion(e); } } }
首先把
person.setId("1");
这行注释掉,运行结果会怎样呢?
身份证号不能为空
校验成功!
下面将比较重要的代码做一下讲解:
1:
public static <T> void doValidator(T t){ Class<?> clazz = t.getClass(); Field[] fields = clazz.getDeclaredFields(); for(Field field:fields){ NotNull notNull = field.getDeclaredAnnotation(NotNull.class); if(null!=notNull){ Object value = getValue(t,field.getName()); if(!notNull(value)){ throwExcpetion(notNull.value()); } } } }
首先形参为一个实体对象,这里是使用泛型,然后通过getClass()方法,获取该对象的字节码对象Class,
进而得到所有的字段,然后遍历字段,获取每个字段上面的注解,如果没有注解,则为null,说明不需要校验
,如果不为null,则获取该字段的值,然后判断是否为空(包括null或者""),如果是则抛出异常。
2:
public static <T> Object getValue(T t,String fieldName){ Object value = null; try { BeanInfo beanInfo = Introspector.getBeanInfo(t.getClass()); PropertyDescriptor[] props = beanInfo.getPropertyDescriptors(); for(PropertyDescriptor property:props){ if(fieldName.equals(property.getName())){ Method method = property.getReadMethod(); value = method.invoke(t,new Object[]{}); } } } catch (Exception e) { e.printStackTrace(); } return value; }
这里面用到了内省(反射中专门针对javaBean),根据该类的字节码文件获取Beaninfo对象,顾名思义就是
包含bean信息的一个对象,然后获取每一个字段的描述器,通过描述器可以获取每个字段的名称、set方法、get
方法,可以获取字段的值,也可以set对象的值,很方便。
当然还可以使用拼接的方式,接set+字段,来得到set方法,和get方法。
以上是关于使用注解校验参数的主要内容,如果未能解决你的问题,请参考以下文章