解决post请求无法多次获取inputstream的问题
问题
post请求在controller中通过request的getinputstream方法获取不到输入流
原因:
post的request当获取流或者获取参数之后,无法再次获取,可能是请求进来时在其他地方进行了数据读取,但是我在项目中没找到。
解决:
可以通过实现httpservletrequestwrapper 对request请求进行封装
package net.referee.config;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class MyRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public MyRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
ServletInputStream inputStream = request.getInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
byte[] b = new byte[10240];
int n;
while ((n = inputStream.read(b)) != -1) {
outputStream.write(b, 0, n);
}
} catch (Exception e) {
try {
inputStream.close();
outputStream.close();
} catch (Exception e1) {
}
}
body = outputStream.toString();
request.setAttribute("body",body); //将post的body数据放入缓存,这样子在后面就能够随时取用
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes());
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) {
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
包装之后在调用getinputstream时就会调用包装类的 方法。
这时候还有问题,因为包装之后并没有应用,因为我们找不到具体什么地方读取了post请求的内容,所以设置了过滤器让请求经过过滤器,并且将request替换成包装类这样就可以重复获取了。
package net.referee.config;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/*
此过滤器用于解决post请求无法重复获取参数的问题
*/
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
MyRequestWrapper req = new MyRequestWrapper((HttpServletRequest)servletRequest);
filterChain.doFilter(req,servletResponse);
}
@Override
public void destroy() {
}
}
这时候又有问题,这个过滤器怎么应用到项目中呢 ,我通过配置类将此过滤器注册,并且将其放到了最前方,请求一进来就会经过。
//将自定义的过滤器置于最前
@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
MyFilter myFilter1 = new MyFilter();
filterRegistrationBean.setFilter(myFilter1);
filterRegistrationBean.addUrlPatterns("/*");//配置过滤规则
filterRegistrationBean.setName("myFilter");//设置过滤器名称
filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);//执行次序
return filterRegistrationBean;
}