日志中获取request中请求参数(url参数和body参数)------post获取请求body(二)

1.创建自定义过滤器

import com.jdcloud.apim.openapi.util.RequestWrapper;
import org.springframework.core.annotation.Order;

import javax.servlet.*;
import java.io.IOException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
//将过滤器注册到springboot的启动项中,顺序为第一个。这里有两种方法
//方法一:通过注解的方式
@Order(1)
@WebFilter(filterName = "httpServletRequestFilter", urlPatterns = "/*")
public class RequestReplacedFilter implements Filter {
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = null;
//        logger.debug("复制request.getInputStream流");
        if (request instanceof HttpServletRequest) {
            requestWrapper = new RequestWrapper((HttpServletRequest) request);
        }
         //获取request请求中的流,将取出来的字符串保存在缓存中,同时再将该字符串再次转换成流,然后把它放入到新request对象中。
        if (requestWrapper == null) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }

}


//方法二:在springboot的启动类中,添加如下代码:

        @Bean
        public FilterRegistrationBean httpServletRequestReplacedRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new HttpServletRequestReplacedFilter());
            registration.addUrlPatterns("/*");
            registration.addInitParameter("paramName", "paramValue");
            registration.setName("httpServletRequestReplacedFilter");
            registration.setOrder(1);
            return registration;
        }

2.创建request请求的包装类,获取到body信息的同时,将该body信息在放入到新的request对象中,并返回。

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

public class RequestWrapper extends HttpServletRequestWrapper {
    private final byte[] body;

    public RequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = readBytes(request.getReader(), "utf-8");
    }

    @Override
    public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream(),"utf-8"));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {
            }

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }

    /**
 * 通过BufferedReader和字符编码集转换成byte数组
 * @param br
 * @param encoding
 * @return
 * @throws IOException
     */
    private byte[] readBytes(BufferedReader br, String encoding) throws IOException {
        String str = null;
        StringBuilder sb=new StringBuilder();
        while ((str = br.readLine()) != null) {
            sb.append(str);
        }
        return sb.toString().getBytes(Charset.forName(encoding));
    }
}

3.在日志的拦截器中,获取request中的body信息

public class LoggerInterceptor implements HandlerInterceptor {
     
private static Logger LOGGER = LoggerFactory.getLogger(LoggerInterceptor.class);

    //拦截器处理之前
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if(method.equals(HttpGet.METHOD_NAME)||method.equals(HttpDelete.METHOD_NAME)){
            requestParam=request.getQueryString();
        }else if(method.equals(HttpPost.METHOD_NAME)||method.equals(HttpPatch.METHOD_NAME)||method.equals(HttpPut.METHOD_NAME)){
            /**
             * 对来自后台的请求统一进行日志处理
             */
            RequestWrapper requestWrapper;
            if (request instanceof RequestWrapper) {
                // 签名处理过程 start....
                requestWrapper = (RequestWrapper) request;
                requestParam=getBodyString(requestWrapper);
                LOGGER.info("请求Body: {} ", requestParam);
                // 签名处理过程 end....
                }
        }

        return true;
    }


 @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        RequestWrapper requestWrapper;
        if (request instanceof RequestWrapper) {
            // 测试再次获取Body start....
            requestWrapper = (RequestWrapper) request;
            LOGGER.info("请求Body: {} ", getBodyString(requestWrapper)); // 测试再次获取Body end....
            }

    }

    private String getBodyString(HttpServletRequest request) throws IOException {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString().trim();
    }
}

至此,通过以上两篇文章即可实现获取request中的参数,实现在生产环境中日志可追溯的场景。以上是个人项目中的总结,有更好的方法欢迎大家留言。

猜你喜欢

转载自blog.csdn.net/bwt1989/article/details/83653065