springboot利用filter获取request和response中的数据

package liu.hope.my_demo_boot.filter;

import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;

@Order(1)
@Component
@WebFilter(filterName = "webLogFilter", urlPatterns = "/*")
public class WebLogFilter implements Filter {
    private final static Logger logger = LoggerFactory.getLogger(WebLogFilter.class);
    private ThreadLocal<Long> threadLocal = new ThreadLocal<>();

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

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 包装request和response
        RequestWrapper requestWrapper = new RequestWrapper((HttpServletRequest) request);
        ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);
        // 获取request的相关数据
        logger.debug("请求URL : " + requestWrapper.getRequestURL().toString());
        logger.debug("请求参数 : " + requestWrapper.getBody());
        threadLocal.set(System.currentTimeMillis());
        chain.doFilter(requestWrapper, responseWrapper);
        // 获取response的相关数据
        logger.debug("响应数据 : " + new String(responseWrapper.getContent(), "UTF-8"));
        logger.debug("请求处理时间 : " + (System.currentTimeMillis() - threadLocal.get()) + "ms");
        // 在得到响应的数据之后,response的输出流中就无可用的数据,所以需要巴数据放回去
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(responseWrapper.getContent());
        outputStream.flush();
        outputStream.close();
    }

    @Override
    public void destroy() {
    }
}

class RequestWrapper extends HttpServletRequestWrapper {
    private String body;

    /**
     * Constructs a request object wrapping the given request.
     * @param request The request to wrap
     * @throws IllegalArgumentException if the request is null
     */
    public RequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        // 此处是得到请求内容的长度
        int contentLength = request.getContentLength();
        StringBuilder stringBuilder = new StringBuilder(contentLength);
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            // 输入流获取请求的数据
            inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[1024];
                int bytesRead;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            }
        } catch (IOException e) {
            throw e;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (bufferedReader != null) {
                bufferedReader.close();
            }
        }
        // 下面会把数据放回request的输入流中,所以要把数据恢复到与之前请求内容相同的长度
        body = String.format("%-" + contentLength + "s", JSONObject.parseObject(stringBuilder.toString()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        // 数据放到字节流中
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.getBody().getBytes());
        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 {
                // 数据放回request的输入流中
                return byteArrayInputStream.read();
            }
        };
    }

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

    public String getBody() {
        // 请求中的数据
        return this.body;
    }
}

class ResponseWrapper extends HttpServletResponseWrapper {
    private ByteArrayOutputStream byteArrayOutputStream;
    private ServletOutputStream servletOutputStream;

    /**
     * Constructs a response adaptor wrapping the given response.
     * @param response The response to be wrapped
     * @throws IllegalArgumentException if the response is null
     */
    public ResponseWrapper(HttpServletResponse response) throws IOException {
        super(response);
        byteArrayOutputStream = new ByteArrayOutputStream();
        servletOutputStream = new MyServletOutputStream(byteArrayOutputStream);
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return servletOutputStream;
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        return new PrintWriter(new OutputStreamWriter(byteArrayOutputStream, StandardCharsets.UTF_8));
    }

    @Override
    public void flushBuffer() {
        if (servletOutputStream != null) {
            try {
                servletOutputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public byte[] getContent() {
        flushBuffer();
        // response中的数据
        return byteArrayOutputStream.toByteArray();
    }

    class MyServletOutputStream extends ServletOutputStream {
        // 把response输出流中的数据写入字节流中
        private ByteArrayOutputStream byteArrayOutputStream;

        public MyServletOutputStream(ByteArrayOutputStream byteArrayOutputStream) {
            this.byteArrayOutputStream = byteArrayOutputStream;
        }

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

        @Override
        public void setWriteListener(WriteListener listener) {
        }

        @Override
        public void write(int b) throws IOException {
            byteArrayOutputStream.write(b);
        }
    }
}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
可以通过使用Spring Boot的过滤器(Filter)来实现请求和响应的压缩。具体步骤如下: 1. 在pom.xml添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.github.ziplet</groupId> <artifactId>ziplet-filter-servlet</artifactId> <version>2.1.2</version> </dependency> ``` 2. 在application.properties文件添加以下配置: ```properties server.compression.enabled=true server.compression.mime-types=application/json,application/xml,text/html,text/plain server.compression.min-response-size=1024 ``` 其,`server.compression.enabled`表示是否启用压缩,`server.compression.mime-types`表示需要压缩的内容类型,`server.compression.min-response-size`表示响应内容超过多少字节才压缩。 3. 创建一个过滤器类并实现Filter接口: ```java public class CompressionFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; if (isGzipSupported(httpRequest) && notAlreadyCompressed(httpResponse)) { GZIPResponseWrapper gzipResponse = new GZIPResponseWrapper(httpResponse); chain.doFilter(request, gzipResponse); gzipResponse.finish(); return; } chain.doFilter(request, response); } private boolean isGzipSupported(HttpServletRequest request) { String encoding = request.getHeader("Accept-Encoding"); return (encoding != null && encoding.contains("gzip")); } private boolean notAlreadyCompressed(HttpServletResponse response) { return (response.getHeader("Content-Encoding") == null); } // GZIPResponseWrapper类是对HttpServletResponse进行封装,实现GZIP压缩 private static class GZIPResponseWrapper extends HttpServletResponseWrapper { private GZIPOutputStream gzipOutputStream; public GZIPResponseWrapper(HttpServletResponse response) throws IOException { super(response); this.gzipOutputStream = new GZIPOutputStream(response.getOutputStream()); } @Override public ServletOutputStream getOutputStream() throws IOException { return new ServletOutputStream() { @Override public void write(int b) throws IOException { gzipOutputStream.write(b); } @Override public void flush() throws IOException { gzipOutputStream.flush(); super.flush(); } @Override public void close() throws IOException { gzipOutputStream.close(); super.close(); } }; } @Override public PrintWriter getWriter() throws IOException { return new PrintWriter(new OutputStreamWriter(gzipOutputStream, getResponse().getCharacterEncoding())); } } } ``` 4. 在Spring Boot应用程序的配置类添加一个FilterRegistrationBean,将上述过滤器类注册为过滤器: ```java @Configuration public class WebConfig { @Bean public FilterRegistrationBean<CompressionFilter> compressionFilter() { FilterRegistrationBean<CompressionFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new CompressionFilter()); registrationBean.addUrlPatterns("/*"); return registrationBean; } } ``` 完成以上步骤后,请求和响应的内容会被自动压缩。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值