zoukankan      html  css  js  c++  java
  • 使用注解校验参数

    一:为什么使用注解

    在项目开发中,参数的校验是不可避免的,通常情况下,我们会使用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方法。

  • 相关阅读:
    Eclipse编译 make: arm-linux-gcc:命令未找到
    ubuntu如何启用root帐号
    jlinkV8指示灯不亮 usb无法识别的问题。
    Normal Equation Algorithm求解多元线性回归的Octave仿真
    Normal Equation Algorithm
    一维高斯分布与多维高斯分布
    Locally weighted regression algorithm
    Linear Regression and Gradient Descent
    导数与偏导数 Derivative and Partial Derivative
    向量的内积、长度和正交性
  • 原文地址:https://www.cnblogs.com/warrior4236/p/7172320.html
Copyright © 2011-2022 走看看