Java实现多种防灌水机制:时间、令牌桶、Redis、IP限制全攻略
# Java防灌水机制实现 防灌水机制通常用于防止用户短时间内重复提交或恶意刷屏。以下是几种常见的防灌水实现方式: ## 1. 基于时间间隔的限制 ```java import java.util.HashMap; import java.util.Map; public class FloodControl { private static final Map<String, Long> lastPostTimes = new HashMap<>(); private static final long MIN_INTERVAL = 5000; // 5秒间隔 public static boolean canPost(String userId) { long currentTime = System.currentTimeMillis(); Long lastTime = lastPostTimes.get(userId); if (lastTime == null || (currentTime - lastTime) >= MIN_INTERVAL) { lastPostTimes.put(userId, currentTime); return true; } return false; } } ``` ## 2. 基于令牌桶算法的限流 ```java import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; public class RateLimiter { private final ConcurrentMap<String, TokenBucket> buckets = new ConcurrentHashMap<>(); private final int capacity; // 桶容量 private final long refillInterval; // 补充间隔(毫秒) public RateLimiter(int capacity, long refillInterval) { this.capacity = capacity; this.refillInterval = refillInterval; } public boolean allowRequest(String key) { TokenBucket bucket = buckets.computeIfAbsent(key, k -> new TokenBucket()); return bucket.tryConsume(); } private class TokenBucket { private final AtomicInteger tokens; private volatile long lastRefillTime; TokenBucket() { this.tokens = new AtomicInteger(capacity); this.lastRefillTime = System.currentTimeMillis(); } boolean tryConsume() { refill(); if (tokens.get() > 0) { return tokens.decrementAndGet() >= 0; } return false; } void refill() { long now = System.currentTimeMillis(); if (now - lastRefillTime > refillInterval) { tokens.set(capacity); lastRefillTime = now; } } } } ``` ## 3. 基于Redis的分布式防灌水 ```java import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; public class RedisFloodControl { private final JedisPool jedisPool; private final int limit; // 限制次数 private final long interval; // 时间窗口(秒) public RedisFloodControl(JedisPool jedisPool, int limit, long interval) { this.jedisPool = jedisPool; this.limit = limit; this.interval = interval; } public boolean isAllowed(String key) { try (Jedis jedis = jedisPool.getResource()) { long current = System.currentTimeMillis(); long windowStart = current - interval * 1000; // 使用Redis的ZSET实现滑动窗口 jedis.zremrangeByScore(key, 0, windowStart); long count = jedis.zcard(key); if (count < limit) { jedis.zadd(key, current, current + "-" + Math.random()); jedis.expire(key, interval + 1); return true; } return false; } } } ``` ## 4. 基于IP的限制 ```java import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class IPFloodControl { private final ConcurrentMap<String, RequestRecord> ipRecords = new ConcurrentHashMap<>(); private final int maxRequests; private final long timeWindow; public IPFloodControl(int maxRequests, long timeWindowMillis) { this.maxRequests = maxRequests; this.timeWindow = timeWindowMillis; } public boolean allowRequest(String ip) { long now = System.currentTimeMillis(); RequestRecord record = ipRecords.computeIfAbsent(ip, k -> new RequestRecord()); synchronized (record) { if (now - record.firstRequestTime > timeWindow) { record.reset(now); } if (record.requestCount < maxRequests) { record.requestCount++; return true; } return false; } } private static class RequestRecord { long firstRequestTime; int requestCount; void reset(long time) { this.firstRequestTime = time; this.requestCount = 0; } } } ``` ## 使用示例 ```java public class Main { public static void main(String[] args) { // 时间间隔限制示例 if (FloodControl.canPost("user123")) { System.out.println("允许提交"); } else { System.out.println("操作太频繁,请稍后再试"); } // 令牌桶示例 RateLimiter limiter = new RateLimiter(10, 60000); // 每分钟10次 if (limiter.allowRequest("user123")) { System.out.println("允许请求"); } else { System.out.println("请求过于频繁"); } } } ``` 以上实现可以根据实际需求进行组合使用,例如同时限制IP和用户ID,或者结合多种算法实现更严格的防灌水机制。 ######[AI问答 | 1170点数解答 | 2025-05-21 21:04:10]
- "Scrapy-Redis-Sentinel 0.7.1 Version Conflict: How to Resolve Redis and Redis-Py-Cluster Mismatch"(阿里通义 | 245点数解答 | 2024-03-01 14:08:38)320
- Java 实现复制粘贴功能:打造简易文本复制粘贴程序(GPT | 1497点数解答 | 2024-08-25 09:40:33)424
- 揭秘软件工程师视角:域名与 IP 一对多关系,一个 IP 能否对应多个域名? (百度文心 | 61点数解答 | 2023-11-09 18:19:12)386
- Python 实现 DES 加密算法编程实验:从原理到单步调试全解析(字节豆包 | 4096点数解答 | 2025-11-09 22:06:30)87
- 解决数据库“dm.jdbc.driver.dmexception: 数据溢出”问题的全步骤指南(阿里通义 | 598点数解答 | 2024-10-15 15:48:38)328
- 达梦数据库数据溢出问题排查及多维度解决方法(阿里通义 | 403点数解答 | 2024-10-15 15:48:41)1207
- Python 实现球类:精准计算半径、表面积与体积,附输入验证与异常处理!(阿里通义 | 261点数解答 | 2024-11-28 21:19:39)366
- 编程里的“神秘令牌”:解析Token的身份与用途 ( | 82点数解答 | 2023-10-04 12:53:33)286
- 易语言读取文本文件并显示到超级列表框:代码示例与注意要点(DeepSeek | 571点数解答 | 2025-08-23 20:54:40)250
- 易语言:读取并显示特定文本到超级列表框,还能增加新数据的方法与要点(DeepSeek | 1317点数解答 | 2025-08-23 20:58:40)251
- 51 单片机:定时器 0 实现 8 个 LED 循环点亮,附代码及优化建议(字节豆包 | 1193点数解答 | 2024-12-27 15:10:29)337
- "Java Code: Uncovering Stock Statistics through CSV File Reading"(字节豆包 | 66点数解答 | 2024-11-13 15:31:04)336