request 字节流只能读取一次

2021-08-22/2021-08-22
0 评论 141 浏览

问题描述:

当我们使用拦截器或者过滤器读取和 request 的字节流之后,controller 中的 @RequestBody 报错,提示 request body 为空。

因为 request 的字节流只能读取一次,我们需要把此字节流存储起来,使其可以多次读取,利用 HttpServletRequestWrapper 对 request 进行封装。

继承 HttpServletRequestWrapper

 1package com.rs.shiliu.filter;
 2
 3import org.springframework.util.StreamUtils;
 4
 5import javax.servlet.ReadListener;
 6import javax.servlet.ServletInputStream;
 7import javax.servlet.http.HttpServletRequest;
 8import javax.servlet.http.HttpServletRequestWrapper;
 9import java.io.BufferedReader;
10import java.io.ByteArrayInputStream;
11import java.io.IOException;
12import java.io.InputStreamReader;
13
14public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
15    private byte[] requestBody = null;
16
17    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
18        super(request);
19        requestBody = StreamUtils.copyToByteArray(request.getInputStream());
20    }
21
22    @Override
23    public ServletInputStream getInputStream() throws IOException {
24        ByteArrayInputStream inputStream = new ByteArrayInputStream(requestBody);
25        return new ServletInputStream() {
26            @Override
27            public boolean isFinished() {
28                return inputStream.available() == 0;
29            }
30
31            @Override
32            public boolean isReady() {
33                return true;
34            }
35
36            @Override
37            public void setReadListener(ReadListener readListener) {
38
39            }
40
41            @Override
42            public int read() throws IOException {
43                return inputStream.read();
44            }
45        };
46    }
47
48    @Override
49    public BufferedReader getReader() throws IOException {
50        return new BufferedReader(new InputStreamReader(getInputStream()));
51    }
52}

添加过滤器,替换 request

 1package com.rs.shiliu.filter;
 2
 3import org.slf4j.Logger;
 4import org.slf4j.LoggerFactory;
 5import org.springframework.stereotype.Component;
 6
 7import javax.servlet.*;
 8import javax.servlet.annotation.WebFilter;
 9import javax.servlet.http.HttpServletRequest;
10import java.io.IOException;
11
12@Component
13@WebFilter(urlPatterns = "/*")
14public class BodyReaderFilter implements Filter {
15    private static final Logger logger = LoggerFactory.getLogger(BodyReaderFilter.class);
16
17    @Override
18    public void init(FilterConfig filterConfig) throws ServletException {
19        Filter.super.init(filterConfig);
20    }
21
22    @Override
23    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
24        ServletRequest requestWrapper = null;
25        if (servletRequest instanceof HttpServletRequest) {
26            requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) servletRequest);
27        }
28        filterChain.doFilter(requestWrapper == null ? servletRequest : requestWrapper, servletResponse);
29    }
30
31    @Override
32    public void destroy() {
33        Filter.super.destroy();
34    }
35}

标题:request 字节流只能读取一次
作者:Rainsheep
地址:HTTPS://www.rainsheep.cn/articles/2021/08/22/1629610223095.html

评论
发表评论
       
       
取消