参考: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
}
}request使用getReader()和getInputStream()获取请求参数报400错误
原文:http://4528195.blog.51cto.com/4518195/1721100