diff --git a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java index 2d6d82ea3..94b976d18 100644 --- a/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java +++ b/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java @@ -1,5 +1,6 @@ package org.dromara.common.ratelimiter.aspectj; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; @@ -99,8 +100,14 @@ public class RateLimiterAspect { key = expression.getValue(context, String.class); } StringBuilder stringBuffer = new StringBuilder(GlobalConstants.RATE_LIMIT_KEY); - stringBuffer.append(ServletUtils.getRequest().getRequestURI()).append(":"); - if (rateLimiter.limitType() == LimitType.IP) { + // 非 HTTP 线程(gRPC、消息消费、异步任务等场景)没有请求上下文,getRequest() 返回 null。 + // 此处跳过 URI/IP 段仅以注解 key 限流,否则 NPE 会导致被拦截方法每次调用都失败 + // (业务侧表现为限流注解在非 HTTP 场景完全不可用) + HttpServletRequest request = ServletUtils.getRequest(); + if (request != null) { + stringBuffer.append(request.getRequestURI()).append(":"); + } + if (rateLimiter.limitType() == LimitType.IP && request != null) { // 获取请求ip stringBuffer.append(ServletUtils.getClientIP()).append(":"); } else if (rateLimiter.limitType() == LimitType.CLUSTER) {