zoukankan      html  css  js  c++  java
  • spring Aop实现防止重复提交

    1.先定义一个注解

    import java.lang.annotation.*;
    
    /**
     * @desc 定义一个不重复提交的注解
     */
    @Target({ElementType.PARAMETER, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface NoRepeatCommit {
    
        String name() default "name:";
    }

    2.实现一个aop

    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    import java.util.Map;
    import java.util.concurrent.TimeUnit;
    
    import javassist.*;
    import javassist.bytecode.CodeAttribute;
    import javassist.bytecode.LocalVariableAttribute;
    import javassist.bytecode.MethodInfo;
    
    /**
     * @desc 防止重复提交aop
     */
    @EnableAspectJAutoProxy
    @Component
    @Aspect
    @Slf4j
    @Configuration
    public class NoRepeatSubmitAspect {
    
        private static final Cache<String, Object> CACHES = CacheBuilder.newBuilder()
                // 最大缓存 100 个
                .maximumSize(100)
                // 设置缓存过期时间为S
                .expireAfterWrite(2, TimeUnit.SECONDS)
                .build();
    
        @Pointcut("@annotation(com.shandie.im.web.aop.NoRepeatCommit)")
        public void point() {
        }
    
        @Around("point()")
        public Object interceptor(ProceedingJoinPoint pjp) {
            MethodSignature signature = (MethodSignature) pjp.getSignature();
            Method method = signature.getMethod();
            NoRepeatCommit form = method.getAnnotation(NoRepeatCommit.class);
            String key = getCacheKey(method,pjp,form);
    
            if (!StringUtils.isEmpty(key)) {
                if (CACHES.getIfPresent(key) != null) {
                    return RestResultDto.fail("请勿重复请求");
                }
                // 如果是第一次请求,就将key存入缓存中
                CACHES.put(key, key);
            }
            try {
                return pjp.proceed();
            } catch (Throwable throwable) {
                throw new RuntimeException("服务器开小差了,请稍后再试");
            } finally {
                CACHES.invalidate(key);
            }
        }
    
        /**
         * 缓存key生成方式
         * @param method
         * @param pjp
         * @param form
         * @return
         */
        private String getCacheKey(Method method, ProceedingJoinPoint pjp, NoRepeatCommit form) {
            try{
                Map<String, Object> map=getFieldsNameValueMap(pjp);
                if(ObjectHelper.isNotEmpty(map) && map.size()>0){
                    HpBaseDto baseDto= JSON.parseObject(JSON.toJSONString(map),HpBaseDto.class);
                    if(ObjectHelper.isNotEmpty(baseDto) && ObjectHelper.isNotEmpty(baseDto.getUserId())){
                        return form.name()+baseDto.getUserId();
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
            }
            return form.name()+ CustomIDGenerator.generate();
        }
    
        public static Map<String, Object> getFieldsNameValueMap(ProceedingJoinPoint joinPoint) throws Exception {
            Object[] args = joinPoint.getArgs();
            String classType = joinPoint.getTarget().getClass().getName();
            Class<?> clazz = Class.forName(classType);
            String clazzName = clazz.getName();
            //获取方法名称
            String methodName = joinPoint.getSignature().getName();
            Map<String, Object> map = Maps.newHashMap();
            ClassPool pool = ClassPool.getDefault();
            ClassClassPath classPath = new ClassClassPath(NoRepeatCommit.class);
            pool.insertClassPath(classPath);
            CtClass cc = pool.get(clazzName);
            CtMethod cm = cc.getDeclaredMethod(methodName);
            MethodInfo methodInfo = cm.getMethodInfo();
            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
            if (attr == null) {
                throw new RuntimeException();
            }
            int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
            //paramNames即参数名
            for (int i = 0; i < cm.getParameterTypes().length; i++) {
                map.put(attr.variableName(i + pos), args[i]);
            }
            return map;
        }
    }

    3.使用

     @PostMapping("/test")
        @NoRepeatCommit
        public RestResultDto aa(){
            return RestResultDto.success("success");
        }

    4.使用的包

  • 相关阅读:
    [转]Ubuntu Tweak 0.8.7 发布:支持 Ubuntu 14.04
    冷知识 —— 地名的解释
    冷知识 —— 地名的解释
    冷知识 —— 国家域名、国际电话区号列表
    冷知识 —— 国家域名、国际电话区号列表
    基于梯度的权重更新优化迭代算法
    基于梯度的权重更新优化迭代算法
    中英文对照 —— 图表等的可视化
    中英文对照 —— 图表等的可视化
    matplotlib plot 绘图函数发生阻塞(block)时的解决方法
  • 原文地址:https://www.cnblogs.com/huzi007/p/12859140.html
Copyright © 2011-2022 走看看