mirror of
				https://github.com/continew-org/continew-starter.git
				synced 2025-10-31 10:57:15 +08:00 
			
		
		
		
	refactor(log): 优化访问日志相关配置属性名称
This commit is contained in:
		| @@ -23,12 +23,6 @@ | ||||
|             <artifactId>spring-boot-configuration-processor</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- servlet包 --> | ||||
|         <dependency> | ||||
|             <groupId>jakarta.servlet</groupId> | ||||
|             <artifactId>jakarta.servlet-api</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- Hibernate Validator --> | ||||
|         <dependency> | ||||
|             <groupId>org.hibernate.validator</groupId> | ||||
| @@ -65,5 +59,12 @@ | ||||
|             <groupId>cn.hutool</groupId> | ||||
|             <artifactId>hutool-http</artifactId> | ||||
|         </dependency> | ||||
|  | ||||
|         <!-- Jakarta(原 Javax Servlet) --> | ||||
|         <dependency> | ||||
|             <groupId>jakarta.servlet</groupId> | ||||
|             <artifactId>jakarta.servlet-api</artifactId> | ||||
|             <optional>true</optional> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
| </project> | ||||
| @@ -33,8 +33,8 @@ import java.nio.charset.StandardCharsets; | ||||
|  * 支持文件流直接透传,非文件流可重复读取 | ||||
|  * | ||||
|  * @author echo | ||||
|  * @since 2025/03/25 11:11 | ||||
|  **/ | ||||
|  * @since 2.10.0 | ||||
|  */ | ||||
| public class RepeatReadRequestWrapper extends HttpServletRequestWrapper { | ||||
|  | ||||
|     private byte[] cachedBody; | ||||
| @@ -50,13 +50,6 @@ public class RepeatReadRequestWrapper extends HttpServletRequestWrapper { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 检查是否为文件上传请求 | ||||
|      */ | ||||
|     private boolean isMultipartContent(HttpServletRequest request) { | ||||
|         return request.getContentType() != null && request.getContentType().toLowerCase().startsWith("multipart/"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public ServletInputStream getInputStream() throws IOException { | ||||
|         // 如果是文件上传,直接返回原始输入流 | ||||
| @@ -98,4 +91,14 @@ public class RepeatReadRequestWrapper extends HttpServletRequestWrapper { | ||||
|         } | ||||
|         return new BufferedReader(new InputStreamReader(new ByteArrayInputStream(cachedBody), StandardCharsets.UTF_8)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 检查是否为文件上传请求 | ||||
|      *  | ||||
|      * @param request 请求对象 | ||||
|      * @return 是否为文件上传请求 | ||||
|      */ | ||||
|     private boolean isMultipartContent(HttpServletRequest request) { | ||||
|         return request.getContentType() != null && request.getContentType().toLowerCase().startsWith("multipart/"); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -31,14 +31,16 @@ import java.nio.charset.StandardCharsets; | ||||
|  * 支持缓存响应内容,便于日志记录和后续处理 (不缓存SSE) | ||||
|  * | ||||
|  * @author echo | ||||
|  * @since 2025/03/25 11:11 | ||||
|  **/ | ||||
|  * @author Charles7c | ||||
|  * @since 2.10.0 | ||||
|  */ | ||||
| public class RepeatReadResponseWrapper extends HttpServletResponseWrapper { | ||||
|  | ||||
|     private final ByteArrayOutputStream cachedOutputStream = new ByteArrayOutputStream(); | ||||
|     private final PrintWriter writer = new PrintWriter(cachedOutputStream, true); | ||||
|  | ||||
|     // 是否为流式响应 | ||||
|     /** | ||||
|      * 是否为流式响应 | ||||
|      */ | ||||
|     private boolean isStreamingResponse = false; | ||||
|  | ||||
|     public RepeatReadResponseWrapper(HttpServletResponse response) { | ||||
| @@ -67,8 +69,8 @@ public class RepeatReadResponseWrapper extends HttpServletResponseWrapper { | ||||
|     @Override | ||||
|     public ServletOutputStream getOutputStream() throws IOException { | ||||
|         checkStreamingResponse(); | ||||
|         // 对于 SSE 流式响应,直接返回原始响应流,不做额外处理 | ||||
|         if (isStreamingResponse) { | ||||
|             // 对于 SSE 流式响应,直接返回原始响应流,不做额外处理 | ||||
|             return super.getOutputStream(); | ||||
|         } | ||||
|         return new ServletOutputStream() { | ||||
| @@ -108,6 +110,11 @@ public class RepeatReadResponseWrapper extends HttpServletResponseWrapper { | ||||
|         return writer; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取缓存的响应内容 | ||||
|      * | ||||
|      * @return 缓存的响应内容 | ||||
|      */ | ||||
|     public String getResponseContent() { | ||||
|         if (!isStreamingResponse) { | ||||
|             writer.flush(); | ||||
| @@ -116,12 +123,22 @@ public class RepeatReadResponseWrapper extends HttpServletResponseWrapper { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 将缓存的响应内容复制到原始响应中 | ||||
|      * | ||||
|      * @throws IOException IO 异常 | ||||
|      */ | ||||
|     public void copyBodyToResponse() throws IOException { | ||||
|         if (!isStreamingResponse && cachedOutputStream.size() > 0) { | ||||
|             getResponse().getOutputStream().write(cachedOutputStream.toByteArray()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 是否为流式响应 | ||||
|      * | ||||
|      * @return 是否为流式响应 | ||||
|      */ | ||||
|     public boolean isStreamingResponse() { | ||||
|         return isStreamingResponse; | ||||
|     } | ||||
|   | ||||
| @@ -22,8 +22,6 @@ import org.aspectj.lang.ProceedingJoinPoint; | ||||
| import org.aspectj.lang.annotation.Around; | ||||
| import org.aspectj.lang.annotation.Aspect; | ||||
| import org.aspectj.lang.annotation.Pointcut; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.web.context.request.RequestContextHolder; | ||||
| import org.springframework.web.context.request.ServletRequestAttributes; | ||||
| import top.continew.starter.log.handler.LogHandler; | ||||
| @@ -44,7 +42,6 @@ import java.time.Instant; | ||||
| @Aspect | ||||
| public class AccessLogAspect { | ||||
|  | ||||
|     private static final Logger log = LoggerFactory.getLogger(AccessLogAspect.class); | ||||
|     private final LogProperties logProperties; | ||||
|     private final LogHandler logHandler; | ||||
|  | ||||
| @@ -113,7 +110,8 @@ public class AccessLogAspect { | ||||
|         HttpServletRequest request = attributes.getRequest(); | ||||
|         HttpServletResponse response = attributes.getResponse(); | ||||
|         try { | ||||
|             logHandler.processAccessLogStartReq(AccessLogContext.builder() | ||||
|             // 开始访问日志记录 | ||||
|             logHandler.accessLogStart(AccessLogContext.builder() | ||||
|                 .startTime(startTime) | ||||
|                 .request(new RecordableServletHttpRequest(request)) | ||||
|                 .properties(logProperties) | ||||
| @@ -121,7 +119,7 @@ public class AccessLogAspect { | ||||
|             return joinPoint.proceed(); | ||||
|         } finally { | ||||
|             Instant endTime = Instant.now(); | ||||
|             logHandler.processAccessLogEndReq(AccessLogContext.builder() | ||||
|             logHandler.accessLogFinish(AccessLogContext.builder() | ||||
|                 .endTime(endTime) | ||||
|                 .response(new RecordableServletHttpResponse(response, response.getStatus())) | ||||
|                 .build()); | ||||
|   | ||||
| @@ -42,6 +42,7 @@ import java.net.URISyntaxException; | ||||
|  * @author Venil Noronha(Spring Boot Actuator) | ||||
|  * @author Madhura Bhave(Spring Boot Actuator) | ||||
|  * @author Charles7c | ||||
|  * @author echo | ||||
|  * @since 1.1.0 | ||||
|  */ | ||||
| public class LogFilter extends OncePerRequestFilter implements Ordered { | ||||
| @@ -66,15 +67,15 @@ public class LogFilter extends OncePerRequestFilter implements Ordered { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         boolean isMatch = logProperties.isMatch(request.getRequestURI()); | ||||
|         boolean isExcludeUri = logProperties.isMatch(request.getRequestURI()); | ||||
|  | ||||
|         // 处理可重复读取的请求 | ||||
|         HttpServletRequest requestWrapper = (isMatch || !this.isRequestWrapper(request)) | ||||
|         HttpServletRequest requestWrapper = (isExcludeUri || !this.isRequestWrapper(request)) | ||||
|             ? request | ||||
|             : new RepeatReadRequestWrapper(request); | ||||
|  | ||||
|         // 处理可重复读取的响应 | ||||
|         HttpServletResponse responseWrapper = (isMatch || !this.isResponseWrapper(response)) | ||||
|         HttpServletResponse responseWrapper = (isExcludeUri || !this.isResponseWrapper(response)) | ||||
|             ? response | ||||
|             : new RepeatReadResponseWrapper(response); | ||||
|  | ||||
|   | ||||
| @@ -171,11 +171,10 @@ public abstract class AbstractLogHandler implements LogHandler { | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void processAccessLogStartReq(AccessLogContext accessLogContext) { | ||||
|     public void accessLogStart(AccessLogContext accessLogContext) { | ||||
|         AccessLogProperties properties = accessLogContext.getProperties().getAccessLog(); | ||||
|         // 是否需要打印 规则: 是否打印开关 或 放行路径 | ||||
|         if (!properties.isPrint() || accessLogContext.getProperties() | ||||
|             .getAccessLog() | ||||
|             .isMatch(accessLogContext.getRequest().getPath())) { | ||||
|             return; | ||||
|         } | ||||
| @@ -184,22 +183,23 @@ public abstract class AbstractLogHandler implements LogHandler { | ||||
|         RecordableHttpRequest request = accessLogContext.getRequest(); | ||||
|         String path = request.getPath(); | ||||
|         String param = AccessLogUtils.getParam(request, properties); | ||||
|         log.info(param != null ? "[Start] [{}] {} {}" : "[Start] [{}] {}", request.getMethod(), path, param); | ||||
|         log.info(param != null ? "[Start] [{}] {} param: {}" : "[Start] [{}] {}", request.getMethod(), path, param); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void processAccessLogEndReq(AccessLogContext accessLogContext) { | ||||
|     public void accessLogFinish(AccessLogContext accessLogContext) { | ||||
|         AccessLogContext logContext = logContextThread.get(); | ||||
|         if (ObjectUtil.isNotEmpty(logContext)) { | ||||
|             try { | ||||
|                 RecordableHttpRequest request = logContext.getRequest(); | ||||
|                 RecordableHttpResponse response = accessLogContext.getResponse(); | ||||
|                 Duration timeTaken = Duration.between(logContext.getStartTime(), accessLogContext.getEndTime()); | ||||
|                 log.info("[End] [{}] {} {} {}ms", request.getMethod(), request.getPath(), response | ||||
|                     .getStatus(), timeTaken.toMillis()); | ||||
|             } finally { | ||||
|                 logContextThread.remove(); | ||||
|             } | ||||
|         if (ObjectUtil.isEmpty(logContext)) { | ||||
|             return; | ||||
|         } | ||||
|         try { | ||||
|             RecordableHttpRequest request = logContext.getRequest(); | ||||
|             RecordableHttpResponse response = accessLogContext.getResponse(); | ||||
|             Duration timeTaken = Duration.between(logContext.getStartTime(), accessLogContext.getEndTime()); | ||||
|             log.info("[End] [{}] {} {} {}ms", request.getMethod(), request.getPath(), response.getStatus(), timeTaken | ||||
|                 .toMillis()); | ||||
|         } finally { | ||||
|             logContextThread.remove(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -30,6 +30,7 @@ import java.util.Set; | ||||
|  * 日志处理器 | ||||
|  * | ||||
|  * @author Charles7c | ||||
|  * @author echo | ||||
|  * @since 2.8.0 | ||||
|  */ | ||||
| public interface LogHandler { | ||||
| @@ -100,16 +101,18 @@ public interface LogHandler { | ||||
|     Set<Include> getIncludes(Set<Include> includes, Method targetMethod, Class<?> targetClass); | ||||
|  | ||||
|     /** | ||||
|      * 处理访问日志开始请求 | ||||
|      * 开始访问日志记录 | ||||
|      * | ||||
|      * @param accessLogContext 访问日志上下文 | ||||
|      * @since 2.10.0 | ||||
|      */ | ||||
|     void processAccessLogStartReq(AccessLogContext accessLogContext); | ||||
|     void accessLogStart(AccessLogContext accessLogContext); | ||||
|  | ||||
|     /** | ||||
|      * 处理访问日志 结束请求 | ||||
|      * 结束访问日志记录 | ||||
|      * | ||||
|      * @param accessLogContext 访问日志上下文 | ||||
|      * @since 2.10.0 | ||||
|      */ | ||||
|     void processAccessLogEndReq(AccessLogContext accessLogContext); | ||||
|     void accessLogFinish(AccessLogContext accessLogContext); | ||||
| } | ||||
|   | ||||
| @@ -25,6 +25,7 @@ import java.util.Map; | ||||
|  * @author Andy Wilkinson(Spring Boot Actuator) | ||||
|  * @author Phillip Webb(Spring Boot Actuator) | ||||
|  * @author Charles7c | ||||
|  * @author echo | ||||
|  * @see RecordableHttpResponse | ||||
|  * @since 1.1.0 | ||||
|  */ | ||||
| @@ -45,11 +46,13 @@ public interface RecordableHttpRequest { | ||||
|     URI getUrl(); | ||||
|  | ||||
|     /** | ||||
|      * 获取 IP | ||||
|      * 获取路径 | ||||
|      * <p>/foo/bar</p> | ||||
|      * | ||||
|      * @return IP | ||||
|      * @return 路径 | ||||
|      * @since 2.10.0 | ||||
|      */ | ||||
|     String getIp(); | ||||
|     String getPath(); | ||||
|  | ||||
|     /** | ||||
|      * 获取请求头 | ||||
| @@ -73,9 +76,9 @@ public interface RecordableHttpRequest { | ||||
|     Map<String, Object> getParam(); | ||||
|  | ||||
|     /** | ||||
|      * 获取路径 - 格式 /system/dept | ||||
|      * 获取 IP | ||||
|      * | ||||
|      * @return {@link String } | ||||
|      * @return IP | ||||
|      */ | ||||
|     String getPath(); | ||||
|     String getIp(); | ||||
| } | ||||
|   | ||||
| @@ -35,6 +35,8 @@ import java.util.Map; | ||||
|  * | ||||
|  * @author Andy Wilkinson(Spring Boot Actuator) | ||||
|  * @author Charles7c | ||||
|  * @author echo | ||||
|  * @since 1.1.0 | ||||
|  */ | ||||
| public final class RecordableServletHttpRequest implements RecordableHttpRequest { | ||||
|  | ||||
| @@ -66,8 +68,8 @@ public final class RecordableServletHttpRequest implements RecordableHttpRequest | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getIp() { | ||||
|         return JakartaServletUtil.getClientIP(request); | ||||
|     public String getPath() { | ||||
|         return request.getRequestURI(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -90,8 +92,8 @@ public final class RecordableServletHttpRequest implements RecordableHttpRequest | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public String getPath() { | ||||
|         return request.getRequestURI(); | ||||
|     public String getIp() { | ||||
|         return JakartaServletUtil.getClientIP(request); | ||||
|     } | ||||
|  | ||||
|     private StringBuilder appendQueryString(String queryString) { | ||||
|   | ||||
| @@ -30,6 +30,8 @@ import java.util.Map; | ||||
|  * | ||||
|  * @author Andy Wilkinson(Spring Boot Actuator) | ||||
|  * @author Charles7c | ||||
|  * @author echo | ||||
|  * @since 1.1.0 | ||||
|  */ | ||||
| public final class RecordableServletHttpResponse implements RecordableHttpResponse { | ||||
|  | ||||
|   | ||||
| @@ -25,7 +25,7 @@ import java.time.Instant; | ||||
|  * 访问日志上下文 | ||||
|  * | ||||
|  * @author echo | ||||
|  * @since 2.8.3 | ||||
|  * @since 2.10.0 | ||||
|  */ | ||||
| public class AccessLogContext { | ||||
|  | ||||
| @@ -90,7 +90,11 @@ public class AccessLogContext { | ||||
|         return new Builder(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 访问日志上下文构建者 | ||||
|      */ | ||||
|     public static class Builder { | ||||
|  | ||||
|         private Instant startTime; | ||||
|         private Instant endTime; | ||||
|         private RecordableHttpRequest request; | ||||
|   | ||||
| @@ -16,76 +16,71 @@ | ||||
|  | ||||
| package top.continew.starter.log.model; | ||||
|  | ||||
| import top.continew.starter.web.util.SpringWebUtils; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 访问日志输出配置 | ||||
|  * 访问日志配置属性 | ||||
|  * | ||||
|  * @author echo | ||||
|  * @since 2.8.3 | ||||
|  * @author Charles7c | ||||
|  * @since 2.10.0 | ||||
|  */ | ||||
| public class AccessLogProperties { | ||||
|  | ||||
|     /** | ||||
|      * 是否打印日志,开启后可打印访问日志(类似于 Nginx access log) | ||||
|      * 是否打印访问日志(类似于 Nginx access log) | ||||
|      * <p> | ||||
|      * 不记录日志也支持开启打印访问日志 | ||||
|      * 不记录请求日志也支持开启打印访问日志 | ||||
|      * </p> | ||||
|      */ | ||||
|     private boolean isPrint = false; | ||||
|  | ||||
|     /** | ||||
|      * 放行路由 | ||||
|      * 是否打印请求参数(body/query/form) | ||||
|      * <p>开启后,访问日志会打印请求参数</p> | ||||
|      */ | ||||
|     private List<String> excludePatterns = new ArrayList<>(); | ||||
|  | ||||
|     /** | ||||
|      * 是否记录请求参数(body/query/form) | ||||
|      * <p>开启后会在日志中输出请求参数</p> | ||||
|      */ | ||||
|     private boolean isReqParams = false; | ||||
|     private boolean isPrintRequestParam = false; | ||||
|  | ||||
|     /** | ||||
|      * 是否自动截断超长参数值(如 base64、大文本) | ||||
|      * <p>开启后会对超过指定长度的参数值进行截断处理</p> | ||||
|      * <p>开启后,超过指定长度的参数值将会自动截断处理</p> | ||||
|      */ | ||||
|     private boolean truncateLongParams = false; | ||||
|     private boolean longParamTruncate = false; | ||||
|  | ||||
|     /** | ||||
|      * 超长参数检测阈值(单位:字符) | ||||
|      * <p>当参数值长度超过此值时,触发截断规则</p> | ||||
|      * <p>默认:2000</p> | ||||
|      * <p>默认:2000,仅在 {@link #longParamTruncate} 启用时生效</p> | ||||
|      */ | ||||
|     private int ultraLongParamThreshold = 2000; | ||||
|     private int longParamThreshold = 2000; | ||||
|  | ||||
|     /** | ||||
|      * 超长参数最大展示长度(单位:字符) | ||||
|      * <p>当参数超过ultraLongParamThreshold时,强制截断到此长度</p> | ||||
|      * <p>默认:50</p> | ||||
|      * 超长参数最大保留长度(单位:字符) | ||||
|      * <p>当参数超过 {@link #longParamThreshold} 时,强制截断到此长度</p> | ||||
|      * <p>默认:50,仅在 {@link #longParamTruncate} 启用时生效</p> | ||||
|      */ | ||||
|     private int ultraLongParamMaxLength = 50; | ||||
|     private int longParamMaxLength = 50; | ||||
|  | ||||
|     /** | ||||
|      * 截断后追加的后缀符号(如配置 "..." 会让截断内容更直观) | ||||
|      * <p>建议配置 3-5 个非占宽字符,默认为空不追加</p> | ||||
|      * <p>建议配置 3-5 个非占宽字符,默认为 ...</p> | ||||
|      * <p>仅在 {@link #longParamTruncate} 启用时生效</p> | ||||
|      */ | ||||
|     private String truncateSuffix = "..."; | ||||
|     private String longParamSuffix = "..."; | ||||
|  | ||||
|     /** | ||||
|      * 是否过滤敏感参数 | ||||
|      * <p>开启后会对敏感参数进行过滤,默认不过滤</p> | ||||
|      */ | ||||
|     private boolean isSensitiveParams = false; | ||||
|     private boolean isParamSensitive = false; | ||||
|  | ||||
|     /** | ||||
|      * 敏感参数字段列表(如:password,token,idCard) | ||||
|      * <p>支持精确匹配(区分大小写)</p> | ||||
|      * <p>示例值:password,oldPassword</p> | ||||
|      */ | ||||
|     private List<String> sensitiveParamList = new ArrayList<>(); | ||||
|     private List<String> sensitiveParams = new ArrayList<>(); | ||||
|  | ||||
|     public boolean isPrint() { | ||||
|         return isPrint; | ||||
| @@ -95,77 +90,59 @@ public class AccessLogProperties { | ||||
|         isPrint = print; | ||||
|     } | ||||
|  | ||||
|     public List<String> getExcludePatterns() { | ||||
|         return excludePatterns; | ||||
|     public boolean isPrintRequestParam() { | ||||
|         return isPrintRequestParam; | ||||
|     } | ||||
|  | ||||
|     public void setExcludePatterns(List<String> excludePatterns) { | ||||
|         this.excludePatterns = excludePatterns; | ||||
|     public void setPrintRequestParam(boolean printRequestParam) { | ||||
|         isPrintRequestParam = printRequestParam; | ||||
|     } | ||||
|  | ||||
|     public boolean isReqParams() { | ||||
|         return isReqParams; | ||||
|     public boolean isLongParamTruncate() { | ||||
|         return longParamTruncate; | ||||
|     } | ||||
|  | ||||
|     public void setReqParams(boolean reqParams) { | ||||
|         isReqParams = reqParams; | ||||
|     public void setLongParamTruncate(boolean longParamTruncate) { | ||||
|         this.longParamTruncate = longParamTruncate; | ||||
|     } | ||||
|  | ||||
|     public boolean isTruncateLongParams() { | ||||
|         return truncateLongParams; | ||||
|     public int getLongParamThreshold() { | ||||
|         return longParamThreshold; | ||||
|     } | ||||
|  | ||||
|     public void setTruncateLongParams(boolean truncateLongParams) { | ||||
|         this.truncateLongParams = truncateLongParams; | ||||
|     public void setLongParamThreshold(int longParamThreshold) { | ||||
|         this.longParamThreshold = longParamThreshold; | ||||
|     } | ||||
|  | ||||
|     public int getUltraLongParamThreshold() { | ||||
|         return ultraLongParamThreshold; | ||||
|     public int getLongParamMaxLength() { | ||||
|         return longParamMaxLength; | ||||
|     } | ||||
|  | ||||
|     public void setUltraLongParamThreshold(int ultraLongParamThreshold) { | ||||
|         this.ultraLongParamThreshold = ultraLongParamThreshold; | ||||
|     public void setLongParamMaxLength(int longParamMaxLength) { | ||||
|         this.longParamMaxLength = longParamMaxLength; | ||||
|     } | ||||
|  | ||||
|     public int getUltraLongParamMaxLength() { | ||||
|         return ultraLongParamMaxLength; | ||||
|     public String getLongParamSuffix() { | ||||
|         return longParamSuffix; | ||||
|     } | ||||
|  | ||||
|     public void setUltraLongParamMaxLength(int ultraLongParamMaxLength) { | ||||
|         this.ultraLongParamMaxLength = ultraLongParamMaxLength; | ||||
|     public void setLongParamSuffix(String longParamSuffix) { | ||||
|         this.longParamSuffix = longParamSuffix; | ||||
|     } | ||||
|  | ||||
|     public String getTruncateSuffix() { | ||||
|         return truncateSuffix; | ||||
|     public boolean isParamSensitive() { | ||||
|         return isParamSensitive; | ||||
|     } | ||||
|  | ||||
|     public void setTruncateSuffix(String truncateSuffix) { | ||||
|         this.truncateSuffix = truncateSuffix; | ||||
|     public void setParamSensitive(boolean paramSensitive) { | ||||
|         isParamSensitive = paramSensitive; | ||||
|     } | ||||
|  | ||||
|     public boolean isSensitiveParams() { | ||||
|         return isSensitiveParams; | ||||
|     public List<String> getSensitiveParams() { | ||||
|         return sensitiveParams; | ||||
|     } | ||||
|  | ||||
|     public void setSensitiveParams(boolean sensitiveParams) { | ||||
|         isSensitiveParams = sensitiveParams; | ||||
|     } | ||||
|  | ||||
|     public List<String> getSensitiveParamList() { | ||||
|         return sensitiveParamList; | ||||
|     } | ||||
|  | ||||
|     public void setSensitiveParamList(List<String> sensitiveParamList) { | ||||
|         this.sensitiveParamList = sensitiveParamList; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 是否匹配放行路由 | ||||
|      * | ||||
|      * @param uri 请求 URI | ||||
|      * @return 是否匹配 | ||||
|      */ | ||||
|     public boolean isMatch(String uri) { | ||||
|         return this.getExcludePatterns().stream().anyMatch(pattern -> SpringWebUtils.isMatch(uri, pattern)); | ||||
|     public void setSensitiveParams(List<String> sensitiveParams) { | ||||
|         this.sensitiveParams = sensitiveParams; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -26,14 +26,14 @@ import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * 访问日志工具类 | ||||
|  * | ||||
|  * @author echo | ||||
|  * @since 2025/03/25 19:16 | ||||
|  **/ | ||||
|  * @author Charles7c | ||||
|  * @since 2.10.0 | ||||
|  */ | ||||
| public class AccessLogUtils { | ||||
|  | ||||
|     public AccessLogUtils() { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取参数信息 | ||||
|      * | ||||
| @@ -42,8 +42,8 @@ public class AccessLogUtils { | ||||
|      * @return {@link String } | ||||
|      */ | ||||
|     public static String getParam(RecordableHttpRequest request, AccessLogProperties properties) { | ||||
|         // 是否需要输出参数 | ||||
|         if (!properties.isReqParams()) { | ||||
|         // 是否需要打印请求参数 | ||||
|         if (!properties.isPrintRequestParam()) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
| @@ -54,16 +54,16 @@ public class AccessLogUtils { | ||||
|         } | ||||
|  | ||||
|         // 是否需要对特定入参脱敏 | ||||
|         if (properties.isSensitiveParams()) { | ||||
|             params = filterSensitiveParams(params, properties.getSensitiveParamList()); | ||||
|         if (properties.isParamSensitive()) { | ||||
|             params = filterSensitiveParams(params, properties.getSensitiveParams()); | ||||
|         } | ||||
|  | ||||
|         // 是否自动截断超长参数值 | ||||
|         if (properties.isTruncateLongParams()) { | ||||
|             params = truncateLongParams(params, properties.getUltraLongParamThreshold(), properties | ||||
|                 .getUltraLongParamMaxLength(), properties.getTruncateSuffix()); | ||||
|         if (properties.isLongParamTruncate()) { | ||||
|             params = truncateLongParams(params, properties.getLongParamThreshold(), properties | ||||
|                 .getLongParamMaxLength(), properties.getLongParamSuffix()); | ||||
|         } | ||||
|         return "param:" + JSONUtil.toJsonStr(params); | ||||
|         return JSONUtil.toJsonStr(params); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -80,9 +80,7 @@ public class AccessLogUtils { | ||||
|  | ||||
|         Map<String, Object> filteredParams = new HashMap<>(params); | ||||
|         for (String sensitiveKey : sensitiveParams) { | ||||
|             if (filteredParams.containsKey(sensitiveKey)) { | ||||
|                 filteredParams.put(sensitiveKey, "***"); | ||||
|             } | ||||
|             filteredParams.computeIfPresent(sensitiveKey, (key, value) -> "***"); | ||||
|         } | ||||
|         return filteredParams; | ||||
|     } | ||||
| @@ -115,4 +113,7 @@ public class AccessLogUtils { | ||||
|         } | ||||
|         return truncatedParams; | ||||
|     } | ||||
|  | ||||
|     private AccessLogUtils() { | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -64,7 +64,7 @@ public class LogInterceptor implements HandlerInterceptor { | ||||
|                              @NonNull HttpServletResponse response, | ||||
|                              @NonNull Object handler) { | ||||
|         Instant startTime = Instant.now(); | ||||
|         logHandler.processAccessLogStartReq(AccessLogContext.builder() | ||||
|         logHandler.accessLogStart(AccessLogContext.builder() | ||||
|             .startTime(startTime) | ||||
|             .request(new RecordableServletHttpRequest(request)) | ||||
|             .properties(logProperties) | ||||
| @@ -84,7 +84,7 @@ public class LogInterceptor implements HandlerInterceptor { | ||||
|                                 Exception e) { | ||||
|         try { | ||||
|             Instant endTime = Instant.now(); | ||||
|             logHandler.processAccessLogEndReq(AccessLogContext.builder() | ||||
|             logHandler.accessLogFinish(AccessLogContext.builder() | ||||
|                 .endTime(endTime) | ||||
|                 .response(new RecordableServletHttpResponse(response, response.getStatus())) | ||||
|                 .build()); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user