# 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,或者结合多种算法实现更严格的防灌水机制。 [2025-05-21 21:04:10 | AI问答 | 1170点数解答]