核心是用filter拦截原始http流,通过contentcachingrequestwrapper/responsewrapper捕获未解析的json/xml等真实报文,结合路径白名单、脱敏处理、traceid追踪及结构化存储实现可查可控的日志。

Java 中记录第三方接口的入参和出参,核心在于捕获真实传输数据,而不是仅记录方法参数或返回对象。因为第三方调用走的是 HTTP 协议,实际入参可能是 JSON、表单、XML 等格式,响应体也是原始字节流;直接打印 Controller 方法参数(如 `@RequestBody User user`)会丢失原始结构、编码、空格、换行等关键信息,也不便于比对第三方发来的原始请求。
用 Filter 拦截原始请求/响应流
这是最可靠的方式,能拿到未经 Spring MVC 解析前的原始数据:
- 继承
OncePerRequestFilter,确保每个请求只执行一次 - 包装
HttpServletRequest和HttpServletResponse,重写getInputStream()和getWriter()/getOutputStream(),缓存读取内容 - 使用
ContentCachingRequestWrapper和ContentCachingResponseWrapper(Spring 自带)可大幅简化实现 - 注意:必须在日志打印前调用
filterChain.doFilter(),否则响应体尚未生成
按环境和路径动态开关日志
第三方接口日志量大、含敏感信息,不能无差别全开:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 配置项示例:
log.thirdparty.enable=true、log.thirdparty.paths=/api/v1/callback,/open/** - 在 Filter 中通过
request.getRequestURI()匹配路径白名单 - 测试环境默认开启,预发/生产环境默认关闭,重要回调接口可单独配置开启
- 避免对静态资源(.js/.css/.png)、健康检查(/actuator/health)等路径打日志
脱敏与格式化处理
原始参数可能含 token、密钥、手机号、身份证号等,必须脱敏后才能落日志:
- 对请求体和响应体做 JSON 解析后遍历字段,匹配关键词(如
password、idCard、mobile)并替换为*** - 不建议正则全局替换(易误伤),优先用 Jackson/Gson 反序列化再处理
- 日志中保留完整结构,例如:
{"username":"zhangsan","token":"***","amount":100} - 记录关键元数据:请求时间、耗时、HTTP 状态码、Remote IP、User-Agent、URL、Method
存储与排查建议
日志不仅要“打得出来”,还要“查得方便”:
- 每条日志加唯一
traceId(如用MDC.put("traceId", UUID.randomUUID().toString())),串联请求-响应-异常 - 数据库存日志时,建表包含
request_body(TEXT)、response_body(LONGTEXT)、status_code、cost_time_ms、create_time等字段 - ELK 场景下,用 Logstash 做字段提取(如
json{ source => "request_body" }),方便 Kibana 聚合分析 - 线上问题复现时,直接按
traceId或request_uri + timestamp快速定位原始报文
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










