1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| @Aspect @Component public class LimitingAspect { private static final String LIMITING_KEY = "limiting:%s:%s"; private static final String LIMITING_BEGINTIME = "beginTime"; private static final String LIMITING_EXFREQUENCY = "exFrequency";
@Autowired private RedisTemplate<String, Object> redisTemplate;
@Pointcut("@annotation(limiter)") public void pointcut(Limiter limiter) { }
@Around("pointcut(limiter)") public Object around(ProceedingJoinPoint pjp, Limiter limiter) throws Throwable { String ipAddress = WebUtil.getIpAddress(); String methodName = pjp.getSignature().toLongString();
long cycle = limiter.cycle(); int frequency = limiter.frequency(); long currentTime = System.currentTimeMillis();
Long beginTimeLong = (Long) redisTemplate.opsForHash().get(String.format(LIMITING_KEY, ipAddress, methodName), LIMITING_BEGINTIME); Integer exFrequencyLong = (Integer) redisTemplate.opsForHash().get(String.format(LIMITING_KEY, ipAddress, methodName), LIMITING_EXFREQUENCY);
long beginTime = beginTimeLong == null ? 0L : beginTimeLong; int exFrequency = exFrequencyLong == null ? 0 : exFrequencyLong;
if (currentTime - beginTime > cycle) { redisTemplate.opsForHash().put(String.format(LIMITING_KEY, ipAddress, methodName), LIMITING_BEGINTIME, currentTime); redisTemplate.opsForHash().put(String.format(LIMITING_KEY, ipAddress, methodName), LIMITING_EXFREQUENCY, 1); redisTemplate.expire(String.format(LIMITING_KEY, ipAddress, methodName), limiter.expireTime(), TimeUnit.SECONDS); return pjp.proceed(); } else { if (exFrequency < frequency) { redisTemplate.opsForHash().put(String.format(LIMITING_KEY, ipAddress, methodName), LIMITING_EXFREQUENCY, exFrequency + 1); redisTemplate.expire(String.format(LIMITING_KEY, ipAddress, methodName), limiter.expireTime(), TimeUnit.SECONDS); return pjp.proceed(); } else { throw new FrequentRequestsException(limiter.message()); } } } }
|