| package com.ruoyi.framework.aspectj; | 
|   | 
| import java.lang.reflect.Method; | 
| import java.util.Collections; | 
| import java.util.List; | 
| import org.aspectj.lang.JoinPoint; | 
| import org.aspectj.lang.annotation.Aspect; | 
| import org.aspectj.lang.annotation.Before; | 
| import org.aspectj.lang.reflect.MethodSignature; | 
| import org.slf4j.Logger; | 
| import org.slf4j.LoggerFactory; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.data.redis.core.RedisTemplate; | 
| import org.springframework.data.redis.core.script.RedisScript; | 
| import org.springframework.stereotype.Component; | 
| import com.ruoyi.common.annotation.RateLimiter; | 
| import com.ruoyi.common.enums.LimitType; | 
| import com.ruoyi.common.exception.ServiceException; | 
| import com.ruoyi.common.utils.ServletUtils; | 
| import com.ruoyi.common.utils.StringUtils; | 
| import com.ruoyi.common.utils.ip.IpUtils; | 
|   | 
| /** | 
|  * 限流处理 | 
|  * | 
|  * @author ruoyi | 
|  */ | 
| @Aspect | 
| @Component | 
| public class RateLimiterAspect | 
| { | 
|     private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class); | 
|   | 
|     private RedisTemplate<Object, Object> redisTemplate; | 
|   | 
|     private RedisScript<Long> limitScript; | 
|   | 
|     @Autowired | 
|     public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate) | 
|     { | 
|         this.redisTemplate = redisTemplate; | 
|     } | 
|   | 
|     @Autowired | 
|     public void setLimitScript(RedisScript<Long> limitScript) | 
|     { | 
|         this.limitScript = limitScript; | 
|     } | 
|   | 
|     @Before("@annotation(rateLimiter)") | 
|     public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable | 
|     { | 
|         int time = rateLimiter.time(); | 
|         int count = rateLimiter.count(); | 
|   | 
|         String combineKey = getCombineKey(rateLimiter, point); | 
|         List<Object> keys = Collections.singletonList(combineKey); | 
|         try | 
|         { | 
|             Long number = redisTemplate.execute(limitScript, keys, count, time); | 
|             if (StringUtils.isNull(number) || number.intValue() > count) | 
|             { | 
|                 throw new ServiceException("访问过于频繁,请稍候再试"); | 
|             } | 
|             log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey); | 
|         } | 
|         catch (ServiceException e) | 
|         { | 
|             throw e; | 
|         } | 
|         catch (Exception e) | 
|         { | 
|             throw new RuntimeException("服务器限流异常,请稍候再试"); | 
|         } | 
|     } | 
|   | 
|     public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) | 
|     { | 
|         StringBuffer stringBuffer = new StringBuffer(rateLimiter.key()); | 
|         if (rateLimiter.limitType() == LimitType.IP) | 
|         { | 
|             stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-"); | 
|         } | 
|         MethodSignature signature = (MethodSignature) point.getSignature(); | 
|         Method method = signature.getMethod(); | 
|         Class<?> targetClass = method.getDeclaringClass(); | 
|         stringBuffer.append(targetClass.getName()).append("-").append(method.getName()); | 
|         return stringBuffer.toString(); | 
|     } | 
| } |