在Spring Boot中使用Filter来记录请求和响应

  |   0 评论   |   0 浏览

背景

在Spring Boot中使用Filter来记录请求和响应

原理

默认的流是不支持重复读取的。这里可以使用下面这两个类,在读取的时候,同时会复制记录。

使用 ContentCachingRequestWrapperContentCachingResponseWrapper 来记录请求。

方法

package io.springcloud.demo.filter;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import lombok.extern.slf4j.Slf4j;

@Component
@WebFilter(urlPatterns = "/*")
@Order(-999)
@Slf4j
public class AccessLogFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        ContentCachingRequestWrapper req = new ContentCachingRequestWrapper(request);
        ContentCachingResponseWrapper resp = new ContentCachingResponseWrapper(response);

        // Execution request chain
        filterChain.doFilter(req, resp);
        
        // Get Cache
        byte[] requestBody = req.getContentAsByteArray();
        byte[] responseBody = resp.getContentAsByteArray();
        
        log.info("request body = {}", new String(requestBody, StandardCharsets.UTF_8));
        
        log.info("response body = {}", new String(responseBody, StandardCharsets.UTF_8));
        
        // Finally remember to respond to the client with the cached data.
        resp.copyBodyToResponse();
    }
}

参考

  1. How to Record Request and Response Bodies in Sping Boot Applications