众所周知,request.getInputStream()只能调一次。如果希望在请求进入Controller之前统一打印请求参数(拦截器或过滤器),又不影响业务,我们只能将获取到的输入流缓存起来,后续都从缓存中获取即可。
首先,自定义一个ServletInputStream- package com.cjs.example.log.filter;
- import javax.servlet.ReadListener;
- import javax.servlet.ServletInputStream;
- import java.io.ByteArrayInputStream;
- import java.io.IOException;
- /**
- * @Author: ChengJianSheng
- * @Date: 2023/3/6
- */
- public class CustomServletInputStream extends ServletInputStream {
- private ByteArrayInputStream inputStream;
- public CustomServletInputStream(byte[] body) {
- this.inputStream = new ByteArrayInputStream(body);
- }
- @Override
- public boolean isFinished() {
- return inputStream.available() == 0;
- }
- @Override
- public boolean isReady() {
- return true;
- }
- @Override
- public void setReadListener(ReadListener readListener) {
- }
- @Override
- public int read() throws IOException {
- return inputStream.read();
- }
- }
复制代码 然后,自定义一个HttpServletRequestWrapper- package com.cjs.example.log.filter;
- import org.apache.commons.io.IOUtils;
- import javax.servlet.ServletInputStream;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletRequestWrapper;
- import java.io.*;
- /**
- * @Author: ChengJianSheng
- * @Date: 2023/3/6
- */
- public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
- private byte[] body;
- public CustomHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
- super(request);
- body = IOUtils.toByteArray(request.getInputStream());
- }
- @Override
- public ServletInputStream getInputStream() throws IOException {
- return new CustomServletInputStream(body);
- }
- @Override
- public BufferedReader getReader() throws IOException {
- return new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
- }
- }
复制代码 接下来,写一个过滤器,在过滤器中打印请求参数- package com.cjs.example.log.filter;
- import org.apache.commons.io.IOUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import javax.servlet.*;
- import javax.servlet.http.HttpServletRequest;
- import java.io.IOException;
- /**
- * @Author: ChengJianSheng
- * @Date: 2023/3/6
- */
- public class LogFilter implements Filter {
- private final static Logger logger = LoggerFactory.getLogger(LogFilter.class);
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
- CustomHttpServletRequestWrapper requestWrapper = new CustomHttpServletRequestWrapper((HttpServletRequest) servletRequest);
- printLog(requestWrapper);
- filterChain.doFilter(requestWrapper, servletResponse);
- }
- private void printLog(CustomHttpServletRequestWrapper requestWrapper) throws IOException {
- logger.info("请求URL: {}", requestWrapper.getRequestURL());
- String method = requestWrapper.getMethod();
- if ("GET".equalsIgnoreCase(method)) {
- logger.info("请求参数: {}", requestWrapper.getQueryString());
- } else if ("POST".equalsIgnoreCase(method) && "application/json".equalsIgnoreCase(requestWrapper.getContentType())) {
- String body = IOUtils.toString(requestWrapper.getInputStream(), requestWrapper.getCharacterEncoding());
- logger.info("请求参数: {}", body);
- }
- }
- }
复制代码 请求经过过滤器的时候,首先在构造CustomHttpServletRequestWrapper的时候将请求中的InputStream转成字节数字缓存到内存中,然后后面每次再getInputStream()的时候都从缓存中取出内容并返回一个新的ServletInputStream
最后,定义一个配置类- package com.cjs.example.log.config;
- import com.cjs.example.log.filter.LogFilter;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- /**
- * @Author: ChengJianSheng
- * @Date: 2023/3/6
- */
- @Configuration
- public class CustomLogAutoConfiguration {
- @Bean
- @ConditionalOnMissingBean
- public LogFilter logFilter() {
- return new LogFilter();
- }
- }
复制代码 在resources/META-INF/spring.factories中新增一行自动配置- org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.cjs.example.log.config.CustomLogAutoConfiguration
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |