Request请求体重新封装,解决请求体只能获取一次的问题
问题
在mvc架构中,经常会对接口进行拦截做一些权限校验,常用做法就是加入拦截器或过滤器,其中会提前获取post请求体,获取之后,controller方法上的参数就无法再获取的问题。
解决方案
定义一个ServletInputStreamWrapper
ServletInputStreamWrapper 是为了重新将请求体包装到HttpServletRequestWrapper中
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.IOException;
public class ServletInputStreamWrapper extends ServletInputStream {
private byte[] data;
private int idx = 0;
public ServletInputStreamWrapper(byte[] data) {
if (data == null) {
data = new byte[0];
}
this.data = data;
}
public int read() throws IOException {
return this.idx == this.data.length ? -1 : this.data[this.idx++] & 255;
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
}
定义一个过滤器,并对request进行包装
这里的目的就是为了重新包装新的request,并且要传入到新的请求中,因此,使用过滤器是最好的选择,拦截器完成此操作比较麻烦。实现 getInputStream() 、getContentLength() 、getContentLengthLong() 方法。在getInputStream()方法返回则是我们上一步定义的ServletInputStreamWrapper,构造方法中传入新请求体的byte[]即可。
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
/**
* 过滤器
*/
@Component
@WebFilter(filterName = "outAuthFilter", urlPatterns = {"/outer/*"})
public class OutAuthFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String requestBody = "";
try {
InputStream stream = request.getInputStream();
if (stream != null) {
requestBody = StreamUtils.copyToString(stream, Charset.forName("UTF-8"));
}
} catch (IOException e) {
//requestBody里面没有数据
System.out.println("requestBody里面没有数据");
return;
}
String newRequestBody ="{\"id\":\"1\",\"text\":\"新包装的JSON数据\"}";
final byte[] reqBodyBytes = newRequestBody.getBytes();
//对request进行重新包装
HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) {
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStreamWrapper(reqBodyBytes);
}
@Override
public int getContentLength() {
return reqBodyBytes.length;
}
@Override
public long getContentLengthLong() {
return reqBodyBytes.length;
}
};
// 将新request包装对象传入过滤器链中
filterChain.doFilter(requestWrapper, servletResponse);
}
@Override
public void destroy() {
}
}