SpringBoot如何处理重复请求?

2023-04-27 17:05:36 浏览数 (1)

日常业务开发中,处理重复请求应该是我们需要经常注意的,那么在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";
    }
}

0 人点赞