Skip to content

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();
    }
}

✨ 网站运行时间: 3年11月15天 ❤️ 道阻且长,行则将至 - 微信号: heikedreamer