ServletRequest中getReader()和getInputStream()只能调用一次的解决办法
最近使用spring mvc做项目,数据格式是json,有一个功能是实现记录请求的参数,而请求的参数是整个RequestBody,Controller里是用过@RequestBody获取的。实现方法是通过一个Filter读取整个RequestBody并记录。但是这时就遇到一个问题,ServletRequest的getReader()和getInputStream()两个方法只能被调用一次,而且不能两个都调用。那么如果Filter中调用了一次,在Controller里面就不能再调用了。查看了下ServletRequest的说明,如下:
/** * Retrieves the body of the request as binary data using * a {@link ServletInputStream}. Either this method or * {@link #getReader} may be called to read the body, not both. * * @returna {@link ServletInputStream} object containing * the body of the request * * @exception IllegalStateException if the {@link #getReader} method * has already been called for this request * * @exception IOException if an input or output exception occurred * */ public ServletInputStream getInputStream() throws IOException; /** * Retrieves the body of the request as character data using * a <code>BufferedReader</code>. The reader translates the character * data according to the character encoding used on the body. * Either this method or {@link #getInputStream} may be called to read the * body, not both. * * * @returna <code>BufferedReader</code> *containing the body of the request * * @exception UnsupportedEncodingException if the character set encoding * used is not supported and the *text cannot be decoded * * @exception IllegalStateException if {@link #getInputStream} method * has been called on this request * * @exception IOException if an input or output exception occurred * * @see #getInputStream * */ public BufferedReader getReader() throws IOException;
import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStreamReader;import javax.servlet.ServletInputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import jodd.JoddDefault;import jodd.io.StreamUtil;public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {private final byte[] body;public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {super(request);body = StreamUtil.readBytes(request.getReader(), JoddDefault.encoding);}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic int read() throws IOException {return bais.read();}};}}
public class HttpServletRequestReplacedFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {//Do nothing}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {ServletRequest requestWrapper = null;if(request instanceof HttpServletRequest) {requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);}if(null == requestWrapper) {chain.doFilter(request, response);} else {chain.doFilter(requestWrapper, response);}}@Overridepublic void destroy() {//Do nothing}}