多次读取 HttpServletRequest 中 body

2019-01-05  本文已影响0人  candyleer

背景

通常情况下,HttpServletRequst 中的 body 内容只会读取一次,但是可能某些情境下可能会读取多次,由于 body 内容是以流的形式存在,所以第一次读取完成后,第二次就无法读取了,一个典型的场景就是 Filter 在校验完成 body 的内容后,业务方法就无法继续读取流了,导致解析报错

包装 Request

既然直接不行,那么我们是否可以用装饰器来修饰一下 request,使其可以包装读取的内容,供多次读取.比如

public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
    public String _body;

    public MultiReadHttpServletRequest(HttpServletRequest request) throws IOException {
        super(request);
        StringBuffer sBuffer = new StringBuffer();
        BufferedReader bufferedReader = request.getReader();
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            sBuffer.append(line);
        }
        _body = sBuffer.toString();

    }

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(_body.getBytes());
        return new ServletInputStream() {
            @Override
            public int read() {
                return byteArrayInputStream.read();
            }

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

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

            @Override
            public void setReadListener(ReadListener listener) {

            }
        };
    }

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

Filter中使用

@Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
       //...some validate stuff against request
        MultiReadHttpServletRequest requestWrapper = new MultiReadHttpServletRequest(request);
        filterChain.doFilter(request, response);
}
上一篇下一篇

猜你喜欢

热点阅读