request.getInputStream()只有读一次的解决办法

问题描述:

我们在基于http做接口间调用时,服务端通过request.getInputStream()获取客户端的请求,如果我们需要在这个请求真正到达方法前做一些数据的校验以及内容的判断时,我们会通过一个filter进行处理,但是在filter执行通过后,我们方法再次获取请求参数时值却为空。

产生原因:

request.getInputStream()只有读一次

解决方法:

我们使用HttpServletRequestWrapper来包装HttpServletRequest,在BodyReaderHttpServletRequestWrapper初始化时读取request中的InputStream数据,并将其以byte[]缓存其中,在filter中我们使用包装过的request对象

代码:(转自http://dditblog.com/itshare_529.html)

(1)BodyReaderHttpServletRequestWrapper类:

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper{

    private final byte[] body;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = HttpHelper.getBodyString(request).getBytes(Charset.forName("UTF-8"));
    }

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

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return bais.read();
            }

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

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

            @Override
            public void setReadListener(ReadListener readListener) {
            }
        };
    }

}

(2)HttpHelper类:

public class HttpHelper {
public static String getBodyString(ServletRequest request) {
    StringBuilder sb = new StringBuilder();
    InputStream inputStream = null;
    BufferedReader reader = null;
    try {
        inputStream = request.getInputStream();
        reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
        String line = "";
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return sb.toString();
}
}

(3)filter中调用:

public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) arg0;
    HttpServletResponse response = (HttpServletResponse) arg1;
    // 解决Controller中RequestBody流的二次读取
    ServletRequest requestWrapper = null;
    try{
        if (request instanceof HttpServletRequest) {
    requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
}
String reqBody=HttpHelper.getBodyString(requestWrapper);    //获取请求参数
}catch (Exception e) {
    logger.error("过滤器错误" + e.getMessage());
}
    arg2.doFilter(requestWrapper, response);

}

(4)目标方法中还是通过request.getInputStream()获取参数

你可能感兴趣的:(web开发)