zoukankan      html  css  js  c++  java
  • springboot aop本地缓存防止重复提交

     实现原理:

    1. 自定义防止重复提交标记(@RepeatSubmit)。
    2. 对需要防止重复提交的Congtroller里的mapping方法加上该注解。
    3. 新增Aspect切入点,为@RepeatSubmitAspect加入切入点。
    4. 每次提交表单时,Aspect都会保存当前key到reids(须设置过期时间)。
    5. 重复提交时Aspect会判断当前redis是否有该key,若有则拦截。
    public enum CaffeineCaches {
    
        baseUsers,
        userRequestUrls(3L, 1000);
        
        private int maxSize = 1000; //默认最大缓存数量
        private Long ttl = 3600L;   //默认过期时间(单位:秒)
    
        CaffeineCaches(){
        }
    
        CaffeineCaches(Long ttl,int maxSize){
            this.ttl = ttl;
            this.maxSize = maxSize;
        }
    
        public int getMaxSize(){
            return maxSize;
        }
    
        public Long getTtl(){
            return ttl;
        }
    }
    @Configuration
    public class CacheConfig {
    
        @Bean
        public CacheManager cacheManager(){
            SimpleCacheManager manager = new SimpleCacheManager();
            List<CaffeineCache> cacheList = new ArrayList<>();
            for(CaffeineCaches ca: CaffeineCaches.values()){
                cacheList.add(new CaffeineCache(ca.name(),
                        Caffeine.newBuilder().recordStats()
                        .expireAfterWrite(ca.getTtl(), TimeUnit.SECONDS)
                        .maximumSize(ca.getMaxSize())
                        .build()));
            }
            manager.setCaches(cacheList);
            return manager;
        }
    
    }
    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 RepeatSubmit {
    }
    import lombok.extern.slf4j.Slf4j;
    @Slf4j
    @Aspect
    @Component
    public class RepeatSubmitAspect {
        
        @Autowired
        private CacheManager caffeineCacheManager;
    
        @Pointcut("@annotation(com.xx.annotation.RepeatSubmit)")
        public void logPointCut() { 
        }
        
        
        @Around("logPointCut()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
            Cache cache = caffeineCacheManager.getCache(CaffeineCaches.userRequestUrls.name());
            
            HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
            String ip = IPUtils.getIpAddr(request);
            String url = request.getServletPath();
    
            String key = ip.replaceAll("\.", "") + "-" + url;
            SysUser u = (SysUser) SecurityUtils.getSubject().getPrincipal();
            log.info(">>>>>>>>>>>>请求ip: {} 请求url: {} 当前用户:{}", ip, url, u != null ? u.getUid() : "anno");
    
            Object result = null;
            if (u != null && !StringUtils.isEmpty(u.getUid())) {
                key = key + "-" + u.getUid() + "-" + url;
                if (cache.get(key) == null ) {
                    result = point.proceed();
                    cache.put(key, 1);
                } else {
                    throw new RRException(-91002);
                }        
            } else { // 匿名
                result = point.proceed();
            }
            
            return result; 
        }
        
    
    }
    @RepeatSubmit
    @PostMapping("/x/x")
    public R x(@RequestBody x x) {
        
    }
  • 相关阅读:
    vue学习(十四) 条件搜索框动态查询表中数据 数组的新方法
    vue学习(十三) 删除对象数组中的某个元素
    数据库管理
    PHP基础
    PHP基础之常量与变量
    Cobalt Strike简单使用
    phpstudy后门利用复现
    DNS劫持
    远程控制(远控Bin)
    php基础
  • 原文地址:https://www.cnblogs.com/llggww888/p/14395671.html
Copyright © 2011-2022 走看看