@Target:注解和@Retention注解

@Target:注解的作用目标

用于自定义注解时
@Target(ElementType.TYPE)——接口、类、枚举、注解
@Target(ElementType.FIELD)——字段、枚举的常量
@Target(ElementType.METHOD)——方法
@Target(ElementType.PARAMETER)——方法参数
@Target(ElementType.CONSTRUCTOR) ——构造函数
@Target(ElementType.LOCAL_VARIABLE)——局部变量
@Target(ElementType.ANNOTATION_TYPE)——注解
@Target(ElementType.PACKAGE)——包

package java.lang.annotation;
 
/**
 * The constants of this enumerated type provide a simple classification of the
 * syntactic locations where annotations may appear in a Java program. These
 * constants are used in {@link Target java.lang.annotation.Target}
 * meta-annotations to specify where it is legal to write annotations of a
 * given type.
 * @author  Joshua Bloch
 * @since 1.5
 * @jls 9.6.4.1 @Target
 * @jls 4.1 The Kinds of Types and Values
 */
public enum ElementType {
    /** 类, 接口 (包括注释类型), 或 枚举 声明 */
    TYPE,
 
    /** 字段声明(包括枚举常量) */
    FIELD,
 
    /** 方法声明(Method declaration) */
    METHOD,
 
    /** 正式的参数声明 */
    PARAMETER,
 
    /** 构造函数声明 */
    CONSTRUCTOR,
 
    /** 局部变量声明 */
    LOCAL_VARIABLE,
 
    /** 注释类型声明 */
    ANNOTATION_TYPE,
 
    /** 包声明 */
    PACKAGE,
 
    /**
     * 类型参数声明
     *
     * @since 1.8
     */
    TYPE_PARAMETER,
 
    /**
     * 使用的类型
     *
     * @since 1.8
     */
    TYPE_USE
}

@Retention:注解的保留位置

RetentionPolicy.SOURCE:这种类型的Annotations只在源代码级别保留,编译时就会被忽略,在class字节码文件中不包含。
RetentionPolicy.CLASS:这种类型的Annotations编译时被保留,默认的保留策略,在class文件中存在,但JVM将会忽略,运行时无法获得。
RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。

package java.lang.annotation;
/**
 * Annotation retention policy.  The constants of this enumerated type
 * describe the various policies for retaining annotations.  They are used
 * in conjunction with the {@link Retention} meta-annotation type to specify
 * how long annotations are to be retained.
 *
 * @author  Joshua Bloch
 * @since 1.5
 */
public enum RetentionPolicy {
    /**
     * 注释只在源代码级别保留,编译时被忽略
     */
    SOURCE,
    /**
     * 注释将被编译器在类文件中记录
     * 但在运行时不需要JVM保留。这是默认的
     * 行为.
     */
    CLASS,
    /**
     *注释将被编译器记录在类文件中
     *在运行时保留VM,因此可以反读。
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

实际运用

定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ReSubmit {

	// 是否允许重复提交(默认不允许)
	boolean allow() default false;
	
}

切面类

@Aspect
@Component
public class ControllerAspect {
	
	private static final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);
	
	@Autowired
	private OperationLogService operationLogService;
	@Autowired
	private RedisService redisService;

	
	private static final String[] NO_ASPECT_LOG = {"/login","/loginAgain","/validateCode","/logout"};
	
	private static final String CUT = "execution(*com.sk.Controller..*.*(..))";
	
	@Around(CUT)
	public Object doAround(ProceedingJoinPoint joinPoint){
		Date requestTime = new Date();
		Signature signature = joinPoint.getSignature();
		String methodName = signature.getName();
		Object[] objs = joinPoint.getArgs();
		String traceId = CommonUtils.getUUID();
		RpcContext.getContext().setAttachment(CommonConstant.TRACE_ID, traceId);
		MDC.put(CommonConstant.TRACE_ID, traceId);
		String requestInfo = JSON.toJSONString(objs);
		if(logger.isInfoEnabled()) {
		    logger.info(" ### {} start and param : {}", methodName, requestInfo);
		}
		ResponseVO<?> returnValue = null;
		try {
			// 单位时间(2秒)内重复提交限制
			checkResubmit(signature, requestInfo);
			
			//TODO 服务型功能码过期判断
			
			//TODO 参数特殊字符处理
			
			Object returnObj = joinPoint.proceed();
			
			if(returnObj instanceof ResponseVO) {
				returnValue = (ResponseVO<?>)returnObj;
			}
		} catch(BusinessException e) {
		    if(logger.isErrorEnabled()) {
		        logger.error(" process exception", e);
	        }
			returnValue = ResponseVO.failed(e);
		} catch (Throwable e) {
		    if(logger.isErrorEnabled()) {
		        logger.error(" process exception", e);
	        }
			returnValue = ResponseVO.failed();
		} finally {
		    if(logger.isInfoEnabled()) {
				logger.info(" ### {} finish and use time {} ms, returnvalue : {} ", new Object[] {methodName, System.currentTimeMillis()-requestTime.getTime(), JSON.toJSONString(returnValue)});
			}
		    MDC.remove(CommonConstant.TRACE_ID);
		}
		
		// 操作日志记录
		try {
			BaseController b = (BaseController)joinPoint.getTarget();
			String operateUri = WebUtils.getPathWithinApplication(b.getRequest());
			if(!Arrays.toString(NO_ASPECT_LOG).contains(operateUri)) {
				SysOperationLogVo operVo = new SysOperationLogVo();
				operVo.setOperateUri(operateUri);
				operVo.setChannel(ChannelEnum.WEB.toString());
				operVo.setRequestTime(requestTime);
				operVo.setUseTime(System.currentTimeMillis()-requestTime.getTime());
				operVo.setResponseTime(new Date());
				operVo.setRequestParams(JSON.toJSONString(objs));
				operVo.setResponseCode(null==returnValue ? "unknown" : returnValue.getCode());
				operVo.setResponseInfo(null==returnValue ? "unknown" : JSON.toJSONString(returnValue));
				SessionUser sessionUser = SessionUtil.getSessionUser();
				if(sessionUser != null) {
					operVo.setOperateUser(sessionUser.getUserId());
					operVo.setOperateUserName(sessionUser.getUserName());
					operVo.setPermitName(sessionUser.getPermsMap().get(operateUri));
				}
				AsyncTaskUtil.asyncTask(new OperationLogAsyncTask(operationLogService, operVo));
			}
		}catch (Exception e) {
			logger.error(" operationLogService.insertSysOperationLog error ", e);
		}
		
		return returnValue;
	}

	private void checkResubmit(Signature signature, String requestInfo) {
		MethodSignature methodSignature  = (MethodSignature) signature;
		Method method = methodSignature.getMethod();
		ReSubmit reSubmit = method.getAnnotation(ReSubmit.class);
		if(reSubmit != null) {
			boolean allow = reSubmit.allow();
			if(!allow) {
				String md5Key = DigestUtils.md5Hex(new StringBuilder("").append(requestInfo).toString()).toLowerCase();
				String value = (String)redisService.get(md5Key);
				if(!CommonUtils.isNullOrEmpty(value)) {
					throw ManagerWebException.RE_SUBMIT;
				}else {
					redisService.set(md5Key, "1", 2);
				}
			}
		}
	}


}

(https://blog.csdn.net/fengcai0123/article/details/90544338)
(https://blog.csdn.net/liang100k/article/details/79515910?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值