3 changed files with 99 additions and 3 deletions
-
82common/src/main/java/com/storeroom/aspect/LimitAspect.java
-
6common/src/main/java/com/storeroom/config/SwaggerConfig.java
-
14common/src/main/java/com/storeroom/utils/RequestHolder.java
@ -0,0 +1,82 @@ |
|||||
|
package com.storeroom.aspect; |
||||
|
|
||||
|
import com.google.common.collect.ImmutableList; |
||||
|
import com.storeroom.annotaion.Limit; |
||||
|
import com.storeroom.exception.BaseException; |
||||
|
import com.storeroom.utils.RequestHolder; |
||||
|
import com.storeroom.utils.StringUtils; |
||||
|
import org.aspectj.lang.ProceedingJoinPoint; |
||||
|
import org.aspectj.lang.annotation.Around; |
||||
|
import org.aspectj.lang.annotation.Aspect; |
||||
|
import org.aspectj.lang.annotation.Pointcut; |
||||
|
import org.aspectj.lang.reflect.MethodSignature; |
||||
|
import org.slf4j.Logger; |
||||
|
import org.slf4j.LoggerFactory; |
||||
|
import org.springframework.data.redis.core.RedisTemplate; |
||||
|
import org.springframework.data.redis.core.script.DefaultRedisScript; |
||||
|
import org.springframework.data.redis.core.script.RedisScript; |
||||
|
import org.springframework.stereotype.Component; |
||||
|
|
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import java.lang.reflect.Method; |
||||
|
|
||||
|
@Aspect |
||||
|
@Component |
||||
|
public class LimitAspect { |
||||
|
|
||||
|
private final RedisTemplate<Object,Object> redisTemplate; |
||||
|
private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class); |
||||
|
|
||||
|
public LimitAspect(RedisTemplate<Object,Object> redisTemplate) { |
||||
|
this.redisTemplate = redisTemplate; |
||||
|
} |
||||
|
|
||||
|
@Pointcut("@annotation(com.storeroom.annotaion.Limit)") |
||||
|
public void pointcut() { |
||||
|
} |
||||
|
|
||||
|
@Around("pointcut()") |
||||
|
public Object around(ProceedingJoinPoint joinPoint) throws Throwable { |
||||
|
HttpServletRequest request = RequestHolder.getHttpServletRequest(); |
||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); |
||||
|
Method signatureMethod = signature.getMethod(); |
||||
|
Limit limit = signatureMethod.getAnnotation(Limit.class); |
||||
|
LimitType limitType = limit.limitType(); |
||||
|
String key = limit.key(); |
||||
|
if (StringUtils.isEmpty(key)) { |
||||
|
if (limitType == LimitType.IP) { |
||||
|
key = StringUtils.getIp(request); |
||||
|
} else { |
||||
|
key = signatureMethod.getName(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
ImmutableList<Object> keys = ImmutableList.of(StringUtils.join(limit.prefix(), "_", key, "_", request.getRequestURI().replaceAll("/","_"))); |
||||
|
|
||||
|
String luaScript = buildLuaScript(); |
||||
|
RedisScript<Number> redisScript = new DefaultRedisScript<>(luaScript, Number.class); |
||||
|
Number count = redisTemplate.execute(redisScript, keys, limit.count(), limit.period()); |
||||
|
if (null != count && count.intValue() <= limit.count()) { |
||||
|
logger.info("第{}次访问key为 {},描述为 [{}] 的接口", count, keys, limit.name()); |
||||
|
return joinPoint.proceed(); |
||||
|
} else { |
||||
|
throw new BaseException("访问次数受限制"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 限流脚本 |
||||
|
*/ |
||||
|
private String buildLuaScript() { |
||||
|
return "local c" + |
||||
|
"\nc = redis.call('get',KEYS[1])" + |
||||
|
"\nif c and tonumber(c) > tonumber(ARGV[1]) then" + |
||||
|
"\nreturn c;" + |
||||
|
"\nend" + |
||||
|
"\nc = redis.call('incr',KEYS[1])" + |
||||
|
"\nif tonumber(c) == 1 then" + |
||||
|
"\nredis.call('expire',KEYS[1],ARGV[2])" + |
||||
|
"\nend" + |
||||
|
"\nreturn c;"; |
||||
|
} |
||||
|
} |
@ -0,0 +1,14 @@ |
|||||
|
package com.storeroom.utils; |
||||
|
|
||||
|
import org.springframework.web.context.request.RequestContextHolder; |
||||
|
import org.springframework.web.context.request.ServletRequestAttributes; |
||||
|
|
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import java.util.Objects; |
||||
|
|
||||
|
public class RequestHolder { |
||||
|
|
||||
|
public static HttpServletRequest getHttpServletRequest() { |
||||
|
return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue