
重新认识Java中防止重复提交
双重检测锁(DCL):这是对HashMap的升级版本,通过锁的双重检查机制,提升频繁重复提交业务的执行效率。 LRUMap:采用基于LRU算法的映射方式,这样可以自动清除过期数据,避免内存无限占用。 方式二的升级:在固定大小数组的基础上,进一步提升性能和安全性。
发布日期:2021-05-27 02:53:57
浏览次数:21
分类:精选文章
本文共 4108 字,大约阅读时间需要 13 分钟。
防止重复提交的请求,可以通过在前端部署拦截器和在后端进行验证来实现。以下是后端拦截的实现思路和方法。
拦截思路
在方法执行之前,先判断该业务是否已执行过。如果已执行,则终止当前请求;否则继续处理。需要将请求的业务ID存储在内存中,并通过互斥锁保证多线程环境下的程序执行安全。最简单的方法是使用HashMap存储业务ID,或者通过Guava Cache achiev相同效果,但HashMap的性能更优。升级方法
具体实现方式
方式一:使用HashMap
@RestControllerpublic class DemoController1 { private Mapmap = new HashMap<>(); @RequestMapping("addUser1") public String addUser(String id) { synchronized (this.getClass()) { if (map.containsKey(id)) { System.out.println("请勿重复提交..." + id); return "请求失败"; } map.put(id, 1); } System.out.println("添加用户ID:" + id); return "请求成功"; }}
方式二:使用固定大小数组
@RestControllerpublic class DemoController2 { private static String[] cache = new String[100]; private static Integer counter = 0; @RequestMapping("addUser2") public String addUser(String id) { synchronized (this.getClass()) { if (Arrays.asList(cache).contains(id)) { System.out.println("请勿重复提交..." + id); return "请求失败"; } if (counter >= cache.length) { counter = 0; } cache[counter] = id; counter++; } System.out.println("添加用户ID:" + id); return "请求成功"; }}
方式三:双重检测锁升级方式
@RestControllerpublic class DemoController3 { private Mapmap = new HashMap<>(); @RequestMapping("addUser3") public String addUser(String id) { if (map.containsKey(id)) { System.out.println("请勿重复提交..." + id); return "请求失败"; } synchronized (this.getClass()) { if (map.containsKey(id)) { System.out.println("请勿重复提交..." + id); return "请求失败"; } map.put(id, 1); } System.out.println("添加用户ID:" + id); return "请求成功"; }}
方式四:固定大小数组升级方式
@RestControllerpublic class DemoController4 { private static String[] cache = new String[100]; private static Integer counter = 0; @RequestMapping("addUser4") public String addUser(String id) { if (Arrays.asList(cache).contains(id)) { System.out.println("请勿重复提交..." + id); return "请求失败"; } synchronized (this.getClass()) { if (Arrays.asList(cache).contains(id)) { System.out.println("请勿重复提交..." + id); return "请求失败"; } if (counter >= cache.length) { counter = 0; } cache[counter] = id; counter++; } System.out.println("添加用户ID:" + id); return "请求成功"; }}
方式五:使用LRUMap
@RestControllerpublic class DemoController5 { private LRUMaplruMap = new LRUMap<>(100); @RequestMapping("addUser5") public String addUser(String id) { if (lruMap.containsKey(id)) { System.out.println("请勿重复提交..." + id); return "请求失败"; } synchronized (this.getClass()) { if (lruMap.containsKey(id)) { System.out.println("请勿重复提交..." + id); return "请求失败"; } lruMap.put(id, 1); } System.out.println("添加用户ID:" + id); return "请求成功"; }}
方式六:工具化封装版本
public class IdempotentUtil { private static LRUMaplruMap = new LRUMap<>(100); public static boolean check(String id, Object lockClass) { synchronized (lockClass) { if (lruMap.containsKey(id)) { System.out.println("请勿重复提交..." + id); return false; } lruMap.put(id, 1); } return true; }}@RestControllerpublic class DemoController6 { @RequestMapping("addUser6") public String addUser(String id) { if (!IdempotentUtil.check(id, this.getClass())) { return "请求失败"; } System.out.println("添加用户ID:" + id); return "请求成功"; }}
后续优化
可以进一步通过自定义注解、反射机制或应用程序拦截器等技术实现防重提交。这些方法结合前端拦截和后端验证,可以更灵活地处理重复请求问题。发表评论
最新留言
表示我来过!
[***.240.166.169]2025年05月01日 09时21分37秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
ElasticSearch - 基于 JavaRestClient 操作索引库和文档
2023-01-24
ElasticSearch - 基础概念,以及和 mysql 的对比
2023-01-24
ElasticSearch - 索引库和文档相关命令操作
2023-01-24
elasticsearch 7.7.0 单节点配置x-pack
2023-01-24
ElasticSearch 中 REST API 详解
2023-01-24
Hot100之回溯算法
2023-01-24
Elasticsearch 时区问题
2023-01-24
Elasticsearch 索引字段类型为text,添加keyword类型操作
2023-01-24
Elasticsearch(四) es出现的问题:填坑
2023-01-24
elasticsearch-5.1.1 安装的问题
2023-01-24
Elasticsearch7.3.1启动指定JDK11
2023-01-24
Elasticsearch下载安装
2023-01-24
Elasticsearch入门教程(Elasticsearch7,linux)
2023-01-24
elasticsearch的helpers.bulk和es_client.bulk的用法
2023-01-24
ElasticSearch设置字段的keyword属性
2023-01-24