spring aop实现参数验证篇

一. 自定义注解

1.首先我们需要定义一组ValidateGroup以数组的形式存放多个ValidateFiled需要校验的参数,话不多说上代码。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ValidateGroup {
	ValidateFiled[] fileds() ;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ValidateFiled {
	
	/**
	 * 参数索引位置
	 */
	public int index() default -1 ;
	
	/**
	 * 如果参数是基本数据类型或String ,就不用指定该参数,如果参数是对象,要验证对象里面某个属性,就用该参数指定属性名
	 */
	public String filedName() default "" ;
	
	/**
	 * 正则验证
	 */
	public String regStr() default "";
	
	/**
	 * 是否能为空  , 为true表示不能为空 , false表示能够为空
	 */
	public boolean notNull() default false;
	
	/**
	 * 最大长度 , 用户验证字符串
	 */
	public int maxLen() default -1 ;
	
	/**
	 * 最小长度 , 用户验证字符串
	 */
	public int minLen() default -1 ;
	
	/**
	 *最大值 ,用于验证数字类型数据
	 */
	public int maxVal() default -1 ;
	
	/**
	 *最小值 ,用于验证数值类型数据
	 */
	public int minVal() default -1 ;
	
	
	
	/**  各自系统定义code,message  **/
	/**
	 * 返回编码
	 * @return
	 */
	public BizCode icode() default BizCode.CLIENT_ERROR;
	
	/**
	 *描述,用于校验不通过时参数描述
	 */
	public String message() default  "" ;
	
	
}

2.注解切面:

/**
 * 验证注解处理类
 * @author ysj
 * @Data 2019-01-15
 */
@Component
@Aspect
public class ValidateAspectHandel implements Ordered {
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	/**
	 * 使用AOP对使用了ValidateGroup的方法进行代理校验
	 * @throws Throwable 
	 */
	@SuppressWarnings({ "finally", "rawtypes" })
	@Around("@annotation(com.ayc.framework.aspect.ValidateGroup)")
	public Object validateAround(ProceedingJoinPoint joinPoint) throws Throwable  {
		Object[] args = joinPoint.getArgs();		//方法的参数	
		Object target = joinPoint.getTarget();
		String methodName = joinPoint.getSignature().getName();
		Method method = getMethodByClassAndName(target.getClass(), methodName);	//得到拦截的方法
		ValidateGroup an = (ValidateGroup)getAnnotationByMethod(method ,ValidateGroup.class );
		Map<String,String> resultMap = new HashMap<String,String>();
		try{
			validateFiled(an.fileds() , args , resultMap);
		}catch(Exception e){
			logger.error("系统校验参数异常:",e);
			resultMap.put("respCode", "99999");
			resultMap.put("respMsg", "自定义异常" + "原因0:" + e.getMessage());
		}finally{
            //是否验证通过
			if(BizCode.SUCCESS.getCode().equals(resultMap.get("respCode"))){
				return joinPoint.proceed();
			}else{
				Class<?> returnType = method.getReturnType();	//得到方法返回值类型
			     //处理参数验证失败后的业务
			}
			
		}
	}

	/**
	 * 验证参数是否合法
	 */
	public void validateFiled( ValidateFiled[] valiedatefiles , Object[] args,Map<String,String> resultMap){
		for (ValidateFiled validateFiled : valiedatefiles) {
			try{
				Object arg = null;
				if("".equals(validateFiled.filedName()) ){
					arg = args[validateFiled.index()];
				}else{
					arg = getFieldByObjectAndFileName(args[validateFiled.index()] ,
							validateFiled.filedName() );
				}

				if(validateFiled.notNull()){		//判断参数是否为空
					if(arg == null ){
						resultMap.put("respCode", validateFiled.icode().getCode());
						resultMap.put("respMsg",   validateFiled.message() + "为空");
						return;
					}
				}else{		//如果该参数能够为空,并且当参数为空时,就不用判断后面的了 
					if(arg == null ){
						continue;
					}
				}

				if(validateFiled.maxLen() > 0){		//判断字符串最大长度
					if(((String)arg).length() > validateFiled.maxLen()){
						resultMap.put("respCode", validateFiled.icode().getCode());
						resultMap.put("respMsg",  validateFiled.message() + "长度超过允许最大长度");
						return;
					}
				}

				if(validateFiled.minLen() > 0){		//判断字符串最小长度
					if(((String)arg).length() < validateFiled.minLen()){
						resultMap.put("respCode", validateFiled.icode().getCode());
						resultMap.put("respMsg",   validateFiled.message() + "长度小于最小长度");
						return;
					}
				}

				if(arg != null) {
					if(validateFiled.maxVal() != -1){	//判断数值最大值
						if( (Integer)arg > validateFiled.maxVal()) {
							resultMap.put("respCode", validateFiled.icode().getCode());
							resultMap.put("respMsg",   validateFiled.message() + "大小大于允许最大值");
							return;
						}
					}
					
					if(validateFiled.minVal() != -1){	//判断数值最小值
						if((Integer)arg < validateFiled.minVal()){
							resultMap.put("respCode", validateFiled.icode().getCode());
							resultMap.put("respMsg",  validateFiled.message() + "小于小大于允许最小值");
							return;
						}
					}
				}

				if(!"".equals(validateFiled.regStr())){	//判断正则
					if(arg instanceof String){
						if(!((String)arg).matches(validateFiled.regStr())){
							resultMap.put("respCode", validateFiled.icode().getCode());
							resultMap.put("respMsg",  validateFiled.message() + "不满足验证的表达式");
							return;
						}
					}else{
						resultMap.put("respCode", validateFiled.icode().getCode());
						resultMap.put("respMsg",  validateFiled.message());
						return;
					}
				}
			}catch(Exception e){
				logger.error("校验字段时候出现异常,字段信息:{},{}", validateFiled.index(), validateFiled.filedName(), e);
                //自定义异常类抛出。
				
			}
		}
		resultMap.put("respCode","00000");
		resultMap.put("respMsg","验证通过");
	}

	/**
	 * 根据对象和属性名得到 属性
	 */
	public Object getFieldByObjectAndFileName(Object targetObj , String fileName) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
		String tmp[] = fileName.split("\\.");
		Object arg = targetObj ;
		for (int i = 0; i < tmp.length; i++) {
			Method methdo = arg.getClass().
					getMethod(getGetterNameByFiledName(tmp[i]));
			arg = methdo.invoke(arg);
		}
		return arg ;
	}

	/**
	 * 根据属性名 得到该属性的getter方法名
	 */
	public String getGetterNameByFiledName(String fieldName){
		return "get" + fieldName.substring(0 ,1).toUpperCase() + fieldName.substring(1) ;
	}

	/**
	 * 根据目标方法和注解类型  得到该目标方法的指定注解
	 */
	public Annotation getAnnotationByMethod(Method method , Class<?> annoClass){
		Annotation all[] = method.getAnnotations();
		for (Annotation annotation : all) {
			if (annotation.annotationType() == annoClass) {
				return annotation;
			}
		}
		return null;
	}

	/**
	 * 根据类和方法名得到方法
	 */
	public Method getMethodByClassAndName(Class<?> c , String methodName){
		Method[] methods = c.getDeclaredMethods();
		for (Method method : methods) {
			if(method.getName().equals(methodName)){
				return method ;
			}
		}
		return null;
	}

	@Override
	public int getOrder() {
		return 1;
	}

}

 

使用方法:BizCode 为自定义错误码枚举类,此方法我就不贴出来了

    

// 例1:验证token是否为空。
// 例2: 验证TestDto中name属性是否为空。


@ValidateGroup(fileds = {
            @ValidateFiled(index = 0, notNull = true, icode = BizCode.CLIENT_ERROR, message = "token"),
            @ValidateFiled(index = 1, notNull = true, icode = BizCode.CLIENT_ERROR, message = "表单"),
            @ValidateFiled(index = 1, filedName = "name", notNull = true, icode = BizCode.CLIENT_ERROR, message = "名称"),
    })
    @PostMapping("test")
    @ResponseBody
    public AjaxResult test(@RequestHeader String token, @RequestBody TestDto dto) {
    
    }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值