Java自定义注解校验参数信息

2018-08-27  本文已影响0人  嬉皮码龙

项目要求

实际项目中存在诸多场景需要校验入参数据。繁杂的参数校验占据相当部分的代码量,且不友好。
为便于实际开发写出此注解,切合实际的开发需求,多种场景的数据校验,并抛出自定义的异常信息,便于控制层处理,简化代码。

对比优势

1.繁杂的Hibernate校验注解,且不宜定制化开发,不适合多场景数据校验。
2.自定义注解,配合多场景数据校验,可定制化配置,可扩展,高效,易懂的配置。

自定义注解

  1. 注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 校验参数注解  可根据需要扩展校验数据的选项,比如值区间max,min,值域
 * @author vinod
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Validation {
    //校验的属性的类型
    ValidateType value() default ValidateType.TYPE_STRING;
    //配置则根据当前字段校验 默认为空
    String accordField() default "";
    //根据accordField的值校验值 默认为空
    String accordValue() default "";
    //正数校验 默认不校验
    boolean isPositive() default false;
}
  1. 数据类型枚举
/**
 * 校验枚举
 * @author vinod
 */
public enum ValidateType {
    TYPE_STRING,
    TYPE_INTEGER,
    TYPE_CHAR,
    TYPE_LONG,
    TYPE_FLOAT,
    TYPE_DOUBLE,
    TYPE_BOOLEAN,
    TYPE_DATE,
    TYPE_LIST,
    TYPE_MAP,
    TYPE_SET,
    TYPE_OBJECT
}

注解处理类

1.注解使用: bean中声明属性校验

public class UserInfo implements Serializable{
    @Validate(ValidateType.TYPE_STRING)
    private String username;
    // 此处则可配置值域为(1,2),需扩展注解
    private Integer sex;       // 1:男 2:女
    // 配置当前字段根据sex=2时才校验非空,
    @Validate(value = ValidateType.TYPE_STRING,accordField = "sex",accordValue = "2")
    private String size;
}

2.调用方法处理

// 1.1 校验必填字段
ValidationHandler.validateParams(req);

3.注解处理类源代码

import com.vinod.test.util.exception.UserDefineException;
import com.vinod.test.util.annotation.Validation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 仅处理传入object中的Validate注解
 * @author vinod
 */
public class ValidationHandler {

    private static Logger logger = LoggerFactory.getLogger(ValidationHandler.class);
    // 方法重载
    public static void validateParams(Object obj){
        validateParams(obj,null,true);
    }

    public static void validateParams(Object obj,boolean accordFlag){
        validateParams(obj,null,accordFlag);
    }

    /**
     * 校验参数不为空
     * @param obj 需要校验的对象
     * @param excludeParams 需要排除校验的属性名集合
     * @param accordFlag 根据属性依赖校验
     */
    public static void validateParams(Object obj,Set<String> excludeParams,boolean accordFlag){
        logger.info("xxxx日志记录");

        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(obj);
                // 当前属性在需要排除校验的集合中时,跳过当前字段校验。
                if(excludeParams!=null&&excludeParams.contains(field.getName())){
                    continue;
                }
                Validation annotation = (Validation)field.getAnnotation(Validation.class);
                //System.out.println("=====----"+annotation+"---> "+field.getName());
                //注解存在时,则说明当前字段需要校验
                if(annotation!=null){
                    // 是否根据依据筛选为空属性
                    if(accordFlag){
                        // 根据某字段判别是否为空
                        if(StringUtils.isNotEmpty(annotation.accordField())){
                            Field accordField = obj.getClass().getDeclaredField(annotation.accordField());
                            accordField.setAccessible(true);
                            Object accordValue = accordField.get(obj);
                            // 为空或不等于注解预设值则跳过当前属性的校验
                            if(accordValue==null||!accordValue.toString().equals(annotation.accordValue())){
                                continue;
                            }
                        }
                    }
                    // 属性值不能为空
                    if(value==null){
                        throw new UserDefineException(field.getName());
                    }
                    checkTypeEnumValue(annotation,field,value,annotation.isPositive());
                }
            } catch (IllegalAccessException e) {
                // e.printStackTrace();
                logger.info("xxxx日志记录");
               //抛出自定义异常信息
               throw new UserDefineException(field.getName());
            } catch (NoSuchFieldException e) {
               logger.info("xxxx日志记录");
               //抛出自定义异常信息
               throw new UserDefineException(field.getName());
            }
        }
    }

    /**
     * 校验注解配置的属性值
     * @param annotation
     * @param field  
     * @param value
     * @param isPositive
     */
    private static void checkTypeEnumValue(Validation annotation, Field field, Object value,boolean isPositive){
        // 暂值列举几种数据处理,剩余类型处理类似
        switch (annotation.value()){
            case TYPE_STRING:
                if(StringUtils.isEmpty(value.toString())||"null".equals(value.toString().toLowerCase())){
                    throw new UserDefineException(field.getName());
                }
                break;
            case TYPE_LONG:
                if(0L==(Long)value){
                    throw new UserDefineException(field.getName());
                }
                if(isPositive&&(Long)value<0){
                    throw new UserDefineException(field.getName());
                }
                break;
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读