fix:解决PlusWebInvokeTimeInterceptor获取真实请求路径和参数不准确问题

This commit is contained in:
lizhixian 2024-03-27 16:31:04 +08:00
parent c6c615308c
commit 81cdf5b3c7

View File

@ -1,20 +1,27 @@
package org.dromara.common.web.interceptor; package org.dromara.common.web.interceptor;
import cn.hutool.core.io.IoUtil; import com.alibaba.ttl.TransmittableThreadLocal;
import cn.hutool.core.map.MapUtil;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.time.StopWatch; import org.apache.commons.lang3.time.StopWatch;
import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.web.filter.RepeatedlyRequestWrapper; import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
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 java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
/** /**
@ -29,34 +36,20 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor {
private final String prodProfile = "prod"; private final String prodProfile = "prod";
private final static ThreadLocal<StopWatch> KEY_CACHE = new ThreadLocal<>(); private final TransmittableThreadLocal<StopWatch> invokeTimeTL = new TransmittableThreadLocal<>();
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!prodProfile.equals(SpringUtils.getActiveProfile())) { if (!prodProfile.equals(SpringUtils.getActiveProfile())) {
String url = request.getMethod() + " " + request.getRequestURI(); if (handler instanceof HandlerMethod handlerMethod) {
String apiUrl = getRequestUrl(handlerMethod);
// 打印请求参数 log.info("[PLUS]开始请求 => URL[{}]", request.getMethod() + " " + apiUrl);
if (isJsonRequest(request)) { parameterMap(request);
String jsonParam = ""; parameterBodyMap(request, apiUrl);
if (request instanceof RepeatedlyRequestWrapper) { StopWatch stopWatch = new StopWatch();
BufferedReader reader = request.getReader(); invokeTimeTL.set(stopWatch);
jsonParam = IoUtil.read(reader); stopWatch.start();
}
log.info("[PLUS]开始请求 => URL[{}],参数类型[json],参数:[{}]", url, jsonParam);
} else {
Map<String, String[]> parameterMap = request.getParameterMap();
if (MapUtil.isNotEmpty(parameterMap)) {
String parameters = JsonUtils.toJsonString(parameterMap);
log.info("[PLUS]开始请求 => URL[{}],参数类型[param],参数:[{}]", url, parameters);
} else {
log.info("[PLUS]开始请求 => URL[{}],无参数", url);
}
} }
StopWatch stopWatch = new StopWatch();
KEY_CACHE.set(stopWatch);
stopWatch.start();
} }
return true; return true;
} }
@ -69,10 +62,14 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor {
@Override @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
if (!prodProfile.equals(SpringUtils.getActiveProfile())) { if (!prodProfile.equals(SpringUtils.getActiveProfile())) {
StopWatch stopWatch = KEY_CACHE.get(); StopWatch stopWatch = invokeTimeTL.get();
stopWatch.stop(); stopWatch.stop();
log.info("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime()); if (handler instanceof HandlerMethod handlerMethod) {
KEY_CACHE.remove(); String apiUrl = getRequestUrl(handlerMethod);
log.info("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + apiUrl, stopWatch.getTime());
}
invokeTimeTL.remove();
} }
} }
@ -81,7 +78,9 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor {
* *
* @param request request * @param request request
* @return boolean * @return boolean
* @since 5.0.0
*/ */
@Deprecated
private boolean isJsonRequest(HttpServletRequest request) { private boolean isJsonRequest(HttpServletRequest request) {
String contentType = request.getContentType(); String contentType = request.getContentType();
if (contentType != null) { if (contentType != null) {
@ -90,4 +89,101 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor {
return false; return false;
} }
/**
* 获取请求的真实接口地址
*
* @param handlerMethod handlerMethod
* @return 返回接口地址
*/
private static String getRequestUrl(HandlerMethod handlerMethod) {
StringBuilder apiURL = new StringBuilder();
//获取类上的RequestMapping注解
RequestMapping mapping = handlerMethod.getBeanType().getAnnotation(RequestMapping.class);
if (null != mapping) {
apiURL.append(mapping.value()[0]);
}
Method method = handlerMethod.getMethod();
//获取方法上的RequestMapping注解
RequestMapping methodRequestMapping = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);
if (methodRequestMapping != null) {
String[] value = methodRequestMapping.value();
if (value.length > 0) {
apiURL.append(value[0]);
}
}
return apiURL.toString();
}
/**
* 获取GET请求中使用entity中的参数
*
* @param request request
*/
private void parameterMap(HttpServletRequest request) {
Enumeration<String> parameterNames = request.getParameterNames();
Map<String, Object> getParameters = new LinkedHashMap<>();
if (parameterNames.hasMoreElements()) {
while (parameterNames.hasMoreElements()) {
String name = parameterNames.nextElement();
String value = request.getParameter(name);
getParameters.put(name, value);
}
log.info("[PLUS]请求参数 => 参数内容:[{}]", JsonUtils.toJsonString(getParameters));
}
}
/**
* 获取restful风格参数和body请求参数
*
* @param request 请求
* @param apiURL 接口地址
*/
private static void parameterBodyMap(HttpServletRequest request, String apiURL) {
//获取restful风格参数
Map<String, Object> parameterMap = findCommonCharacters(request.getRequestURI(), apiURL);
if (ObjectUtils.isNotEmpty(parameterMap)) {
log.info("[PLUS]请求参数 => 参数内容:[{}]", JsonUtils.toJsonString(parameterMap));
}
//获取body参数
int contentLength = request.getContentLength();
if (contentLength > 0) {
try {
// 获取请求体的输入流
BufferedReader reader = request.getReader();
StringBuilder body = new StringBuilder();
String line;
// 逐行读取请求体内容
while ((line = reader.readLine()) != null) {
body.append(line);
}
if (ObjectUtils.isNotEmpty(body)) {
log.info("[PLUS]请求参数 => 参数内容:[{}]", body);
}
} catch (IOException e) {
log.error("[PLUS]拦截器获取body参数异常", e);
}
}
}
/**
* 获取restfull风格参数
*
* @param str1 全路径
* @param str2 接口路径
* @return Map<String, Object>
*/
private static Map<String, Object> findCommonCharacters(String str1, String str2) {
if (str1 == null || str2 == null) {
return Collections.emptyMap();
}
int index = StringUtils.indexOfDifference(str1, str2);
if (index == -1) {
return Collections.emptyMap();
}
String values = StringUtils.substring(str1, index);
String params = StringUtils.substring(str2, index);
Map<String, Object> parameterMap = new LinkedHashMap<>();
parameterMap.put(params.replace("{","").replace("}",""), values);
return parameterMap;
}
} }