日常业务开发中,处理重复请求应该是我们需要经常注意的,那么在Spring Boot中,防止重复请求的方法可以通过以下几种方式实现:
IDEA解析教程
1、Token 验证
通过在页面中生成一个唯一的Token,然后在请求中携带这个Token,服务端接收到请求后验证Token是否正确。如果Token不正确,则认为是重复请求并拒绝处理。
代码示例:
①、首先在页面中生成一个唯一的Token
代码语言:html复制<form id="myForm" action="/submit" method="post">
<input type="hidden" name="token" value="${token}" />
<!-- 其他表单元素 -->
<button type="submit">提交</button>
</form>
②、在服务端中接收请求并验证Token
代码语言:java复制@RestController
public class MyController {
private Map<String, Boolean> tokenMap = new ConcurrentHashMap<>();
@PostMapping("/submit")
public String submit(HttpServletRequest request) {
String token = request.getParameter("token");
if (!tokenMap.containsKey(token)) {
tokenMap.put(token, true);
// 处理请求
return "success";
} else {
// 重复请求
return "error";
}
}
}
2、Token 桶算法
在服务端使用Token桶算法对请求进行限制,每个用户都有一个Token桶,每次请求需要从Token桶中获取一个Token,如果Token桶中没有Token,则认为是重复请求并拒绝处理。
代码示例:
代码语言:java复制@RestController
public class MyController {
private Map<String, LinkedList<Long>> tokenBucketMap = new ConcurrentHashMap<>();
@PostMapping("/submit")
public String submit(HttpServletRequest request) {
String userId = request.getParameter("userId");
LinkedList<Long> tokenBucket = tokenBucketMap.get(userId);
if (tokenBucket == null) {
tokenBucket = new LinkedList<>();
tokenBucketMap.put(userId, tokenBucket);
}
long currentTime = System.currentTimeMillis();
synchronized (tokenBucket) {
if (tokenBucket.size() < 10 || currentTime - tokenBucket.getFirst() > 60000) {
tokenBucket.addLast(currentTime);
if (tokenBucket.size() > 10) {
tokenBucket.removeFirst();
}
// 处理请求
return "success";
} else {
// 重复请求
return "error";
}
}
}
}
3、限流控制
通过在请求接口中设置一个时间间隔,例如5秒钟,同一个用户在5秒钟内只能请求一次,如果再次请求则认为是重复请求并拒绝处理。
代码示例:
代码语言:java复制@RestController
public class MyController {
private Map<String, Long> lastRequestTimeMap = new ConcurrentHashMap<>();
@PostMapping("/submit")
public String submit(HttpServletRequest request) {
String userId = request.getParameter("userId");
Long lastRequestTime = lastRequestTimeMap.get(userId);
if (lastRequestTime == null || System.currentTimeMillis() - lastRequestTime > 5000) {
lastRequestTimeMap.put(userId, System.currentTimeMillis());
// 处理请求
return "success";
} else {
// 重复请求
return "error";
}
}
}
4、接口幂等性设计
代码语言:java复制通过设计接口的幂等性来防止重复请求。在设计接口时,确保同样的请求不管发送多少次都会得到相同的结果,这样即使用户发送了重复请求,服务端也可以正常处理,不会对系统产生影响。
@RestController
public class MyController {
private Map<String, String> resultCache = new ConcurrentHashMap<>();
@PostMapping("/submit")
public String submit(HttpServletRequest request) {
String key = request.getParameter("key");
String result = resultCache.get(key);
if (result != null) {
// 返回之前的结果
return result;
} else {
// 处理请求并缓存结果
result = doBusinessLogic();
resultCache.put(key, result);
return result;
}
}
private String doBusinessLogic() {
// 业务逻辑处理
return "success";
}
}