|
|
package com.yoho.search.restapi;
|
|
|
|
|
|
import java.util.HashMap;
|
|
|
import java.util.Iterator;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
|
|
|
import javax.servlet.ServletContext;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
|
|
import org.apache.commons.collections.MapUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.stereotype.Controller;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
import org.springframework.web.bind.annotation.ResponseBody;
|
|
|
import org.springframework.web.context.WebApplicationContext;
|
|
|
import org.springframework.web.context.support.WebApplicationContextUtils;
|
|
|
import org.springframework.web.method.HandlerMethod;
|
|
|
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
|
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
|
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.yoho.search.utils.HttpClientUtils;
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* <Description> 接口返回格式检测<br>
|
|
|
*
|
|
|
* @author amos.shan<br>
|
|
|
* @version 1.0<br>
|
|
|
* @taskId <br>
|
|
|
* @CreateDate 2016年11月3日 <br>
|
|
|
*/
|
|
|
@Controller
|
|
|
public class SearchRespCheckTool {
|
|
|
private static final Logger log = LoggerFactory.getLogger(SearchRespCheckTool.class);
|
|
|
/**
|
|
|
* 目标url前缀
|
|
|
*/
|
|
|
private static final String DEST_URL_PREFIX = "http://192.168.102.216:8080/yohosearch/";
|
|
|
|
|
|
/**
|
|
|
* 当前url前缀
|
|
|
*/
|
|
|
private static final String ORI_URL_PREFIX = "http://localhost:8080/yoho-search-service-web/";
|
|
|
|
|
|
/**
|
|
|
* url后缀
|
|
|
*/
|
|
|
private static final String URL_SUFFIX = ".json";
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* Description: 自动检测所有接口的返回值<br>
|
|
|
*
|
|
|
* @author amos.shan<br>
|
|
|
* @taskId <br>
|
|
|
* @param request
|
|
|
* @return <br>
|
|
|
*/
|
|
|
@ResponseBody
|
|
|
@RequestMapping("/checkResponse")
|
|
|
public Object checkResponse(HttpServletRequest request) {
|
|
|
// 定义返回格式不匹配的url,校验完返回
|
|
|
StringBuffer warnUrl = new StringBuffer();
|
|
|
Map<String, Object> retMap = new HashMap<String, Object>();
|
|
|
retMap.put("code", 200);
|
|
|
retMap.put("msg", "success");
|
|
|
WebApplicationContext wc = getWebApplicationContext(request.getSession().getServletContext());
|
|
|
RequestMappingHandlerMapping rmhp = wc.getBean(RequestMappingHandlerMapping.class);
|
|
|
Map<RequestMappingInfo, HandlerMethod> map = rmhp.getHandlerMethods();
|
|
|
for (Iterator<RequestMappingInfo> iterator = map.keySet().iterator(); iterator.hasNext();) {
|
|
|
RequestMappingInfo url = iterator.next();
|
|
|
HandlerMethod method = map.get(url);
|
|
|
String className = method.getMethod().getDeclaringClass().getName();
|
|
|
String rmUrl = url.getPatternsCondition().toString().replaceAll("[\\[\\]]", "");
|
|
|
|
|
|
// 1. 排除一些类的校验
|
|
|
if (!className.contains("SearchNewController")) {
|
|
|
continue;
|
|
|
}
|
|
|
if (rmUrl.contains("count")) {
|
|
|
continue;
|
|
|
}
|
|
|
// 2. 根据接口判断是否需要添加参数
|
|
|
StringBuffer destReqUrl = new StringBuffer(100);
|
|
|
StringBuffer oriReqUrl = new StringBuffer(100);
|
|
|
Map<String, String> params = generateParams(rmUrl);
|
|
|
if (MapUtils.isEmpty(params)) {
|
|
|
destReqUrl.append(DEST_URL_PREFIX).append(rmUrl).append(URL_SUFFIX);
|
|
|
oriReqUrl.append(ORI_URL_PREFIX).append(rmUrl).append(URL_SUFFIX);
|
|
|
} else {
|
|
|
destReqUrl.append(DEST_URL_PREFIX).append(rmUrl).append(URL_SUFFIX).append(buildParams(params));
|
|
|
oriReqUrl.append(ORI_URL_PREFIX).append(rmUrl).append(URL_SUFFIX).append(buildParams(params));
|
|
|
}
|
|
|
|
|
|
// 3. 比较这个接口
|
|
|
if (!compareJson(oriReqUrl.toString(), destReqUrl.toString())) {
|
|
|
warnUrl.append(rmUrl).append(",");
|
|
|
}
|
|
|
|
|
|
// 4. 拼装错误的返回结果,提示
|
|
|
if (warnUrl.length() > 0) {
|
|
|
retMap.put("code", 400);
|
|
|
retMap.put("msg", "请检查以下requestmapping: " + warnUrl.substring(0, warnUrl.length() - 1));
|
|
|
}
|
|
|
}
|
|
|
return retMap;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Description: 根据不同接口的需求相应添加参数<br>
|
|
|
*
|
|
|
* @author amos.shan<br>
|
|
|
* @taskId <br>
|
|
|
* @param rmUrl
|
|
|
* @return <br>
|
|
|
*/
|
|
|
private Map<String, String> generateParams(String rmUrl) {
|
|
|
Map<String, String> params = new HashMap<String, String>();
|
|
|
|
|
|
// 根据不同接口需求添加不同的参数
|
|
|
if (rmUrl.contains("group_brands")) {
|
|
|
// 批量获取brandIds对应的商品数量和商品列表[我收藏的品牌]--需要传brand
|
|
|
params.put("brand", "1");
|
|
|
}
|
|
|
if (rmUrl.contains("shops")) {
|
|
|
// 根据关键字搜索品牌--需要传keyword
|
|
|
params.put("keyword", "nike");
|
|
|
}
|
|
|
if (rmUrl.contains("group_shops")) {
|
|
|
// 按shopId聚合一些商品--需要传 shop字段
|
|
|
params.put("shop", "1");
|
|
|
}
|
|
|
if (rmUrl.contains("suggest")) {
|
|
|
// 搜索建议接口--需要传query
|
|
|
params.put("query", "ad");
|
|
|
}
|
|
|
if (rmUrl.contains("product_pool")) {
|
|
|
// 搜索商品池列表--需要传filter_poolId
|
|
|
params.put("filter_poolId", "1");
|
|
|
}
|
|
|
return params;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* Description: 获取applicationContext<br>
|
|
|
*
|
|
|
* @author amos.shan<br>
|
|
|
* @taskId <br>
|
|
|
* @param sc
|
|
|
* @return <br>
|
|
|
*/
|
|
|
private WebApplicationContext getWebApplicationContext(ServletContext sc) {
|
|
|
return WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* Description: 动态添加url后的参数<br>
|
|
|
*
|
|
|
* @author amos.shan<br>
|
|
|
* @taskId <br>
|
|
|
* @param map
|
|
|
* @return <br>
|
|
|
*/
|
|
|
private String buildParams(Map<String, String> map) {
|
|
|
StringBuffer sb = new StringBuffer(100);
|
|
|
boolean isFirst = true;
|
|
|
if (map != null && !map.isEmpty()) {
|
|
|
for (Map.Entry<String, String> entry : map.entrySet()) {
|
|
|
sb.append(isFirst ? "?" : "&").append(entry.getKey()).append("=").append(entry.getValue());
|
|
|
isFirst = false;
|
|
|
}
|
|
|
}
|
|
|
return sb.toString();
|
|
|
}
|
|
|
/**
|
|
|
*
|
|
|
* Description: 比较修改后接口与线上接口的返回格式<br>
|
|
|
*
|
|
|
* @author amos.shan<br>
|
|
|
* @taskId <br>
|
|
|
* @param ori
|
|
|
* @param dest <br>
|
|
|
*/
|
|
|
@SuppressWarnings("unchecked")
|
|
|
private boolean compareJson(String oriUrl, String destUrl) {
|
|
|
try {
|
|
|
if (StringUtils.isBlank(oriUrl) || StringUtils.isBlank(destUrl)) {
|
|
|
return false;
|
|
|
}
|
|
|
// 1. 获取源和目标接口返回结果
|
|
|
String oriResult = HttpClientUtils.getMethod(oriUrl);
|
|
|
String destResult = HttpClientUtils.getMethod(destUrl);
|
|
|
if (StringUtils.isBlank(oriResult) || StringUtils.isBlank(destResult)) {
|
|
|
return false;
|
|
|
}
|
|
|
// 2. 过滤数据,仅保留源和目标接口返回结果框架
|
|
|
Map<String, Object> oriResObj = JSONObject.toJavaObject(JSONObject.parseObject(oriResult), Map.class);
|
|
|
Map<String, Object> destResObj = JSONObject.toJavaObject(JSONObject.parseObject(destResult), Map.class);
|
|
|
if ("400".equals(oriResObj.get("code")) || "400".equals(destResObj.get("code"))) {
|
|
|
return false;
|
|
|
}
|
|
|
clearValue(oriResObj, 1, "root");
|
|
|
clearValue(destResObj, 1, "root");
|
|
|
|
|
|
// 3. 比较结果
|
|
|
return StringUtils.equals(JSON.toJSONString(oriResObj), JSON.toJSONString(destResObj));
|
|
|
} catch (Exception e) {
|
|
|
log.error(e.getMessage(), e);
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
* Description: 递归遍历json,清空数据,仅保留基本格式,如遇json数组,仅取第一个元素<br>
|
|
|
*
|
|
|
* @author amos.shan<br>
|
|
|
* @taskId <br>
|
|
|
* @param objConst
|
|
|
* @param currentLevel
|
|
|
* @param parentKey <br>
|
|
|
*/
|
|
|
@SuppressWarnings("unchecked")
|
|
|
private void clearValue(Map<String, Object> objConst, int currentLevel, String parentKey) {
|
|
|
if (CollectionUtils.isEmpty(objConst)) {
|
|
|
return;
|
|
|
}
|
|
|
Object tempValue = null;
|
|
|
List<Map<String, Object>> tempList = null;
|
|
|
Map<String, Object> tempMap = null;
|
|
|
for (Map.Entry<String, Object> entry : objConst.entrySet()) {
|
|
|
if (null != entry.getValue()) {
|
|
|
tempValue = entry.getValue();
|
|
|
if (tempValue instanceof JSONArray) {
|
|
|
// 数组或list, 取第一个
|
|
|
tempList = (List<Map<String, Object>>) tempValue;
|
|
|
if (!CollectionUtils.isEmpty(tempList)) {
|
|
|
tempList = tempList.subList(0, 1);
|
|
|
objConst.put(entry.getKey(), tempList);
|
|
|
clearValue(tempList.get(0), currentLevel + 1, entry.getKey());
|
|
|
}
|
|
|
} else if (tempValue instanceof JSONObject) {
|
|
|
// 对象,循环调用,递归
|
|
|
tempMap = (Map<String, Object>) tempValue;
|
|
|
if (!CollectionUtils.isEmpty(objConst)) {
|
|
|
clearValue(tempMap, currentLevel + 1, entry.getKey());
|
|
|
}
|
|
|
} else {
|
|
|
// 基本类型
|
|
|
objConst.put(entry.getKey(), StringUtils.EMPTY);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} |
...
|
...
|
|