Filter
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 打印所有请求头信息的拦截器
*/
@Component
public class HeaderLogInterceptor implements HandlerInterceptor {
private static final Logger log = LoggerFactory.getLogger(HeaderLogInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
java.util.Enumeration<String> headerNames = request.getHeaderNames();
StringBuilder sb = new StringBuilder();
sb.append("\n\n");
sb.append("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
sb.append("┃ 🚀 请求头信息(HeaderLog)开始 🚀\n");
sb.append("┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
sb.append(String.format("┃ 📍 请求地址 : %-30s\n", request.getRequestURI()));
String queryString = request.getQueryString();
if (queryString == null || queryString.isEmpty()) {
sb.append("┃ 📝 请求参数 : 无\n");
} else {
sb.append("┃ 📝 请求参数:\n");
String[] params = queryString.split("&");
for (String param : params) {
String[] kv = param.split("=", 2);
String key = kv[0];
String value = kv.length > 1 ? kv[1] : "";
sb.append(String.format("┃ • %-18s = %s\n", key, value));
}
}
sb.append("┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
String headerValue = request.getHeader(headerName);
sb.append(String.format("┃ 🌟 %-20s : %-30s\n", headerName, headerValue));
}
sb.append("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
sb.append("\n");
LogContextHolder.set(sb);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, org.springframework.web.servlet.ModelAndView modelAndView) throws Exception {
// 如果有需要可以在这里处理响应内容
}
}package com.investoday.boot.interceptor.log;
/**
* 用于在一次请求内传递日志内容,实现日志合并输出
*/
public class LogContextHolder {
private static final ThreadLocal<StringBuilder> LOG_HOLDER = new ThreadLocal<>();
public static void set(StringBuilder sb) {
LOG_HOLDER.set(sb);
}
public static StringBuilder get() {
return LOG_HOLDER.get();
}
public static void clear() {
LOG_HOLDER.remove();
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 打印响应体内容的 Filter
*/
@Component
@Order(Ordered.LOWEST_PRECEDENCE - 10)
public class ResponseLogFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(ResponseLogFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (!(response instanceof HttpServletResponse) || !(request instanceof HttpServletRequest)) {
chain.doFilter(request, response);
return;
}
ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, responseWrapper);
byte[] respBytes = responseWrapper.getResponseData();
String respBody = new String(respBytes, response.getCharacterEncoding());
StringBuilder sb = LogContextHolder.get();
if (sb == null) sb = new StringBuilder();
sb.append("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
sb.append("┃ 🎁 响应体内容(ResponseLog)\n");
sb.append("┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
sb.append(respBody);
sb.append("\n┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
log.info(sb.toString());
LogContextHolder.clear();
response.getOutputStream().write(respBytes);
}
}
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
// 自定义响应包装器,用于缓存响应体内容
public class ResponseWrapper extends HttpServletResponseWrapper {
// 用于缓存响应数据的字节输出流
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
// Servlet 输出流对象
private ServletOutputStream out = null;
// 字符输出流对象
private PrintWriter writer = null;
// 构造方法,传入原始 HttpServletResponse
public ResponseWrapper(HttpServletResponse response) {
super(response);
}
// 重写 getOutputStream 方法,返回自定义的 ServletOutputStream
@Override
public ServletOutputStream getOutputStream() throws IOException {
// 如果还没有创建输出流
if (out == null) {
out = new ServletOutputStream() {
// 判断流是否就绪,这里直接返回 true
@Override
public boolean isReady() { return true; }
// 设置写监听器,这里不做处理
@Override
public void setWriteListener(WriteListener writeListener) {}
// 实际写入数据到 buffer
@Override
public void write(int b) throws IOException { buffer.write(b); }
};
}
return out;
}
// 重写 getWriter 方法,返回自定义的 PrintWriter
@Override
public PrintWriter getWriter() throws IOException {
// 如果还没有创建 writer
if (writer == null) {
// 包装 buffer
writer = new PrintWriter(buffer, true);
}
return writer;
}
// 获取缓存的响应数据
public byte[] getResponseData() {
return buffer.toByteArray();
}
}