美文网首页
解决request无法重复读取数据流问题

解决request无法重复读取数据流问题

作者: yuanjian | 来源:发表于2018-09-05 15:48 被阅读0次

    去年在开放中遇到过一个问题,因为项目重构,数据库等完全的重构,所以线上产生了两套环境。由于我们做的是开放平台,已经有很多开发者对接了,所以老的服务需要保留,一时间需要维护两套服务,老服务中很多应用遇到问题,无法修改应用信息,需要联系客服然后我们手动修改,非常麻烦。于是项目组决定将老的数据订正到新的表中,然后在老的服务中做一次向上的转发,如果失败了再走老的平台。所以需要重复读取HTTP请求的body数据,团队leader给了思路,写一个request的包装类,将读到的inputstream缓存到内存中,便可以重复读取。先上代码:

    
    import org.apache.commons.io.IOUtils;
    
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    /**
     * HttpServletRequestWrapper的包装类,用于重复读取inputStream
     *
     * Created by yuanjian on 10/17/17
     * @author liuyj@shinemo.com
     */
    public class InputStreamReadRepeatableRequestWrapper extends HttpServletRequestWrapper {
        private ServletInputStream inputStream;
        public InputStreamReadRepeatableRequestWrapper(HttpServletRequest request) {
            super(request);
        }
        @Override
        public ServletInputStream getInputStream() throws IOException {
            if (this.getContentLength() < 1) {
                return null;
            }
            if (this.inputStream == null) {
                this.inputStream = new InputStreamReadRepeatableRequestWrapper.ReadRepeatableInputStream(this.getRequest().getInputStream(), this.getRequest().getContentLength());
            }
            return inputStream;
        }
        private class ReadRepeatableInputStream extends ServletInputStream {
            private final ByteArrayInputStream bi;
            private ReadRepeatableInputStream(ServletInputStream inputStream, int length) throws IOException {
                if (length > 0) {
                    byte[] bytes = new byte[length];
                    IOUtils.read(inputStream, bytes, 0, length);
                    inputStream.read(bytes, 0, length);
                    bi = new ByteArrayInputStream(bytes, 0, length);
                } else {
                    bi = null;
                }
            }
            @Override
            public int read() throws IOException {
                int bt = -1;
                if (bi != null) {
                    bt = this.bi.read();
                    if (bt == -1) {
                        this.bi.reset();
                    }
                }
                return bt;
            }
            @Override
            public void reset() {
                this.bi.reset();
            }
            @Override
            public boolean isFinished() {
                return false;
            }
            @Override
            public boolean isReady() {
                return false;
            }
            @Override
            public void setReadListener(ReadListener readListener) {
    
            }
        }
    }
    

    然后新增一个filter

    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    /**
     * @author liuyj@shinemo.com
     */
    public final class RequestFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            InputStreamReadRepeatableRequestWrapper request = new InputStreamReadRepeatableRequestWrapper((HttpServletRequest) servletRequest);
            filterChain.doFilter(request, servletResponse);
        }
        @Override
        public void destroy() {
    
        }
    }
    
    

    最后只需要在web.xml中配置此filter即可。

    相关文章

      网友评论

          本文标题:解决request无法重复读取数据流问题

          本文链接:https://www.haomeiwen.com/subject/abmawftx.html