有时候我们需要在拦截器中获取请求参数进行判断,普通表单提交的参数可以通过httpServletRequest.getParameterMap()获取,但是JSON数据需要从HttpServletRequest的流中读取。问题来了,HttpServletRequest的流只能读取一次,如果在拦截器中读取了流,那么继续向下执行到controller将无法获取到Json参数,同时会提示流已关闭。
解决方法:我们可以利用HttpServletRequestWrapper来包装HttpServletRequest,将请求体中的流copy一份,覆写getInputStream()和getReader()方法供外部使用,同时自己定义一个getRequestBody()方法,用于直接获取Json参数。每次调用覆写后的getInputStream()方法都是从复制出来的二进制数组中进行获取,这个二进制数组在对象存在期间一直存在,这样就实现了流的重复读取。
自定义包装类:public class RequestWrapper extends HttpServletRequestWrapper {
private final byte[] requestBody;
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
requestBody = StreamUtils.copyToByteArray(request.getInputStream());
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody);
return new ServletInputStream() {
public boolean isFinished() {
return false;
}
public boolean isReady() {
return false;
}
public void setReadListener(ReadListener readListener) {}
public int read() {
return byteArrayInputStream.read();
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getRequestBody() {
return new String(this.requestBody);
}
}
过滤器中启用包装类:
public class JsonFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//请求参数为JSON类型,则使用自定义包装
if(request instanceof HttpServletRequest
&& "application/json".equals(((HttpServletRequest)request).getHeader("Content-Type"))) {
chain.doFilter(new RequestWrapper((HttpServletRequest)request), response);
} else {
chain.doFilter(request, response);
}
}
public void destroy() {
}
}
拦截器中获取JSON参数:
public boolean repeatDataValidator(HttpServletRequest httpServletRequest) throws IOException {
String params = "";
if("application/json".equals(httpServletRequest.getHeader("Content-Type"))){
//通过方法直接获取JSON参数
params = ((RequestWrapper)httpServletRequest).getRequestBody();
}else {
params = JSONObject.toJSONString(httpServletRequest.getParameterMap());
}
..................自定义处理
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)