From ff81ea1b22aa35776012233f0e3c8b4073faee69 Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期五, 10 四月 2026 22:47:27 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java |  315 +++++++++++++++++++++++++++++-----------------------
 1 files changed, 176 insertions(+), 139 deletions(-)

diff --git a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java
index 5c46133..f70057c 100644
--- a/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java
+++ b/xp-robotaxi-traffic-control-boot/src/main/java/com/xiaopeng/trafficControl/config/log/RequestResponseLoggingFilter.java
@@ -1,139 +1,176 @@
-package com.xiaopeng.trafficControl.config.log;
-
-import lombok.extern.slf4j.Slf4j;
-import org.slf4j.MDC;
-import org.springframework.core.Ordered;
-import org.springframework.core.annotation.Order;
-import org.springframework.http.MediaType;
-import org.springframework.stereotype.Component;
-import org.springframework.web.filter.OncePerRequestFilter;
-import org.springframework.web.util.ContentCachingRequestWrapper;
-import org.springframework.web.util.ContentCachingResponseWrapper;
-
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * 请求/响应日志过滤器
- * 打印:traceId、method、uri、queryString、请求体、响应状态、耗时、响应体
- */
-@Slf4j
-@Component
-@Order(Ordered.HIGHEST_PRECEDENCE + 10)
-public class RequestResponseLoggingFilter extends OncePerRequestFilter {
-
-    /** 不打印 body 的路径前缀(健康检查、actuator 等) */
-    private static final Set<String> EXCLUDE_PATHS = new HashSet<>(Arrays.asList(
-            "/actuator", "/healthcheck", "/health", "/prometheus"
-    ));
-
-    /** 只对这些 Content-Type 打印 body(避免打印二进制流) */
-    private static final Set<String> LOGGABLE_CONTENT_TYPES = new HashSet<>(Arrays.asList(
-            MediaType.APPLICATION_JSON_VALUE,
-            MediaType.APPLICATION_JSON_UTF8_VALUE,
-            MediaType.TEXT_PLAIN_VALUE,
-            MediaType.TEXT_XML_VALUE,
-            MediaType.APPLICATION_XML_VALUE,
-            "application/x-www-form-urlencoded"
-    ));
-
-    private static final int MAX_BODY_LENGTH = 2000;
-
-    @Override
-    protected boolean shouldNotFilter(HttpServletRequest request) {
-        String uri = request.getRequestURI();
-        return EXCLUDE_PATHS.stream().anyMatch(uri::startsWith);
-    }
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
-                                    FilterChain chain) throws ServletException, IOException {
-        // 初始化 MDC(Filter 先于 Interceptor 执行,在此统一设置)
-        String traceId = request.getHeader("X-Trace-Id");
-        if (traceId == null || traceId.isEmpty()) {
-            traceId = java.util.UUID.randomUUID().toString().replace("-", "");
-        }
-        MDC.put("traceId",    traceId);
-        MDC.put("clientIp",   getClientIp(request));
-        MDC.put("requestUri", request.getRequestURI());
-        response.setHeader("X-Trace-Id", traceId);
-
-        ContentCachingRequestWrapper reqWrapper  = new ContentCachingRequestWrapper(request);
-        ContentCachingResponseWrapper respWrapper = new ContentCachingResponseWrapper(response);
-
-        long start = System.currentTimeMillis();
-        try {
-            chain.doFilter(reqWrapper, respWrapper);
-        } finally {
-            long cost = System.currentTimeMillis() - start;
-            logRequest(reqWrapper);
-            logResponse(respWrapper, cost);
-            // 必须把响应体写回,否则客户端收不到数据
-            respWrapper.copyBodyToResponse();
-            MDC.clear();
-        }
-    }
-
-    private String getClientIp(HttpServletRequest request) {
-        String ip = request.getHeader("X-Forwarded-For");
-        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
-            return ip.split(",")[0].trim();
-        }
-        ip = request.getHeader("X-Real-IP");
-        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
-            return ip;
-        }
-        return request.getRemoteAddr();
-    }
-
-    private void logRequest(ContentCachingRequestWrapper request) {
-        String traceId = MDC.get("traceId");
-        String uri     = request.getRequestURI();
-        String query   = request.getQueryString();
-        String method  = request.getMethod();
-        String body    = extractBody(request.getContentAsByteArray(), request.getContentType());
-
-        log.info(">>> [{}] {} {}{} | body={}",
-                traceId,
-                method,
-                uri,
-                query != null ? "?" + query : "",
-                body);
-    }
-
-    private void logResponse(ContentCachingResponseWrapper response, long cost) {
-        String traceId = MDC.get("traceId");
-        int    status  = response.getStatus();
-        String body    = extractBody(response.getContentAsByteArray(), response.getContentType());
-
-        log.info("<<< [{}] status={} cost={}ms | body={}",
-                traceId, status, cost, body);
-    }
-
-    private String extractBody(byte[] bodyBytes, String contentType) {
-        if (bodyBytes == null || bodyBytes.length == 0) {
-            return "";
-        }
-        if (!isLoggableContentType(contentType)) {
-            return "[binary, " + bodyBytes.length + " bytes]";
-        }
-        String body = new String(bodyBytes, StandardCharsets.UTF_8);
-        if (body.length() > MAX_BODY_LENGTH) {
-            body = body.substring(0, MAX_BODY_LENGTH) + "...(truncated)";
-        }
-        return body;
-    }
-
-    private boolean isLoggableContentType(String contentType) {
-        if (contentType == null) return true;
-        String ct = contentType.toLowerCase();
-        return LOGGABLE_CONTENT_TYPES.stream().anyMatch(ct::contains);
-    }
-}
+//package com.xiaopeng.trafficControl.config.log;
+//
+//import com.xiaopeng.common.log.config.LogHeaderProperties;
+//import lombok.extern.slf4j.Slf4j;
+//import org.slf4j.MDC;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.core.Ordered;
+//import org.springframework.core.annotation.Order;
+//import org.springframework.http.MediaType;
+//import org.springframework.stereotype.Component;
+//import org.springframework.web.filter.OncePerRequestFilter;
+//import org.springframework.web.util.ContentCachingRequestWrapper;
+//import org.springframework.web.util.ContentCachingResponseWrapper;
+//
+//import javax.servlet.FilterChain;
+//import javax.servlet.ServletException;
+//import javax.servlet.http.HttpServletRequest;
+//import javax.servlet.http.HttpServletResponse;
+//import java.io.IOException;
+//import java.nio.charset.StandardCharsets;
+//import java.util.*;
+//
+///**
+// * 请求/响应日志过滤器
+// * 打印:traceId、method、uri、queryString、请求体、响应状态、耗时、响应体
+// */
+//@Slf4j
+//@Component
+//@Order(Ordered.HIGHEST_PRECEDENCE + 10)
+//public class RequestResponseLoggingFilter extends OncePerRequestFilter {
+//
+//    @Autowired
+//    private LogHeaderProperties logHeaderProperties;
+//
+//    /** 不打印 body 的路径前缀(健康检查、actuator 等) */
+//    private static final Set<String> EXCLUDE_PATHS = new HashSet<>(Arrays.asList(
+//            "/actuator", "/healthcheck", "/health", "/prometheus"
+//    ));
+//
+//    /** 只对这些 Content-Type 打印 body(避免打印二进制流) */
+//    private static final Set<String> LOGGABLE_CONTENT_TYPES = new HashSet<>(Arrays.asList(
+//            MediaType.APPLICATION_JSON_VALUE,
+//            MediaType.APPLICATION_JSON_UTF8_VALUE,
+//            MediaType.TEXT_PLAIN_VALUE,
+//            MediaType.TEXT_XML_VALUE,
+//            MediaType.APPLICATION_XML_VALUE,
+//            "application/x-www-form-urlencoded"
+//    ));
+//
+//    private static final int MAX_BODY_LENGTH = 2000;
+//
+//    @Override
+//    protected boolean shouldNotFilter(HttpServletRequest request) {
+//        String uri = request.getRequestURI();
+//        return EXCLUDE_PATHS.stream().anyMatch(uri::startsWith);
+//    }
+//
+//    @Override
+//    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
+//                                    FilterChain chain) throws ServletException, IOException {
+//        // 初始化 MDC(Filter 先于 Interceptor 执行,在此统一设置)
+//        String traceId = request.getHeader("X-Trace-Id");
+//        if (traceId == null || traceId.isEmpty()) {
+//            traceId = UUID.randomUUID().toString().replace("-", "");
+//        }
+//        MDC.put("traceId",    traceId);
+//        MDC.put("clientIp",   getClientIp(request));
+//        MDC.put("requestUri", request.getRequestURI());
+//        response.setHeader("X-Trace-Id", traceId);
+//
+//        ContentCachingRequestWrapper reqWrapper  = new ContentCachingRequestWrapper(request);
+//        ContentCachingResponseWrapper respWrapper = new ContentCachingResponseWrapper(response);
+//
+//        long start = System.currentTimeMillis();
+//        try {
+//            chain.doFilter(reqWrapper, respWrapper);
+//        } finally {
+//            long cost = System.currentTimeMillis() - start;
+//            logRequest(reqWrapper);
+//            logResponse(respWrapper, cost);
+//            // 必须把响应体写回,否则客户端收不到数据
+//            respWrapper.copyBodyToResponse();
+//            MDC.clear();
+//        }
+//    }
+//
+//    private String getClientIp(HttpServletRequest request) {
+//        String ip = request.getHeader("X-Forwarded-For");
+//        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
+//            return ip.split(",")[0].trim();
+//        }
+//        ip = request.getHeader("X-Real-IP");
+//        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
+//            return ip;
+//        }
+//        return request.getRemoteAddr();
+//    }
+//
+//    private void logRequest(ContentCachingRequestWrapper request) {
+//        String traceId = MDC.get("traceId");
+//        String uri     = request.getRequestURI();
+//        String query   = request.getQueryString();
+//        String method  = request.getMethod();
+//        String body    = extractBody(request.getContentAsByteArray(), request.getContentType());
+//
+//        if (logHeaderProperties.isEnabled()) {
+//            String headers = extractHeaders(request);
+//            log.info(">>> [{}] {} {}{} | headers={} | body={}",
+//                    traceId, method, uri,
+//                    query != null ? "?" + query : "",
+//                    headers, body);
+//        } else {
+//            log.info(">>> [{}] {} {}{} | body={}",
+//                    traceId, method, uri,
+//                    query != null ? "?" + query : "",
+//                    body);
+//        }
+//    }
+//
+//    private String extractHeaders(HttpServletRequest request) {
+//        List<String> names = logHeaderProperties.getNames();
+//        StringBuilder sb = new StringBuilder("{");
+//        boolean first = true;
+//        if (names != null && !names.isEmpty()) {
+//            // 只打印配置的请求头
+//            for (String name : names) {
+//                String value = request.getHeader(name);
+//                if (value != null) {
+//                    if (!first) sb.append(", ");
+//                    first = false;
+//                    sb.append(name).append("=").append(value);
+//                }
+//            }
+//        } else {
+//            // 未配置则打印全部请求头
+//            Enumeration<String> headerNames = request.getHeaderNames();
+//            while (headerNames != null && headerNames.hasMoreElements()) {
+//                String name = headerNames.nextElement();
+//                String value = request.getHeader(name);
+//                if (!first) sb.append(", ");
+//                first = false;
+//                sb.append(name).append("=").append(value);
+//            }
+//        }
+//        return sb.append("}").toString();
+//    }
+//
+//    private void logResponse(ContentCachingResponseWrapper response, long cost) {
+//        String traceId = MDC.get("traceId");
+//        int    status  = response.getStatus();
+//        String body    = extractBody(response.getContentAsByteArray(), response.getContentType());
+//
+//        log.info("<<< [{}] status={} cost={}ms | body={}",
+//                traceId, status, cost, body);
+//    }
+//
+//    private String extractBody(byte[] bodyBytes, String contentType) {
+//        if (bodyBytes == null || bodyBytes.length == 0) {
+//            return "";
+//        }
+//        if (!isLoggableContentType(contentType)) {
+//            return "[binary, " + bodyBytes.length + " bytes]";
+//        }
+//        String body = new String(bodyBytes, StandardCharsets.UTF_8);
+//        if (body.length() > MAX_BODY_LENGTH) {
+//            body = body.substring(0, MAX_BODY_LENGTH) + "...(truncated)";
+//        }
+//        return body;
+//    }
+//
+//    private boolean isLoggableContentType(String contentType) {
+//        if (contentType == null) return true;
+//        String ct = contentType.toLowerCase();
+//        return LOGGABLE_CONTENT_TYPES.stream().anyMatch(ct::contains);
+//    }
+//}

--
Gitblit v1.7.1