springboot aop本地缓存防止重复提交
实现原理:
- 自定义防止重复提交标记(@RepeatSubmit)。
- 对需要防止重复提交的Congtroller里的mapping方法加上该注解。
- 新增Aspect切入点,为@RepeatSubmitAspect加入切入点。
- 每次提交表单时,Aspect都会保存当前key到reids(须设置过期时间)。
- 重复提交时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) { }
.cnblogs_code { }
springboot aop本地缓存防止重复提交的更多相关文章
- Springboot 2.x 如何解决重复提交 (本地锁的实践)
有没有遇到过这种情况:网页响应很慢,提交一次表单后发现没反应,然后你就疯狂点击提交按钮(12306就经常被这样怒怼),如果做过防重复提交还好,否则那是什么级别的灾难就不好说了... 本文主要是应用 自 ...
- springboot之本地缓存(guava与caffeine)
1. 场景描述 因项目要使用本地缓存,具体为啥不用redis等,就不讨论,记录下过程,希望能帮到需要的朋友. 2.解决方案 2.1 使用google的guava作为本地缓存 初步的想法是使用googl ...
- AOP实现防止接口重复提交
项目中对于状态变更接口存在重复提交的问题. package com.yxx.survey.foundation.aop; import com.alibaba.fastjson.JSON; impor ...
- JAVA后端生成Token(令牌),用于校验客户端,防止重复提交
转:https://blog.csdn.net/u011821334/article/details/79390980 转:https://blog.csdn.net/joshua1830/artic ...
- Springboot+Redisson自定义注解一次解决重复提交问题(含源码)
前言 项目中经常会出现重复提交的问题,而接口幂等性也一直以来是做任何项目都要关注的疑难点,网上可以查到非常多的方案,我归纳了几点如下: 1).数据库层面,对责任字段设置唯一索引,这是最直接有效 ...
- AOP+Token防止表单重复提交
表单重复提交: 由于用户误操作,多次点击表单提交按钮 由于网速等原因造成页面卡顿,用户重复刷新提交页面 避免表单重复提交的方式: 1.页面上的按钮做防重复点击操作 2.在数据库中可以做唯一约束 3.利 ...
- 使用aop注解实现表单防重复提交功能
原文:https://www.cnblogs.com/manliu/articles/5983888.html 1.这里采用的方法是:使用get请求进入表单页面时,后台会生成一个tokrn_flag分 ...
- springboot——重定向解决刷新浏览器造成表单重复提交的问题(超详细)
原因:造成表单重复提交的原因是当我们刷新浏览器的时候,浏览器会发送上一次提交的请求.由于上一次提交的请求方式为post,刷新浏览器就会重新发送这个post请求,造成表单重复提交. 解决办法: 将请求当 ...
- Spring Boot (一) 校验表单重复提交
一.前言 在某些情况下,由于网速慢,用户操作有误(连续点击两下提交按钮),页面卡顿等原因,可能会出现表单数据重复提交造成数据库保存多条重复数据. 存在如上问题可以交给前端解决,判断多长时间内不能再次点 ...
- SpringBoot--防止重复提交(锁机制---本地锁、分布式锁)
防止重复提交,主要是使用锁的形式来处理,如果是单机部署,可以使用本地缓存锁(Guava)即可,如果是分布式部署,则需要使用分布式锁(可以使用zk分布式锁或者redis分布式锁),本文的分布式锁以red ...
随机推荐
- KingbaseES恢复被删除数据
KingbaseES恢复被删除数据 生产环境操作请先备份整个data目录或cp 当前数据目录/home/kingbase/pg_data到新的data目录,然后在备份的data目录进行恢复被删除数据操 ...
- ES字段类型
1 String ELasticsearch 5.X之后的字段类型不再支持string,由text和keyword取代,不做说明. 2 text和keyword 2.1 简介 ElasticSearc ...
- IDEA手动导入jar包到maven本地库
第一步:下载需要的jar包 第二步:file project structure-liberaries 第三步:点击+号-选择java,再选择刚才下载的jar包,ok 此时我们把jar包加到项目了,但 ...
- vue @click的stop和prevent
@click.stop 阻止事件冒泡 @click.prevent 阻止事件的默认行为 联合饿了吗UI使用的时候,el-table(主表)包含一个或多个子表时(el-tabs),点击右侧的编辑.删除时 ...
- pycharm用不了pip
环境: win10,安装有python2和python3,主要使用python3,所有环境变量配合的也是python3,之前一直用的好好的,pip可以在命令行和pycharm中正常使用. pychar ...
- JavaSE基础 (全网最全知识点)
背景介绍 java运行机理(即使编译型语言,又是解释型语言) 编译型语言(如:c语言) 源代码需要通过预编译形成可执行文件,再由系统执行该文件形成可识别的二进制文件 解释型语言 边执行边转换.源代码先 ...
- css background背景透明
background: transparent; background: rgba(0, 0, 0, 0.8);
- forEach、for in 、 for of三者的区别
1.for 原始的遍历: 其实除了这三种方法以外还有一种最原始的遍历,自Javascript诞生起就一直用的 就是for循环,它用来遍历数组 var arr = [1,2,3,4] for(var i ...
- 把 URL 中文和一堆百分号转换成字符串
https://www.cnblogs.com/Enziandom/tag/Web%20%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91 JS 有解析这样的 URL 的函数,主 ...
- 05#Web 实战:可拖拽的侧边栏
效果演示图 可拖拽的左.右侧边栏的使用情况还是挺多的,博客园后台管理的左侧边栏就可以拖拽哟!效果演示如下图: HTML 代码 <div class="container"&g ...