Java请求日志记录封装器 | AI生成和翻译

Home 2025.09

在 Java Web 应用程序中,当你需要装饰或修改标准 HttpServletRequest 的行为而不触及 Servlet 容器的实现时,通常会使用 HttpServletRequestWrapper

HttpServletRequestWrapper 的工作原理

为何需要它来实现日志记录


示例:记录请求体和 URL 参数

以下是一个使用自定义包装器的过滤器:

public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
    private byte[] cachedBody;

    public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        InputStream requestInputStream = request.getInputStream();
        this.cachedBody = requestInputStream.readAllBytes();
    }

    @Override
    public ServletInputStream getInputStream() {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedBody);
        return new ServletInputStream() {
            @Override
            public int read() {
                return byteArrayInputStream.read();
            }
            @Override
            public boolean isFinished() {
                return byteArrayInputStream.available() == 0;
            }
            @Override
            public boolean isReady() {
                return true;
            }
            @Override
            public void setReadListener(ReadListener readListener) {}
        };
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    public String getBody() {
        return new String(this.cachedBody, StandardCharsets.UTF_8);
    }
}

在过滤器中的使用示例:

@WebFilter("/*")
public class LoggingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        CachedBodyHttpServletRequest wrappedRequest = new CachedBodyHttpServletRequest((HttpServletRequest) request);

        // 记录 URL
        String url = wrappedRequest.getRequestURL().toString();
        String query = wrappedRequest.getQueryString();

        // 记录参数
        Map<String, String[]> params = wrappedRequest.getParameterMap();

        // 记录请求体
        String body = wrappedRequest.getBody();

        System.out.println("请求 URL: " + url + (query != null ? "?" + query : ""));
        System.out.println("参数: " + params);
        System.out.println("请求体: " + body);

        // 继续过滤器链
        chain.doFilter(wrappedRequest, response);
    }
}

关键要点


需要我继续展示 Spring Boot 风格的解决方案吗(使用 OncePerRequestFilterContentCachingRequestWrapper)?这种实现方式会更加简洁。


Back Donate