96SEO 2026-08-10 21:08 5
作为一名摸爬滚打八年的 Java 开发。我敢说:线上 % 的 “数据错乱” 故障,都和接口重复提交有关。上周大促,使用者疯狂点击下单按钮,导致同一订单被创建了 次;去年支付接口被爬虫高频调用。直接产生了双倍扣款 —— 这些血淋淋的案例告诉我们:接口防抖不是 “可选功能”,而是 “必做防护”。
很多人觉得 “防重复提交不就是前端按钮禁用吗?”—— 太天真了,爬虫、Postman 直接调用、网络延迟重发,这些场景前端防护形同虚设。今天就从实战出发,分享种 SpringBoot 接口防抖的高级方案,覆盖单机、分布式、高并发等所有场景。每一种都附可直接复制的代码和八年踩坑让你解决掉 “手抖党” 和 “恶意刷接口” 的烦恼。

在讲方案前。先澄清两个高频混淆的概念:
这篇文章的方案是 “防抖 + 防重” 结合 —— 既阻止高频重复调用。又保证即使调用多次也不会出问题,真正做到 “双重防护”。
利用 Redis 的原子性 + Lua 脚本。给接口加 “限时锁”:同一请求标识在指定时间内只能执行一次超过时间自动释放锁。
Redis 单条命令是原子的,但多条命令组合会有并发问题。Lua 脚本能把多步操作打包成原子执行,避免 “竞态条件”—— 这是分布式防重的关键。
import java.lang.annotation.*;import java.util.concurrent.TimeUnit;@Target
@Retention
@Documented
public @interface AntiDuplicateSubmit {
long timeout default 1;// 防抖时间
TimeUnit unit default TimeUnit.SECONDS;老实说,// 时间单位
String message default "操作过于频繁。请稍后再试,";}
-- 接收参数:key=请求标识;timeout=过期时间
local key = KEYS
local timeout = ARGV
if redis.call == 1 n
return 1 -- 重复提交
else
redis.call
return 0 -- 正常提交
end
import jakarta.annotation.Resource;老实说,import jakarta.servlet.http.HttpServletRequest;import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;按理说,import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.core.io.ClassPathResource;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.core.script.DefaultRedisScript;不过,import org.springframework.stereotype.Component;import org.springframework.util.DigestUtils;怎么说呢,import java.lang.reflect.Method;怎么说呢,import java.nio.charset.StandardCharsets;import java.util.Collections;@Aspect
@Component
@Slf4j
public class AntiDuplicateSubmitAspect {
@Resource
private StringRedisTemplate stringRedisTemplate;不过,private final DefaultRedisScript antiDuplicateScript;说起来,public AntiDuplicateSubmitAspect {
antiDuplicateScript = new DefaultRedisScript<>;antiDuplicateScript.setLocation);antiDuplicateScript.setResultType;}
@Around")
public Object around throws Throwable {
MethodSignature signature = joinPoint.getSignature;其实,Method method = signature.getMethod;AntiDuplicateSubmit annotation = method.getAnnotation;String requestKey = generateRequestKey;
long timeout = annotation.unit.toSeconds);Long result = stringRedisTemplate.execute(
antiDuplicateScript。Collections.singletonList,String.valueOf
);if {
log.warn;throw new RuntimeException);}
try {
return joinPoint.proceed;} finally {
// 可选:非幂等接口执行完手动释放锁
// stringRedisTemplate.delete;}
}
private String generateRequestKey {
String userId = "anonymous";// 替换为真实使用者标识
String methodName = method.getDeclaringClass.getName + "." + method.getName;String paramDigest = DigestUtils.md5DigestAsHex(
= null?joinPoint.getArgs.toString : "")
.getBytes);return "anti_duplicate:" + userId + ":" + methodName + ":" + paramDigest;}
}
@RestController
public class OrderController {
@AntiDuplicateSubmit
@PostMapping
public String createOrder {
// 下单逻辑省略
return "下单成功,订单号:" + System.currentTimeMillis;}
}
- 分布式程序,高并发场景,如电商大促、支付、预订等主要业务;- 支持幂等与非幂等两类业务;- 与 Token 或 Caffeine 混合使用提供更安全或更高效组合。
前端请求业务接口前先向服务端申请“唯一令牌”,服务端生成令牌存入 Redis;前端携带该令牌调用业务 API 时服务器验证其存在后执行,并立即删除。以确保每个令牌只能使用一次从而彻底消除“恶意刷 API”的风险。话说回来,
LUA 与 Redis 保证令牌存取原子性。而浏览器无法伪造未获取到令牌的数据包,即使攻击者抓包,也无法在没有有效令牌时 发送相同请求。
@RestController
class TokenController {
@Resource
private lateinit var stringRedisTemplate: StringRedisTemplate
@GetMapping
fun getAntiDuplicateToken: String {
val token ="anti_duplicate_token:" + UUID.randomUUID
.toString.replace
stringRedisTemplate.opsForValue
.set)
return token
}
}
private void validateToken{
if){
throw new RuntimeException;}
Boolean deleted=stringRedisTemplate.delete;if{
throw new RuntimeException;}
}
// 在around方法中加入: String token=request.getHeader;老实说,validateToken;// 若失败则抛异常终止处理。
fetch
.n)
.n(token=>{
fetch('/api/order/create'。{method:'POST',headers:{'Content-Type':'application/json','Anti-Duplicate-Token':token},body:JSON.stringify});}),
`
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback