Authored by hugufei

自定降级代码提交

package com.yoho.search.common.downgrade.persional;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoDownGradePersional {
public int timeInSecond();
public int maxCount();
}
... ...
package com.yoho.search.common.downgrade.persional;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
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.cache.impls.SearchRedis;
import com.yoho.search.common.filter.YohoHttpServletRequestWrapper;
@Component
@Aspect
public class AutoDownGradePersionalAspect {
private static final Logger logger = LoggerFactory.getLogger(AutoDownGradePersionalAspect.class);
@Autowired
private SearchRedis searchRedis;
@Around("@annotation(com.yoho.search.common.downgrade.persional.AutoDownGradePersional)")
public Object downGrade(ProceedingJoinPoint pjp) throws Throwable {
String autoDownGradeKey = this.getAutoDownGradeKey(pjp);
boolean isPersional = false;
try {
MethodSignature signature = (MethodSignature) pjp.getSignature();
AutoDownGradePersional autoDownGrade = signature.getMethod().getAnnotation(AutoDownGradePersional.class);
Object[] arges = pjp.getArgs();
for (Object object : arges) {
if (this.dealPersional(object, autoDownGrade, autoDownGradeKey)) {
isPersional = true;
break;
}
}
return pjp.proceed();
} catch (Exception e) {
logger.error(e.getMessage());
throw e;
} finally {
if (isPersional) {
this.decrease(autoDownGradeKey);
}
}
}
private boolean dealPersional(Object object, AutoDownGradePersional autoDownGrade, String autoDownGradeKey) {
if (!(object instanceof YohoHttpServletRequestWrapper)) {
return false;
}
YohoHttpServletRequestWrapper yohoHttpServletRequestWrapper = (YohoHttpServletRequestWrapper) object;
String uid = yohoHttpServletRequestWrapper.getParameter("uid");
if (StringUtils.isBlank(uid) || "0".equalsIgnoreCase(uid)) {
return false;
}
if (StringUtils.isNotBlank(yohoHttpServletRequestWrapper.getParameter("order"))) {
return false;
}
if (autoDownGrade == null) {
return false;
}
int count = this.increase(autoDownGradeKey, autoDownGrade.timeInSecond());
if (count >= autoDownGrade.maxCount()) {
logger.error("AutoDownGradePersionalAspect,autoDownGradeKey is [{}]", autoDownGradeKey);
yohoHttpServletRequestWrapper.addParams("uid", new String[] { "0" });
}
return true;
}
private String getAutoDownGradeKey(ProceedingJoinPoint pjp) {
Method targetMethod = ((MethodSignature) (pjp.getSignature())).getMethod();
Class<?> clazz = targetMethod.getDeclaringClass();
String classRequestMappingValue = "";
RequestMapping classRequestMapping = clazz.getDeclaredAnnotation(RequestMapping.class);
if (classRequestMapping != null && classRequestMapping.value() != null && classRequestMapping.value().length > 0) {
classRequestMappingValue = classRequestMapping.value()[0];
}
String methodRequestMappingValue = "";
RequestMapping methodRequestMapping = targetMethod.getDeclaredAnnotation(RequestMapping.class);
if (methodRequestMapping != null && methodRequestMapping.value() != null && methodRequestMapping.value().length > 0) {
methodRequestMappingValue = methodRequestMapping.value()[0];
}
if (StringUtils.isNotBlank(classRequestMappingValue) || StringUtils.isNotBlank(methodRequestMappingValue)) {
return classRequestMappingValue + methodRequestMappingValue;
} else {
return clazz.getName() + '_' + targetMethod.getName();
}
}
private int increase(String autoDownGradeKey, long expireInSeconds) {
if (!searchRedis.searchRedisTemplate.hasKey(autoDownGradeKey)) {
// 回调 计数器使用者, 初始化计数器
String initialValue = String.valueOf(0);
// 如果已经被初始化过, 则不用再初始化, 因为其他线程可能已经进行了 increase, 所以必须使用 setIfAbsent
searchRedis.searchValueOperations.setIfAbsent(autoDownGradeKey, initialValue);
// 设置有效期, redis所有的key, 必须设置有效期
searchRedis.searchRedisTemplate.longExpire(autoDownGradeKey, expireInSeconds, TimeUnit.SECONDS);
}
// 原子性对值修改delta数值
return searchRedis.searchValueOperations.increment(autoDownGradeKey, 1).intValue();
}
private int decrease(String autoDownGradeKey) {
return searchRedis.searchValueOperations.increment(autoDownGradeKey, -1).intValue();
}
}
... ...
package com.yoho.search.common.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class YohoHttpServletRequestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
YohoHttpServletRequestWrapper yohoHttpServletRequestWrapper = new YohoHttpServletRequestWrapper(httpServletRequest);
chain.doFilter(yohoHttpServletRequestWrapper, response);
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
}
... ...
package com.yoho.search.common.filter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class YohoHttpServletRequestWrapper extends HttpServletRequestWrapper {
private Map<String, String[]> params;
public YohoHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.params = new HashMap<String, String[]>();
this.params.putAll(request.getParameterMap());
}
public YohoHttpServletRequestWrapper addParams(String key, String[] values) {
this.params.put(key, values);
return this;
}
@Override
public String getParameter(String name) {
String result = "";
Object v = params.get(name);
if (v == null) {
result = null;
} else if (v instanceof String[]) {
String[] strArr = (String[]) v;
if (strArr.length > 0) {
result = strArr[0];
} else {
result = null;
}
} else if (v instanceof String) {
result = (String) v;
} else {
result = v.toString();
}
return result;
}
@Override
public Map<String, String[]> getParameterMap() {
return params;
}
@Override
public Enumeration<String> getParameterNames() {
return new Vector<String>(params.keySet()).elements();
}
@Override
public String[] getParameterValues(String name) {
String[] result = null;
Object v = params.get(name);
if (v == null) {
result = null;
} else if (v instanceof String[]) {
result = (String[]) v;
} else if (v instanceof String) {
result = new String[] { (String) v };
} else {
result = new String[] { v.toString() };
}
return result;
}
}
... ...
... ... @@ -19,27 +19,28 @@ import com.yoho.search.common.utils.HttpServletRequestUtils;
/**
* 耗时拦截器
*
* @author gufei.hu
*
*/
public class ControllerCostInterceptor implements HandlerInterceptor {
private static final Logger CONTROLLER_COST = LoggerFactory.getLogger("CONTROLLER_COST");
private static final Logger CONTROLLER_PERFORMANCE = LoggerFactory.getLogger("CONTROLLER_PERFORMANCE");
private static final ThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("ThreadLocal StartTime");
@Autowired
private DownGradeService downGradeService;
private PerformanceMonitor monitor;
@PostConstruct
void init(){
monitor = new PerformanceMonitor("CONTROLLER_PERFORMANCE",CONTROLLER_PERFORMANCE, 10);
void init() {
monitor = new PerformanceMonitor("CONTROLLER_PERFORMANCE", CONTROLLER_PERFORMANCE, 10);
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle) throws Exception {
long beginTime = System.currentTimeMillis();// 1、开始时间
... ... @@ -51,7 +52,7 @@ public class ControllerCostInterceptor implements HandlerInterceptor {
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) throws Exception {
}
@Override
... ...
package com.yoho.search.restapi;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.service.IProductListService;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
... ... @@ -12,10 +12,11 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import com.yoho.search.common.downgrade.persional.AutoDownGradePersional;
import com.yoho.search.common.utils.HttpServletRequestUtils;
import com.yoho.search.models.SearchApiResult;
import com.yoho.search.service.service.IProductListService;
@Controller
public class ProductListController {
... ... @@ -28,6 +29,7 @@ public class ProductListController {
*
* @return
*/
@AutoDownGradePersional(timeInSecond = 10, maxCount = 0)
@RequestMapping(method = RequestMethod.GET, value = "/productindex/productList")
@ResponseBody
public SearchApiResult productList(HttpServletRequest request) {
... ... @@ -46,7 +48,7 @@ public class ProductListController {
Map<String, String> paramMap = HttpServletRequestUtils.transParamType(request);
return productListService.productListWithPhrase(paramMap);
}
/**
* 获取商品列表
*
... ...
package com.yoho.search.service.service;
import com.yoho.search.models.SearchApiResult;
import java.util.Map;
import com.yoho.search.models.SearchApiResult;
public interface IProductListService {
/**
... ...
... ... @@ -80,7 +80,7 @@ public class ProductListServiceImpl implements IProductListService {
void init() {
productListSearchCache = searchCacheFactory.getProductListSearchCache();
}
@Override
public SearchApiResult productList(Map<String, String> paramMap) {
try {
... ...
... ... @@ -52,6 +52,21 @@
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- yohoHttpRequest过滤器 -->
<filter>
<filter-name>yohoHttpRequestFilter</filter-name>
<filter-class>com.yoho.search.common.filter.YohoHttpServletRequestFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>yohoHttpRequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 防止Spring内存溢出监听器 -->
<listener>
... ...