PersionalRateLimitAspect.java
5.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package com.yoho.search.aop.downgrade;
import java.lang.reflect.Method;
import java.util.Map;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import com.yoho.search.common.filter.YohoHttpServletGetRequestWrapper;
import com.yoho.search.service.base.SearchDynamicConfigService;
@Component
@Aspect
public class PersionalRateLimitAspect {
private static final Logger DOWNGRADE = LoggerFactory.getLogger("DOWNGRADE");
@Autowired
private PersionalRateLimitService persionalRateLimitService;
@Autowired
private SearchDynamicConfigService searchDynamicConfigService;
@Around("@annotation(com.yoho.search.aop.downgrade.PersionalRateLimit)")
public Object persionalRateLimit(ProceedingJoinPoint pjp) throws Throwable {
try {
//限流是否打开
if(!searchDynamicConfigService.isPersionalRateLimitOpen()){
return pjp.proceed();
}
MethodSignature signature = (MethodSignature) pjp.getSignature();
PersionalRateLimit rersionalRateLimit = signature.getMethod().getAnnotation(PersionalRateLimit.class);
String rateLimitName = this.getPersionalRateLimitName(rersionalRateLimit, pjp);
Object[] arges = pjp.getArgs();
for (Object object : arges) {
if (this.doPersionalRateLimit(object, rersionalRateLimit, rateLimitName)) {
break;
}
}
return pjp.proceed();
} catch (Exception e) {
DOWNGRADE.error(e.getMessage());
throw e;
}
}
private boolean doPersionalRateLimit(Object object, PersionalRateLimit rateLimit, String rateLimitName) {
if (object instanceof YohoHttpServletGetRequestWrapper) {
return this.dealWithGetMethod(object, rateLimit, rateLimitName);
}
if (object instanceof Map) {
return this.dealWithPostMethod(object, rateLimit, rateLimitName);
}
return false;
}
/**
* 处理get请求的方式
*
* @param object
* @return
*/
private boolean dealWithGetMethod(Object object, PersionalRateLimit rateLimit, String rateLimitName) {
if (!(object instanceof YohoHttpServletGetRequestWrapper)) {
return false;
}
YohoHttpServletGetRequestWrapper yohoHttpServletRequestWrapper = (YohoHttpServletGetRequestWrapper) object;
String uid = yohoHttpServletRequestWrapper.getParameter("uid");
if (StringUtils.isBlank(uid) || "0".equalsIgnoreCase(uid)) {
return false;
}
if (rateLimit.isOrderUseable() && StringUtils.isNotBlank(yohoHttpServletRequestWrapper.getParameter("order"))) {
return false;
}
PersionalRateLimitConfig limitConfig = searchDynamicConfigService.getPersionalRateLimitConfig(rateLimitName,rateLimit);
if (persionalRateLimitService.isPersionalRateLimit(rateLimitName, limitConfig)) {
yohoHttpServletRequestWrapper.addParams("uid", new String[] { "0" });
return true;
}
return false;
}
@SuppressWarnings("unchecked")
private boolean dealWithPostMethod(Object object, PersionalRateLimit rateLimit, String rateLimitName) {
if (!(object instanceof Map)) {
return false;
}
Map<String, Object> map = (Map<String, Object>) object;
String uid = MapUtils.getString(map, "uid", "");
if (StringUtils.isBlank(uid) || "0".equalsIgnoreCase(uid)) {
return false;
}
if (rateLimit.isOrderUseable() && StringUtils.isNotBlank(MapUtils.getString(map, "order", ""))) {
return false;
}
PersionalRateLimitConfig limitConfig = searchDynamicConfigService.getPersionalRateLimitConfig(rateLimitName,rateLimit);
if (persionalRateLimitService.isPersionalRateLimit(rateLimitName, limitConfig)) {
map.put("uid", 0);
return true;
}
return false;
}
/**
* @controller层则获取url名称
* @service层则获取方法名称
* @param pjp
* @return
*/
private String getPersionalRateLimitName(PersionalRateLimit rersionalRateLimit, ProceedingJoinPoint pjp) {
if (StringUtils.isNotBlank(rersionalRateLimit.name())) {
return rersionalRateLimit.name();
}
// 1、获取method和class
Method targetMethod = ((MethodSignature) (pjp.getSignature())).getMethod();
Class<?> clazz = targetMethod.getDeclaringClass();
// 2、获取class上的requestMapping
String classRequestMappingValue = "";
RequestMapping classRequestMapping = clazz.getDeclaredAnnotation(RequestMapping.class);
if (classRequestMapping != null && classRequestMapping.value() != null && classRequestMapping.value().length > 0) {
classRequestMappingValue = classRequestMapping.value()[0];
}
// 3、获取method上的requestMapping
String methodRequestMappingValue = "";
RequestMapping methodRequestMapping = targetMethod.getDeclaredAnnotation(RequestMapping.class);
if (methodRequestMapping != null && methodRequestMapping.value() != null && methodRequestMapping.value().length > 0) {
methodRequestMappingValue = methodRequestMapping.value()[0];
}
// 4、获取key
if (StringUtils.isNotBlank(classRequestMappingValue) || StringUtils.isNotBlank(methodRequestMappingValue)) {
return classRequestMappingValue + methodRequestMappingValue;
} else {
return clazz.getName() + '.' + targetMethod.getName();
}
}
}