提交 | 用户 | 时间
|
e57a89
|
1 |
package com.jcdm.framework.aspectj; |
懒 |
2 |
|
|
3 |
import java.lang.reflect.Method; |
|
4 |
import java.util.Collections; |
|
5 |
import java.util.List; |
|
6 |
import org.aspectj.lang.JoinPoint; |
|
7 |
import org.aspectj.lang.annotation.Aspect; |
|
8 |
import org.aspectj.lang.annotation.Before; |
|
9 |
import org.aspectj.lang.reflect.MethodSignature; |
|
10 |
import org.slf4j.Logger; |
|
11 |
import org.slf4j.LoggerFactory; |
|
12 |
import org.springframework.beans.factory.annotation.Autowired; |
|
13 |
import org.springframework.data.redis.core.RedisTemplate; |
|
14 |
import org.springframework.data.redis.core.script.RedisScript; |
|
15 |
import org.springframework.stereotype.Component; |
|
16 |
import com.jcdm.common.annotation.RateLimiter; |
|
17 |
import com.jcdm.common.enums.LimitType; |
|
18 |
import com.jcdm.common.exception.ServiceException; |
|
19 |
import com.jcdm.common.utils.StringUtils; |
|
20 |
import com.jcdm.common.utils.ip.IpUtils; |
|
21 |
|
|
22 |
/** |
|
23 |
* 限流处理 |
|
24 |
* |
|
25 |
* @author jc |
|
26 |
*/ |
|
27 |
//@Aspect |
|
28 |
//@Component |
|
29 |
public class RateLimiterAspect |
|
30 |
{ |
|
31 |
private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class); |
|
32 |
|
|
33 |
private RedisTemplate<Object, Object> redisTemplate; |
|
34 |
|
|
35 |
private RedisScript<Long> limitScript; |
|
36 |
|
|
37 |
// @Autowired |
|
38 |
public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate) |
|
39 |
{ |
|
40 |
this.redisTemplate = redisTemplate; |
|
41 |
} |
|
42 |
|
|
43 |
// @Autowired |
|
44 |
public void setLimitScript(RedisScript<Long> limitScript) |
|
45 |
{ |
|
46 |
this.limitScript = limitScript; |
|
47 |
} |
|
48 |
|
|
49 |
@Before("@annotation(rateLimiter)") |
|
50 |
public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable |
|
51 |
{ |
|
52 |
int time = rateLimiter.time(); |
|
53 |
int count = rateLimiter.count(); |
|
54 |
|
|
55 |
String combineKey = getCombineKey(rateLimiter, point); |
|
56 |
List<Object> keys = Collections.singletonList(combineKey); |
|
57 |
try |
|
58 |
{ |
|
59 |
Long number = redisTemplate.execute(limitScript, keys, count, time); |
|
60 |
if (StringUtils.isNull(number) || number.intValue() > count) |
|
61 |
{ |
|
62 |
throw new ServiceException("访问过于频繁,请稍候再试"); |
|
63 |
} |
|
64 |
log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey); |
|
65 |
} |
|
66 |
catch (ServiceException e) |
|
67 |
{ |
|
68 |
throw e; |
|
69 |
} |
|
70 |
catch (Exception e) |
|
71 |
{ |
|
72 |
throw new RuntimeException("服务器限流异常,请稍候再试"); |
|
73 |
} |
|
74 |
} |
|
75 |
|
|
76 |
public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) |
|
77 |
{ |
|
78 |
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key()); |
|
79 |
if (rateLimiter.limitType() == LimitType.IP) |
|
80 |
{ |
|
81 |
stringBuffer.append(IpUtils.getIpAddr()).append("-"); |
|
82 |
} |
|
83 |
MethodSignature signature = (MethodSignature) point.getSignature(); |
|
84 |
Method method = signature.getMethod(); |
|
85 |
Class<?> targetClass = method.getDeclaringClass(); |
|
86 |
stringBuffer.append(targetClass.getName()).append("-").append(method.getName()); |
|
87 |
return stringBuffer.toString(); |
|
88 |
} |
|
89 |
} |