参考:http://liwx2000.iteye.com/blog/1542431 和http://stackoverflow.com/questions/7318632/java-lang-illegalstateexception-getreader-has-already-been-called-for-this-re
原因:ServletRequest中getReader()和getInputStream()只能调用一次的解决办法
最近使用spring mvc做项目,数据格式是json,需要对请求参数中的密码解密,而请求的参数是整个RequestBody,Controller里是用过@RequestBody获取的。实现方法是通过一个Filter读取整个RequestBody并记录。但是这时就遇到一个问题,ServletRequest的getReader()和getInputStream()两个方法只能被调用一次,而且不能两个都调用。那么如果Filter中调用了一次,在Controller里面就不能再调用了
解决办法:
两个方法都注明方法只能被调用一次,由于RequestBody是流的形式读取,那么流读了一次就没有了,所以只能被调用一次。既然是因为流只能读一次的原因,那么只要将流的内容保存下来,就可以实现反复读取了。
实现方法:先将RequestBody保存为一个byte数组,然后通过Servlet自带的HttpServletRequestWrapper类覆盖getReader()和getInputStream()方法,使流从保存的byte数组读取。然后再Filter中将ServletRequest替换为ServletRequestWrapper。代码如下:
public class DecodeFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { ServletRequest requestWrapper = null; if(request instanceof HttpServletRequest) { requestWrapper = new MyHttpServletRequest((HttpServletRequest) request); } if(null == requestWrapper) { chain.doFilter(request, response); } else { chain.doFilter(requestWrapper, response); } } /** * getInputStream()和getReader() 都只能读取一次,由于RequestBody是流的形式读取,那么流读了一次就没有了,所以只能被调用一次。 * 先将RequestBody保存,然后通过Servlet自带的HttpServletRequestWrapper类覆盖getReader()和getInputStream()方法, * 使流从保存的body读取。然后再Filter中将ServletRequest替换为ServletRequestWrapper * @description * @author yuhy * @date 2015年12月9日 */ private class MyHttpServletRequest extends HttpServletRequestWrapper { private String _body; private HttpServletRequest _request; public MyHttpServletRequest(HttpServletRequest request) throws IOException { super(request); _request = request; StringBuffer jsonStr = new StringBuffer(); try (BufferedReader bufferedReader = request.getReader()) { String line; while ((line = bufferedReader.readLine()) != null) jsonStr.append(line); } //获取到提交测json,将密码解密后重新复制给requestBody JSONObject json = JSONObject.parseObject(jsonStr.toString()); json.put("trdPwd", DesUtil.decrypt(json.getString("trdPwd"),DesUtil.key)); _body = json.toJSONString(); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(_body.getBytes()); return new ServletInputStream() { public int read() throws IOException { return byteArrayInputStream.read(); } }; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(this.getInputStream())); } } @Override public void destroy() { // TODO Auto-generated method stub } }
时间: 2024-10-06 20:04:38