|
@@ -1,37 +1,31 @@
|
|
package cn.com.qmth.examcloud.web.interceptor;
|
|
package cn.com.qmth.examcloud.web.interceptor;
|
|
|
|
|
|
-import java.io.File;
|
|
|
|
-import java.io.IOException;
|
|
|
|
import java.util.Enumeration;
|
|
import java.util.Enumeration;
|
|
-import java.util.List;
|
|
|
|
|
|
+import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
|
|
-import org.apache.commons.collections.CollectionUtils;
|
|
|
|
-import org.apache.commons.io.FileUtils;
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
-import org.slf4j.MDC;
|
|
|
|
-import org.springframework.core.annotation.AnnotationUtils;
|
|
|
|
|
|
+import org.apache.logging.log4j.ThreadContext;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.HttpStatus;
|
|
-import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
import org.springframework.web.method.HandlerMethod;
|
|
import org.springframework.web.method.HandlerMethod;
|
|
import org.springframework.web.servlet.HandlerInterceptor;
|
|
import org.springframework.web.servlet.HandlerInterceptor;
|
|
import org.springframework.web.servlet.ModelAndView;
|
|
import org.springframework.web.servlet.ModelAndView;
|
|
|
|
|
|
import com.google.common.collect.Maps;
|
|
import com.google.common.collect.Maps;
|
|
-import com.google.common.collect.Sets;
|
|
|
|
|
|
|
|
-import cn.com.qmth.examcloud.commons.helpers.FileChangeWatchdog;
|
|
|
|
import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
|
|
import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
|
|
import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
|
|
import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
|
|
-import cn.com.qmth.examcloud.commons.logging.SLF4JImpl;
|
|
|
|
import cn.com.qmth.examcloud.commons.util.JsonUtil;
|
|
import cn.com.qmth.examcloud.commons.util.JsonUtil;
|
|
-import cn.com.qmth.examcloud.commons.util.PathUtil;
|
|
|
|
import cn.com.qmth.examcloud.commons.util.StringUtil;
|
|
import cn.com.qmth.examcloud.commons.util.StringUtil;
|
|
import cn.com.qmth.examcloud.commons.util.ThreadLocalUtil;
|
|
import cn.com.qmth.examcloud.commons.util.ThreadLocalUtil;
|
|
|
|
+import cn.com.qmth.examcloud.web.enums.HttpServletRequestAttribute;
|
|
|
|
+import cn.com.qmth.examcloud.web.support.ApiId;
|
|
|
|
+import cn.com.qmth.examcloud.web.support.ApiInfo;
|
|
|
|
+import cn.com.qmth.examcloud.web.support.ApiInfoHolder;
|
|
import cn.com.qmth.examcloud.web.support.ServletUtil;
|
|
import cn.com.qmth.examcloud.web.support.ServletUtil;
|
|
import cn.com.qmth.examcloud.web.support.StatusResponse;
|
|
import cn.com.qmth.examcloud.web.support.StatusResponse;
|
|
|
|
|
|
@@ -39,171 +33,86 @@ import cn.com.qmth.examcloud.web.support.StatusResponse;
|
|
* 首发拦截器
|
|
* 首发拦截器
|
|
*
|
|
*
|
|
* @author WANGWEI
|
|
* @author WANGWEI
|
|
- * @date 2018年5月22日
|
|
|
|
- * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
|
|
|
|
|
|
+ * @date 2018年10月22日
|
|
|
|
+ * @Copyright (c) 2018-2020 WANGWEI [QQ:522080330] All Rights Reserved.
|
|
*/
|
|
*/
|
|
public class FirstInterceptor implements HandlerInterceptor {
|
|
public class FirstInterceptor implements HandlerInterceptor {
|
|
|
|
|
|
private static final ExamCloudLog LOG = ExamCloudLogFactory.getLog(FirstInterceptor.class);
|
|
private static final ExamCloudLog LOG = ExamCloudLogFactory.getLog(FirstInterceptor.class);
|
|
|
|
|
|
- /**
|
|
|
|
- * 接口日志
|
|
|
|
- */
|
|
|
|
- protected static final ExamCloudLog INTERFACE_LOG = ExamCloudLogFactory
|
|
|
|
|
|
+ private static final ExamCloudLog INTERFACE_LOG = ExamCloudLogFactory
|
|
.getLog("INTERFACE_LOGGER");
|
|
.getLog("INTERFACE_LOGGER");
|
|
|
|
|
|
- private static final Set<String> RESOURCE_NAME_SET = Sets.newConcurrentHashSet();
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 拦截的请求
|
|
|
|
- */
|
|
|
|
- private Set<String> badRequests;
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 热加载配置文件
|
|
|
|
- *
|
|
|
|
- * @author WANGWEI
|
|
|
|
- * @param resourceName
|
|
|
|
- */
|
|
|
|
- public synchronized void configureAndWatch(String resourceName) {
|
|
|
|
- if (RESOURCE_NAME_SET.contains(resourceName)) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- String path = PathUtil.getResoucePath(resourceName);
|
|
|
|
- loadFromFile(path);
|
|
|
|
-
|
|
|
|
- InterceptConfFileChangeWatchdog dog = new InterceptConfFileChangeWatchdog(path);
|
|
|
|
- dog.setDelay(30000);
|
|
|
|
- dog.start();
|
|
|
|
- RESOURCE_NAME_SET.add(resourceName);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 观察线程
|
|
|
|
- *
|
|
|
|
- * @author WANGWEI
|
|
|
|
- */
|
|
|
|
- private class InterceptConfFileChangeWatchdog extends FileChangeWatchdog {
|
|
|
|
-
|
|
|
|
- protected InterceptConfFileChangeWatchdog(String path) {
|
|
|
|
- super(path);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- protected void doOnChange() {
|
|
|
|
- try {
|
|
|
|
- loadFromFile(path);
|
|
|
|
- } catch (Exception e) {
|
|
|
|
- LOG.info("Fail to load from file [" + path + "].", e);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private void loadFromFile(String path) {
|
|
|
|
- try {
|
|
|
|
- Set<String> newBadRequests = Sets.newHashSet();
|
|
|
|
- List<String> lines = FileUtils.readLines(new File(path), "UTF-8");
|
|
|
|
- for (String cur : lines) {
|
|
|
|
- if (StringUtils.isNotBlank(cur)) {
|
|
|
|
- newBadRequests.add(cur.trim());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- badRequests = newBadRequests;
|
|
|
|
- LOG.info("exclusions=" + JsonUtil.toJson(badRequests));
|
|
|
|
- } catch (IOException e) {
|
|
|
|
- LOG.error("fail to load config from file. filePath=" + path, e);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
@Override
|
|
@Override
|
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
|
Object handler) throws Exception {
|
|
Object handler) throws Exception {
|
|
|
|
|
|
- String traceID = request.getHeader("TRACE_ID");
|
|
|
|
- if (StringUtils.isBlank(traceID)) {
|
|
|
|
- traceID = ThreadLocalUtil.next();
|
|
|
|
|
|
+ String traceId = request.getHeader("Trace-Id");
|
|
|
|
+ if (StringUtils.isBlank(traceId)) {
|
|
|
|
+ traceId = ThreadLocalUtil.next();
|
|
} else {
|
|
} else {
|
|
- ThreadLocalUtil.setTraceID(traceID);
|
|
|
|
|
|
+ ThreadLocalUtil.setTraceId(traceId);
|
|
}
|
|
}
|
|
|
|
|
|
- // 设置MDC
|
|
|
|
- if (LOG instanceof SLF4JImpl) {
|
|
|
|
- MDC.put("TRACE_ID", traceID);
|
|
|
|
- MDC.put("KEY", "$$$$$");
|
|
|
|
- }
|
|
|
|
|
|
+ // 设置log4j线程上下文
|
|
|
|
+ ThreadContext.put("TRACE_ID", traceId);
|
|
|
|
+ ThreadContext.put("CALLER", "$$$$$");
|
|
|
|
|
|
String path = request.getServletPath();
|
|
String path = request.getServletPath();
|
|
String method = request.getMethod();
|
|
String method = request.getMethod();
|
|
|
|
|
|
- String reqPath = method + ":" + path;
|
|
|
|
-
|
|
|
|
- LOG.debug("[preHandle]. reqPath = " + reqPath);
|
|
|
|
-
|
|
|
|
- if (CollectionUtils.isNotEmpty(badRequests)) {
|
|
|
|
- if (badRequests.contains(reqPath)) {
|
|
|
|
- response.setStatus(HttpStatus.NOT_ACCEPTABLE.value());
|
|
|
|
- ServletUtil.returnJsonWithoutLog(new StatusResponse("406", "Not Acceptable."),
|
|
|
|
- response);
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ Set<String> headerNames = new HashSet<String>(20);
|
|
if (INTERFACE_LOG.isDebugEnabled()) {
|
|
if (INTERFACE_LOG.isDebugEnabled()) {
|
|
Map<String, String> headers = Maps.newHashMap();
|
|
Map<String, String> headers = Maps.newHashMap();
|
|
Enumeration<String> e = request.getHeaderNames();
|
|
Enumeration<String> e = request.getHeaderNames();
|
|
while (e.hasMoreElements()) {
|
|
while (e.hasMoreElements()) {
|
|
String name = (String) e.nextElement();
|
|
String name = (String) e.nextElement();
|
|
String value = request.getHeader(name);
|
|
String value = request.getHeader(name);
|
|
- if (name.startsWith("cookie")) {
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
headers.put(name, value);
|
|
headers.put(name, value);
|
|
|
|
+ headerNames.add(name);
|
|
}
|
|
}
|
|
INTERFACE_LOG.debug(StringUtil.join("[preHandle]. path=\"", path, "\"; method=[",
|
|
INTERFACE_LOG.debug(StringUtil.join("[preHandle]. path=\"", path, "\"; method=[",
|
|
method, "]", "; headers=", JsonUtil.toJson(headers)));
|
|
method, "]", "; headers=", JsonUtil.toJson(headers)));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (path.equals("/error")) {
|
|
|
|
+ response.setStatus(HttpStatus.NOT_FOUND.value());
|
|
|
|
+ ServletUtil.returnJson(new StatusResponse(String.valueOf(HttpStatus.NOT_FOUND.value()),
|
|
|
|
+ String.valueOf(HttpStatus.NOT_FOUND.getReasonPhrase())), response);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (handler instanceof HandlerMethod) {
|
|
if (handler instanceof HandlerMethod) {
|
|
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
|
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
|
- Object controllerObject = handlerMethod.getBean();
|
|
|
|
- RequestMapping mappingOfClass = AnnotationUtils
|
|
|
|
- .findAnnotation(controllerObject.getClass(), RequestMapping.class);
|
|
|
|
- RequestMapping mappingOfMethod = handlerMethod
|
|
|
|
- .getMethodAnnotation(RequestMapping.class);
|
|
|
|
-
|
|
|
|
- String[] allPathOfClass = null;
|
|
|
|
- String[] allPathOfMethod = null;
|
|
|
|
|
|
+ ApiId apiId = handlerMethod.getMethodAnnotation(ApiId.class);
|
|
|
|
|
|
- if (null != mappingOfClass) {
|
|
|
|
- allPathOfClass = mappingOfClass.path();
|
|
|
|
|
|
+ ApiInfo apiInfo = null;
|
|
|
|
+ if (null != apiId) {
|
|
|
|
+ apiInfo = ApiInfoHolder.getApiInfo(apiId.value());
|
|
|
|
+ } else {
|
|
|
|
+ apiInfo = ApiInfoHolder.getApiInfo(handlerMethod.getMethod());
|
|
}
|
|
}
|
|
- if (null != mappingOfMethod) {
|
|
|
|
- allPathOfMethod = mappingOfMethod.path();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- String pathsOfClass = null;
|
|
|
|
- String pathsOfMethod = null;
|
|
|
|
|
|
+ String mapping = apiInfo.getMapping();
|
|
|
|
+ request.setAttribute(HttpServletRequestAttribute.$_API_INFO.name(), apiInfo);
|
|
|
|
|
|
- if (null != allPathOfClass) {
|
|
|
|
- pathsOfClass = StringUtils.join(allPathOfClass, ",");
|
|
|
|
|
|
+ if (INTERFACE_LOG.isDebugEnabled()) {
|
|
|
|
+ INTERFACE_LOG.debug("[preHandle]. mapping = " + mapping);
|
|
}
|
|
}
|
|
- if (null != allPathOfMethod) {
|
|
|
|
- pathsOfMethod = StringUtils.join(allPathOfMethod, ",");
|
|
|
|
|
|
+ request.setAttribute(HttpServletRequestAttribute.$_MAPPING.name(), mapping);
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+ if (INTERFACE_LOG.isDebugEnabled()) {
|
|
|
|
+ INTERFACE_LOG.debug("not handle by HandlerMethod.");
|
|
}
|
|
}
|
|
|
|
|
|
- String mappingPath = StringUtils.join("[", pathsOfClass, "][", pathsOfMethod, "][",
|
|
|
|
- method, "]");
|
|
|
|
|
|
+ String mapping = StringUtils.join("_[", path, "][", method, "]");
|
|
|
|
|
|
if (INTERFACE_LOG.isDebugEnabled()) {
|
|
if (INTERFACE_LOG.isDebugEnabled()) {
|
|
- INTERFACE_LOG.debug("[preHandle]. mapping = " + mappingPath);
|
|
|
|
|
|
+ INTERFACE_LOG.debug("[preHandle]. mapping = " + mapping);
|
|
}
|
|
}
|
|
|
|
|
|
- request.setAttribute("$mappingPath", mappingPath);
|
|
|
|
- request.setAttribute("$ctrClass", controllerObject.getClass());
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
- INTERFACE_LOG.error("cry.....");
|
|
|
|
- return false;
|
|
|
|
|
|
+ request.setAttribute(HttpServletRequestAttribute.$_MAPPING.name(), mapping);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
return true;
|
|
return true;
|
|
@@ -219,10 +128,8 @@ public class FirstInterceptor implements HandlerInterceptor {
|
|
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
|
|
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
|
|
Object handler, Exception ex) throws Exception {
|
|
Object handler, Exception ex) throws Exception {
|
|
LOG.debug("afterCompletion... ...");
|
|
LOG.debug("afterCompletion... ...");
|
|
- // 清理MDC
|
|
|
|
- if (LOG instanceof SLF4JImpl) {
|
|
|
|
- MDC.clear();
|
|
|
|
- }
|
|
|
|
|
|
+ // 清理log4j线程上下文
|
|
|
|
+ ThreadContext.clearAll();
|
|
}
|
|
}
|
|
|
|
|
|
-}
|
|
|
|
|
|
+}
|