防止重复提交可以通过前端拦截校验和后端拦截校验的方式,在此对后端拦截进行重复提交判断进行尝试。
后端拦截的实现思路是在方法执行之前,先判断此业务是否已经执行过,如果执行过则不再执行,否则就正常执行。我们将请求的业务 ID 存储在内存中,并且通过添加互斥锁来保证多线程下的程序执行安全,将数据存储在内存中,最简单的方法就是使用 HashMap 存储,或者是使用 Guava Cache 也是同样的效果,但很显然 HashMap 可以更快的实现功能,所以我们先来实现一个 HashMap 的防重(防止重复)版本。
升级方法是加上双重检测锁DCL;再升级方法是采用LRUMap实现;
代码示例:
public class IdempotentUtil { //根据LRU算法淘汰最近最少使用的数据的Map集合,最大容量100个 private static LRUMap<String,Integer> lruMap = new LRUMap<>(100); /** * 幂等性判断 */ public static boolean check(String id, Object lockClass) { synchronized (lockClass) { //重复请求判断 if (lruMap.containsKey(id)) { //重复请求 System.out.println("请勿重复提交..." + id); return false; } //非重复请求,存储ID lruMap.put(id,1); } return true; } }
@RequestMapping("addUser6") public String addUser(String id) { //调用幂等性工具判断 if (!IdempotentUtil.check(id,this.getClass())) { return "请求失败"; } //业务代码 System.out.println("添加用户ID:" + id); return "请求成功"; }
需要使用Maven引用包
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.4</version> </dependency>