From 152781b05131e48bf6e94d71cc72dd54af52a3fb Mon Sep 17 00:00:00 2001 From: houzhongjian <houzhongyi@126.com> Date: 星期四, 10 四月 2025 14:13:29 +0800 Subject: [PATCH] 恢复iailab-framework --- iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 103 insertions(+), 0 deletions(-) diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java new file mode 100644 index 0000000..f22500a --- /dev/null +++ b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java @@ -0,0 +1,103 @@ +package com.iailab.framework.apilog.core.interceptor; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.util.StrUtil; +import com.iailab.framework.common.util.servlet.ServletUtils; +import com.iailab.framework.common.util.spring.SpringUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.util.StopWatch; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.IntStream; + +/** + * API 访问日志 Interceptor + * + * 目的:在非 prod 环境时,打印 request 和 response 两条日志到日志文件(控制台)中。 + * + * @author iailab + */ +@Slf4j +public class ApiAccessLogInterceptor implements HandlerInterceptor { + + public static final String ATTRIBUTE_HANDLER_METHOD = "HANDLER_METHOD"; + + private static final String ATTRIBUTE_STOP_WATCH = "ApiAccessLogInterceptor.StopWatch"; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + // 记录 HandlerMethod,提供给 ApiAccessLogFilter 使用 + HandlerMethod handlerMethod = handler instanceof HandlerMethod ? (HandlerMethod) handler : null; + if (handlerMethod != null) { + request.setAttribute(ATTRIBUTE_HANDLER_METHOD, handlerMethod); + } + + // 打印 request 日志 + if (!SpringUtils.isProd()) { + Map<String, String> queryString = ServletUtils.getParamMap(request); + String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtils.getBody(request) : null; + if (CollUtil.isEmpty(queryString) && StrUtil.isEmpty(requestBody)) { + log.info("[preHandle][开始请求 URL({}) 无参数]", request.getRequestURI()); + } else { + log.info("[preHandle][开始请求 URL({}) 参数({})]", request.getRequestURI(), + StrUtil.blankToDefault(requestBody, queryString.toString())); + } + // 计时 + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + request.setAttribute(ATTRIBUTE_STOP_WATCH, stopWatch); + // 打印 Controller 路径 + printHandlerMethodPosition(handlerMethod); + } + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { + // 打印 response 日志 + if (!SpringUtils.isProd()) { + StopWatch stopWatch = (StopWatch) request.getAttribute(ATTRIBUTE_STOP_WATCH); + stopWatch.stop(); + log.info("[afterCompletion][完成请求 URL({}) 耗时({} ms)]", + request.getRequestURI(), stopWatch.getTotalTimeMillis()); + } + } + + /** + * 打印 Controller 方法路径 + */ + private void printHandlerMethodPosition(HandlerMethod handlerMethod) { + if (handlerMethod == null) { + return; + } + Method method = handlerMethod.getMethod(); + Class<?> clazz = method.getDeclaringClass(); + try { + // 获取 method 的 lineNumber + List<String> clazzContents = FileUtil.readUtf8Lines( + ResourceUtil.getResource(null, clazz).getPath().replace("/target/classes/", "/src/main/java/") + + clazz.getSimpleName() + ".java"); + Optional<Integer> lineNumber = IntStream.range(0, clazzContents.size()) + .filter(i -> clazzContents.get(i).contains(" " + method.getName() + "(")) // 简单匹配,不考虑方法重名 + .mapToObj(i -> i + 1) // 行号从 1 开始 + .findFirst(); + if (!lineNumber.isPresent()) { + return; + } + // 打印结果 + System.out.printf("\tController 方法路径:%s(%s.java:%d)\n", clazz.getName(), clazz.getSimpleName(), lineNumber.get()); + } catch (Exception ignore) { + // 忽略异常。原因:仅仅打印,非重要逻辑 + } + } + +} -- Gitblit v1.9.3