论坛首页新手上路 签到
查看: 4573|回复: 0

[知识分享] 自定义参数校验注解

[复制链接]
金智-周雷

该用户从未签到

11

主题

11

帖子

33

积分

初来乍到

凡人

Rank: 1

积分
33
发表于 2017-9-2 14:18:15 | 显示全部楼层 |阅读模式
自定义参数校验注解

------------------------------------------------
目的:
   使用springmvc自带的校验参数的注解@Valid,不支持webservice接口。建议自定义注解,利用AOP切面进行参数校验。








------------------------------------------------
自定义注解
  1. /**
  2. * <pre>
  3. * 描述:字段校验的注解
  4. * 举例:
  5. * 校验长度@FV(names="REGEX", pattern="^[\\s\\S]{0,1000}$", msg="长度必须小于等于1000")
  6. * @FV(names="TRIM,REGEX", pattern="^(0|1|2)$", msg="值超出范围:{0:所有;1:教职工;2:学生}")
  7. * </pre>
  8. * @author 01116253
  9. * @since 1.0
  10. */
  11. @Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到  
  12. @Target({ElementType.FIELD})//定义注解的作用目标**作用范围字段、枚举的常量/方法  
  13. @Documented//说明该注解将被包含在javadoc中  
  14. public @interface FV {  
  15.   
  16.     /**
  17.      * 字段校验方法 ,如NOTNULL,NOTBLANK,REGEX,TRIM,CODEVALID,NAMEVALID。英文逗号分隔。
  18.      * @return
  19.      */  
  20.     String names() default "";  
  21.     /**
  22.      * 字段正则校验时的表达式
  23.      * @return
  24.      */  
  25.     String pattern() default "";
  26.     /**
  27.      * 字段校验失败的描述
  28.      * @return
  29.      */  
  30.     String msg() default "";  
  31. }  
复制代码

  1. /**
  2. * <pre>
  3. * 描述:获取到注解
  4. * </pre>
  5. * @author 01116253
  6. * @since 1.0
  7. */
  8. public class FieldValid {  
  9.   
  10.     private FV meta;  
  11.     private Field field;  
  12.     private Object val;
  13.       
  14.     public FieldValid(){}  
  15.    
  16.     public FieldValid(FV meta, Field field, Object val) {  
  17.         super();  
  18.         this.meta = meta;  
  19.         this.field = field;  
  20.         this.val=val;
  21.     }  

  22. }
复制代码
  1. /**
  2. * 描述:注解校验类的工厂
  3. *
  4. * @author Administrator
  5. * @since 1.0
  6. */
  7. public class ValidFactory {
  8.     public static final String NOTNULL="NOTNULL";
  9.     public static final String NOTBLANK="NOTBLANK";
  10.     public static final String REGEX="REGEX";
  11.     public static final String TRIM="TRIM";
  12.     public static final String CODEVALID="CODEVALID";
  13.     public static final String NAMEVALID="NAMEVALID";
  14.    
  15.     public IValid createValid(String metaName){
  16.         if(NOTNULL.equals(metaName)){
  17.             return NotNullValid.getInstance();
  18.         }
  19.         if(NOTBLANK.equals(metaName)){
  20.             return NotBlankValid.getInstance();
  21.         }
  22.         if(REGEX.equals(metaName)){
  23.             return RegexValid.getInstance();
  24.         }
  25.         if(TRIM.equals(metaName)){
  26.             return TrimValid.getInstance();
  27.         }
  28.         if(CODEVALID.equals(metaName)){
  29.             return CodeValid.getInstance();
  30.         }
  31.         if(NAMEVALID.equals(metaName)){
  32.             return NameValid.getInstance();
  33.         }
  34.         throw new MyException("未设置"+metaName+"校验处理器");
  35.     }
  36. }
复制代码
  1. public interface IValid {
  2.     static final LoggerDecorate logger = LoggerDecorateFactory.getLogger(IValid.class);
  3.     String valid(FieldValid f, Object bean);
  4. }
复制代码
  1. /**
  2. * 描述:非空校验举例
  3. *
  4. * @author Administrator
  5. * @since 1.0
  6. */
  7. public class NotBlankValid implements IValid {

  8.     private NotBlankValid() {
  9.     }

  10.     private static class SingletonFactory {
  11.         private static NotBlankValid instance = new NotBlankValid();
  12.     }

  13.     /* 静态工程方法,创建实例 */
  14.     public static NotBlankValid getInstance() {
  15.         return SingletonFactory.instance;
  16.     }

  17.     public String valid(FieldValid f, Object bean) {
  18.         StringBuilder err = new StringBuilder();
  19.         FV meta = f.getMeta();
  20.         Field field = f.getField();
  21.         Object val = f.getVal();
  22.         if (null==val || StringUtils.isBlank(val.toString())) {
  23.             String message = meta.msg();
  24.             if (StringUtils.isNotBlank(message)) {
  25.                 FieldUtil.createErrMsg(field, message, err);
  26.             } else {
  27.                 err.append(field.getName());
  28.                 err.append("不能为空");
  29.             }
  30.             err.append(";");
  31.         }
  32.         return err.toString();
  33.     }
  34. }
复制代码
  1. /**
  2. * <pre>
  3. * 描述:运行时获取注解
  4. * </pre>
  5. * @author 01116253
  6. * @since 1.0
  7. */
  8. public class BaseBeanValid {  
  9.   
  10.     /**
  11.      * <pre>
  12.      * 校验参数
  13.      * </pre>
  14.      * @throws IllegalArgumentException
  15.      * @throws IllegalAccessException
  16.      */
  17.     public static <T> void validField(T bean) throws IllegalArgumentException, IllegalAccessException{
  18.         List<FieldValid> fields = listFieldValid(bean);
  19.         StringBuilder err = new StringBuilder();
  20.         ValidFactory vf = new ValidFactory();
  21.         IValid v = null;
  22.         for(FieldValid f : fields){
  23.             String names = f.getMeta().names();
  24.             if(StringUtils.isBlank(names)){
  25.                 continue;
  26.             }
  27.             //多个,则按顺序校验,遇到第一个失败则返回
  28.             String[] nameArray = names.split(",");
  29.             for(String name : nameArray){
  30.                 v = vf.createValid(name); // 校验类实例
  31.                 String errmsg = v.valid(f, bean); // 校验结果
  32.                 if(StringUtils.isNotBlank(errmsg)){
  33.                     err.append(errmsg);
  34.                     break;
  35.                 }
  36.             }
  37.         }
  38.         if(err.length()>0){
  39.             throw new MyException(ResultCode.PARAM_ERROR, err.toString()); //参数校验异常
  40.         }
  41.     }
  42.    
  43.     /**
  44.      * <pre>
  45.      * 获取FieldMeta注解的字段
  46.      * </pre>
  47.      * @return
  48.      * @throws IllegalAccessException
  49.      * @throws IllegalArgumentException
  50.      */
  51.     private static <T> List<FieldValid> listFieldValid(T bean) throws IllegalArgumentException, IllegalAccessException{  
  52.         List<FieldValid> list = new ArrayList<FieldValid>();  
  53.         Class entity = bean.getClass();  
  54.         if(entity!=null){  
  55.             /*
  56.              * 返回类中所有字段,包括公共、保护、默认(包)访问和私有字段,获取包括父类在内的所有字段
  57.              * */  
  58.             List<Field> fields = BeanUtil.listField(entity);
  59.             for(Field f : fields){  
  60.                 //获取字段中包含fieldMeta的注解  
  61.                 FV meta = f.getAnnotation(FV.class);  
  62.                 if(meta!=null){  
  63.                     f.setAccessible(true); //设置些属性是可以访问的  
  64.                     Object val = f.get(bean);//得到此属性的值
  65.                     FieldValid sf = new FieldValid(meta, f, val);  
  66.                     list.add(sf);  
  67.                 }  
  68.             }  
  69.         }  
  70.         return list;  
  71.          
  72.     }  
  73. }  
复制代码




------------------------------------------------
利用AOP切面进行参数校验
  1. /**
  2. * <pre>
  3. * 描述:切面记录请求日志,拦截各种接口
  4. * </pre>
  5. * @author 01116253
  6. * @since 1.0
  7. */
  8. @Aspect
  9. @Component
  10. public class LogAspect {
  11.     private static LoggerDecorate logger = LoggerDecorateFactory.getLogger(LogAspect.class);
  12.     private static final String REQ = "REQ";
  13.     private static final String RSP = "RSP";

  14.     @Pointcut("execution(* com.wisedu.api.message.controller..*Controller.*(..))"
  15.             + "|| execution(* com.wisedu.api.app.controller..*Controller.*(..))"
  16.             + "|| execution(* com.wisedu.api.transfer.controller..*Controller.*(..))")
  17.     public void api() {
  18.     }

  19.     @Around("api()")
  20.     public Object invoke(ProceedingJoinPoint pjp) throws Throwable {

  21.         Object[] arguments = pjp.getArgs();

  22.         validBaseReq(arguments);
  23.         
  24.         Object rsp = pjp.proceed();
  25.         
  26.         return rsp;

  27.     }

  28.     public void validBaseReq(Object... params) throws IllegalArgumentException, IllegalAccessException {
  29.         if (ArrayUtils.isEmpty(params)) {
  30.             return;
  31.         }
  32.         for (Object object : params) {
  33.             if (null == object) {
  34.                 throw new MyException(ResultCode.PARAM_ERROR, "Bean参数不能为null");
  35.             }
  36.             if (object.getClass().isArray()) {
  37.                 Object[] objectArr = (Object[]) object;
  38.                 if (ArrayUtils.isNotEmpty(objectArr)) {
  39.                     for (Object item : objectArr) {
  40.                         validBaseReq(new Object[] { item });
  41.                     }
  42.                 }
  43.             } else if ((object instanceof IBaseReq)) {
  44.                 ((IBaseReq) object).verify();
  45.                 BaseBeanValid.validField(object);
  46.             }
  47.         }
  48.     }
  49.    
  50. }
复制代码





------------------------------------------------
使用注解
  1. public class CheckSchoolAppCustomCReq implements IBaseReq{
  2.    
  3.     @FV(names="NOTBLANK,TRIM")
  4.     private String schoolCode;
  5.    
  6.     @FV(names="NOTBLANK,TRIM")
  7.     private String domainCode;
  8.    
  9.     @FV(names="NOTBLANK,TRIM")
  10.     private String serverId;

  11.     @FV(names="NOTBLANK,TRIM")
  12.     private String appName;

  13.     @FV(names="NOTBLANK,TRIM")
  14.     private String appVersion;


  15.     @Override
  16.     public void verify() {
  17.         
  18.     }
  19.    

  20. }
复制代码




像猪一样乐观,像鱼一样自由
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

Archiver|手机版|小黑屋|江苏金智教育信息股份有限公司 ( 系统管理员:binmeng@wisedu.com  

GMT+8, 2021-4-23 07:53

Powered by Discuz! X3.2

© 2015 Design: www.wisedu.com

快速回复 返回顶部 返回列表