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