mirror of
				https://github.com/dromara/RuoYi-Vue-Plus.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	!486 RateLimiter优化
Merge pull request !486 from ly-chn/rate-limiter-feat
This commit is contained in:
		@@ -1,29 +1,29 @@
 | 
			
		||||
package org.dromara.common.ratelimiter.aspectj;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.util.ArrayUtil;
 | 
			
		||||
import org.dromara.common.core.constant.GlobalConstants;
 | 
			
		||||
import org.dromara.common.core.exception.ServiceException;
 | 
			
		||||
import org.dromara.common.core.utils.MessageUtils;
 | 
			
		||||
import org.dromara.common.core.utils.ServletUtils;
 | 
			
		||||
import org.dromara.common.core.utils.StringUtils;
 | 
			
		||||
import org.dromara.common.ratelimiter.annotation.RateLimiter;
 | 
			
		||||
import org.dromara.common.ratelimiter.enums.LimitType;
 | 
			
		||||
import org.dromara.common.redis.utils.RedisUtils;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
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.dromara.common.core.constant.GlobalConstants;
 | 
			
		||||
import org.dromara.common.core.exception.ServiceException;
 | 
			
		||||
import org.dromara.common.core.utils.MessageUtils;
 | 
			
		||||
import org.dromara.common.core.utils.ServletUtils;
 | 
			
		||||
import org.dromara.common.core.utils.SpringUtils;
 | 
			
		||||
import org.dromara.common.core.utils.StringUtils;
 | 
			
		||||
import org.dromara.common.ratelimiter.annotation.RateLimiter;
 | 
			
		||||
import org.dromara.common.ratelimiter.enums.LimitType;
 | 
			
		||||
import org.dromara.common.redis.utils.RedisUtils;
 | 
			
		||||
import org.redisson.api.RateType;
 | 
			
		||||
import org.springframework.context.expression.BeanFactoryResolver;
 | 
			
		||||
import org.springframework.context.expression.MethodBasedEvaluationContext;
 | 
			
		||||
import org.springframework.core.DefaultParameterNameDiscoverer;
 | 
			
		||||
import org.springframework.core.ParameterNameDiscoverer;
 | 
			
		||||
import org.springframework.expression.EvaluationContext;
 | 
			
		||||
import org.springframework.expression.Expression;
 | 
			
		||||
import org.springframework.expression.ExpressionParser;
 | 
			
		||||
import org.springframework.expression.ParserContext;
 | 
			
		||||
import org.springframework.expression.common.TemplateParserContext;
 | 
			
		||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
 | 
			
		||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
 | 
			
		||||
@@ -44,21 +44,18 @@ public class RateLimiterAspect {
 | 
			
		||||
     * 定义spel解析模版
 | 
			
		||||
     */
 | 
			
		||||
    private final ParserContext parserContext = new TemplateParserContext();
 | 
			
		||||
    /**
 | 
			
		||||
     * 定义spel上下文对象进行解析
 | 
			
		||||
     */
 | 
			
		||||
    private final EvaluationContext context = new StandardEvaluationContext();
 | 
			
		||||
    /**
 | 
			
		||||
     * 方法参数解析器
 | 
			
		||||
     */
 | 
			
		||||
    private final ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Before("@annotation(rateLimiter)")
 | 
			
		||||
    public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable {
 | 
			
		||||
    public void doBefore(JoinPoint point, RateLimiter rateLimiter) {
 | 
			
		||||
        int time = rateLimiter.time();
 | 
			
		||||
        int count = rateLimiter.count();
 | 
			
		||||
        String combineKey = getCombineKey(rateLimiter, point);
 | 
			
		||||
        try {
 | 
			
		||||
            String combineKey = getCombineKey(rateLimiter, point);
 | 
			
		||||
            RateType rateType = RateType.OVERALL;
 | 
			
		||||
            if (rateLimiter.limitType() == LimitType.CLUSTER) {
 | 
			
		||||
                rateType = RateType.PER_CLIENT;
 | 
			
		||||
@@ -76,42 +73,29 @@ public class RateLimiterAspect {
 | 
			
		||||
            if (e instanceof ServiceException) {
 | 
			
		||||
                throw e;
 | 
			
		||||
            } else {
 | 
			
		||||
                throw new RuntimeException("服务器限流异常,请稍候再试");
 | 
			
		||||
                throw new RuntimeException("服务器限流异常,请稍候再试", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
 | 
			
		||||
    private String getCombineKey(RateLimiter rateLimiter, JoinPoint point) {
 | 
			
		||||
        String key = rateLimiter.key();
 | 
			
		||||
        // 获取方法(通过方法签名来获取)
 | 
			
		||||
        MethodSignature signature = (MethodSignature) point.getSignature();
 | 
			
		||||
        Method method = signature.getMethod();
 | 
			
		||||
        Class<?> targetClass = method.getDeclaringClass();
 | 
			
		||||
        // 判断是否是spel格式
 | 
			
		||||
        if (StringUtils.containsAny(key, "#")) {
 | 
			
		||||
            // 获取参数值
 | 
			
		||||
        if (StringUtils.isNotBlank(key)) {
 | 
			
		||||
            MethodSignature signature = (MethodSignature) point.getSignature();
 | 
			
		||||
            Method targetMethod = signature.getMethod();
 | 
			
		||||
            Object[] args = point.getArgs();
 | 
			
		||||
            // 获取方法上参数的名称
 | 
			
		||||
            String[] parameterNames = pnd.getParameterNames(method);
 | 
			
		||||
            if (ArrayUtil.isEmpty(parameterNames)) {
 | 
			
		||||
                throw new ServiceException("限流key解析异常!请联系管理员!");
 | 
			
		||||
            }
 | 
			
		||||
            for (int i = 0; i < parameterNames.length; i++) {
 | 
			
		||||
                context.setVariable(parameterNames[i], args[i]);
 | 
			
		||||
            }
 | 
			
		||||
            // 解析返回给key
 | 
			
		||||
            try {
 | 
			
		||||
                Expression expression;
 | 
			
		||||
                if (StringUtils.startsWith(key, parserContext.getExpressionPrefix())
 | 
			
		||||
                    && StringUtils.endsWith(key, parserContext.getExpressionSuffix())) {
 | 
			
		||||
                    expression = parser.parseExpression(key, parserContext);
 | 
			
		||||
                } else {
 | 
			
		||||
                    expression = parser.parseExpression(key);
 | 
			
		||||
                }
 | 
			
		||||
                key = expression.getValue(context, String.class) + ":";
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                throw new ServiceException("限流key解析异常!请联系管理员!");
 | 
			
		||||
            //noinspection DataFlowIssue
 | 
			
		||||
            MethodBasedEvaluationContext context =
 | 
			
		||||
                new MethodBasedEvaluationContext(null, targetMethod, args, pnd);
 | 
			
		||||
            context.setBeanResolver(new BeanFactoryResolver(SpringUtils.getBeanFactory()));
 | 
			
		||||
            Expression expression;
 | 
			
		||||
            if (StringUtils.startsWith(key, parserContext.getExpressionPrefix())
 | 
			
		||||
                && StringUtils.endsWith(key, parserContext.getExpressionSuffix())) {
 | 
			
		||||
                expression = parser.parseExpression(key, parserContext);
 | 
			
		||||
            } else {
 | 
			
		||||
                expression = parser.parseExpression(key);
 | 
			
		||||
            }
 | 
			
		||||
            key = expression.getValue(context, String.class);
 | 
			
		||||
        }
 | 
			
		||||
        StringBuilder stringBuffer = new StringBuilder(GlobalConstants.RATE_LIMIT_KEY);
 | 
			
		||||
        stringBuffer.append(ServletUtils.getRequest().getRequestURI()).append(":");
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
  "org.dromara.common.ratelimiter.annotation.RateLimiter@key": {
 | 
			
		||||
    "method": {
 | 
			
		||||
      "parameters": true
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user