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) {
    
}

 

posted @ 2021-02-10 14:12  llggww  阅读(343)  评论(0编辑  收藏  举报