自定义注解结合SpringAop实现权限,参数校验,日志等等功能

Posted 有时间指导毕业设计SmallMonkey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义注解结合SpringAop实现权限,参数校验,日志等等功能相关的知识,希望对你有一定的参考价值。

文章目录

Aop(Aspect Orient Programming)

使用场景实现一些共性需求:

  1. 收集上报指定一些 重要的关键方法的入参,执行时间返回结果等等关键的信息进行上报到服务器,可以作为后面的调优。
  2. 幂等性的前置校验
  3. 调用重试机制
  4. 入参的共性校验
  5. 方法执行的进行相关扩展行为,记录日志,启动其他任务等等。

1.参数校验实现

1. 自定义注解 参数,集合等等校验注解

1.1 FiledCheck字段校验注解

package com.eshore.iscm.aop.validate.validator.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target( ElementType.PARAMETER, ElementType.FIELD )
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldCheck 

	/**
	 * 参数校验错误默认返回的信息
	 * 
	 * @return
	 */
	public String defaultMessage() default "";

	/**
	 * 不允许为空
	 * 
	 * @return
	 */
	public boolean notNull() default false;

	/**
	 * 为空时返回信息
	 * 
	 * @return
	 */
	public String notNullMessage() default "";

	/**
	 * 只允许数字
	 * 
	 * @return
	 */
	public boolean numeric() default false;
	
	

	/**
	 * 只允许数字错误信息
	 * 
	 * @return
	 */
	public String numericMessage() default "";
	
	/**
	 * 字符串只允许输入数字或空串
	 * 
	 * @return
	 */
	public boolean stringLimitNumeric() default false;
	
	
	/**
	 * 字符串只允许输入数字或空串
	 * 
	 * @return
	 */
	public String stringLimitNumericMessage() default "";
	
	/**
	 * 只对字符串、List起效,最小长度
	 * 
	 * @return
	 */
	public int minLen() default -1;

	/**
	 * 只对字符串、List起效,最大长度
	 * 
	 * @return
	 */
	public int maxLen() default -1;

	/**
	 * maxLen的错误信息
	 * 
	 * @return
	 */
	public String minLenMessage() default "";

	/**
	 * maxLen的错误信息
	 * 
	 * @return
	 */
	public String maxLenMessage() default "";

	/**
	 * 最小数字
	 * 
	 * @return
	 */
	public double minNum() default -999999999;

	/**
	 * 最大数字
	 * 
	 * @return
	 */
	public double maxNum() default -999999999;

	/**
	 * minNum错误信息
	 * 
	 * @return
	 */
	public String minNumMessage() default "";

	/**
	 * maxNum错误信息
	 * 
	 * @return
	 */
	public String maxNumMessage() default "";



1.2 ListCheck集合校验注解

package com.eshore.iscm.aop.validate.validator.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target( ElementType.PARAMETER, ElementType.FIELD )
@Retention(RetentionPolicy.RUNTIME)
public @interface ListCheck 

	public boolean notNull() default false;

	public String notNullMessage() default "";

	public int minLen() default -1;

	public String minLenMessage() default "";

	public int maxLen() default -1;

	public String maxLenMessage() default "";

	public String defaultMessage() default "";



1.3方法参数校验注解 ModelCheck

@Target( ElementType.METHOD, ElementType.PARAMETER )
@Retention(RetentionPolicy.RUNTIME)
public @interface ModelCheck 
	public boolean notNull() default true;

	public String notNullMessage() default "方法参数不能为空";

1.4 参数校验注解

package com.eshore.iscm.aop.validate.validator.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target( ElementType.METHOD )
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamCheck 







2.定义Aop并且通过反射进行和注解作用的地方(方法,参数,类)进行关联 反射可以单独写一个类,Aop的配置可以单独写一个类

2.1通过反射组合上面参数校验的注解灵活使用 (ParamterCheckComp 参数校验组合类)

package com.eshore.iscm.aop.validate.validator.comp;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import com.eshore.iscm.aop.validate.validator.anno.FieldCheck;
import com.eshore.iscm.aop.validate.validator.anno.ListCheck;
import com.eshore.iscm.aop.validate.validator.anno.ModelCheck;
import com.eshore.khala.common.exception.ValidateParameterException;

@Component
public class ParamterCheckComp 
	LocalVariableTableParameterNameDiscoverer disc = new LocalVariableTableParameterNameDiscoverer();

	public void checkValid(String methodName, Object target, Object[] args) throws ValidateParameterException 
		String str = "";
		try 
			Method method = getMethodByClassAndName(target.getClass(), methodName, args);
			Annotation[][] annotations = method.getParameterAnnotations();
			String[] paramNames = disc.getParameterNames(method);
			if (annotations != null) 
				for (int i = 0; i < annotations.length; i++) 
					Annotation[] anno = annotations[i];
					for (int j = 0; j < anno.length; j++) 
						if (annotations[i][j].annotationType().equals(ModelCheck.class)) 
							ModelCheck mcheck = (ModelCheck) annotations[i][j];
							str = checkModel(args[i], mcheck, paramNames[i]);
						 else if (annotations[i][j].annotationType().equals(ListCheck.class)) // List
							ListCheck lcheck = (ListCheck) annotations[i][j];
							str = checkListParam(args[i], lcheck, paramNames[i]);
						 else if (annotations[i][j].annotationType().equals(FieldCheck.class)) // Field
							FieldCheck fcheck = (FieldCheck) annotations[i][j];
							str = checkField(fcheck, args[i], paramNames[i]);
						
						if (StringUtils.hasText(str)) 
							throw new ValidateParameterException(str);
						
					
				
			
		 catch (Throwable e) 
//			System.out.println(e.getMessage());
			if (ObjectUtils.isEmpty(str)) 
				str = e.getMessage();
			
			throw new ValidateParameterException(str);
		
	

	public void checkValid(ProceedingJoinPoint joinPoint) throws ValidateParameterException 
		Object[] args = null;
		Method method = null;
		Object target = null;
		String methodName = null;
		String str = "";
		try 
			methodName = joinPoint.getSignature().getName();
			target = joinPoint.getTarget();
			args = joinPoint.getArgs(); // 方法的参数
			method = getMethodByClassAndName(target.getClass(), methodName, args);
			Annotation[][] annotations = method.getParameterAnnotations();
			String[] paramNames = disc.getParameterNames(method);
			if (annotations != null) 
				for (int i = 0; i < annotations.length; i++) 
					Annotation[] anno = annotations[i];
					for (int j = 0; j < anno.length; j++) 
						if (annotations[i][j].annotationType().equals(ModelCheck.class)) 
							ModelCheck mcheck = (ModelCheck) annotations[i][j];
							str = checkModel(args[i], mcheck, paramNames[i]);
						 else if (annotations[i][j].annotationType().equals(ListCheck.class)) // List
							ListCheck lcheck = (ListCheck) annotations[i][j];
							str = checkListParam(args[i], lcheck, paramNames[i]);
						 else if (annotations[i][j].annotationType().equals(FieldCheck.class)) // Field
							FieldCheck fcheck = (FieldCheck) annotations[i][j];
							str = checkField(fcheck, args[i], paramNames[i]);
						
						if (StringUtils.hasText(str)) 
							throw new ValidateParameterException(str);
						
					
				
			
		 catch (Throwable e) 
//			System.out.println(e.getMessage());
			throw new ValidateParameterException(str);
		
	

	private String checkField(FieldCheck check, Object arg, String paramNames) 
		int length = 0;
		if (arg == null) 
			if (check.notNull()) 
				return getNotNullMessage(paramNames, check);
			 else if (check.numeric()) 
				return getNumericMessage(paramNames, check);
			 else if (check.minLen() > 0) 
				return getMinLenMessage(paramNames, check);
			 else if (check.maxLen() > 0) 
				return getMaxLenMessage(paramNames, check);
			 else if (check.minNum() != -999999999) 
				return getMinNumMessage(paramNames, check, false);
			 else if (check.maxNum() != -999999999) 
				return getMaxNumMessage(paramNames, check, false);
			 else 
				return "";
			
		
		Class<?> cls = arg.getClass();
		String clname = cls.getName();
//        System.out.println("field-class: " + cls.getName());
		boolean arraybl = false, strbl = false, intbl = false, longbl = false, doublebl = false, floatbl = false,
				blbl = false;
		// 判断是否为数字
		if (clname.equals("java.lang.Integer") || clname.equals("int")) 
			intbl = true;
		 else if (clname.equals("java.lang.Long") || clname.equals("long")) 
			longbl = true;
		 else if (clname.equals("java.lang.Double") || clname.equals("double")) 
			doublebl = true;
		 else if (clname.equals("java.lang.Float") || clname.equals以上是关于自定义注解结合SpringAop实现权限,参数校验,日志等等功能的主要内容,如果未能解决你的问题,请参考以下文章

SpringAOP+自定义注解实现日志记录

SpringAOP的自定义注解实践

springboot通过AOP和自定义注解实现权限校验

springAOP自定义注解讲解

SpringBoot Validation参数校验 详解自定义注解规则和分组校验

springBoot参数联合校验,自定义分组校验