解决springboot只能获取一次post请求的body数据
自定义一个类继承 HttpServletRequestWrapper
HttpServletRequestWrapper 类可以用来做关键字过滤器,因为post提交的请求是以流的形式存放,所以获取也需要以流方式获取,但是如果在拦截器中直接获取,那么在controller中将无法在获取第二次,因为流的指针无法回到最初的位置。所以使用此类就可以解决此类问题。原理是将内容以流的形式获取后,在将内容以流的形式存放进request请求中。
import com.jgmes.base.utils.JgmesFilterSpecialCharUtil;
import org.apache.commons.lang.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
import java.util.List;
/**
* @author Zh
* @version v1.0
* @description:
* @date 2020/8/6 19:07
*/
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
String sessStr = getBody(request);
this.body = sessStr.getBytes(Charset.forName("UTF-8"));
}
/**
* 获取body
* @param request
* @return
* @throws IOException
*/
public String getBody(HttpServletRequest request) throws IOException {
StringBuffer stringBuffer = new StringBuffer();
InputStream inputStream = request.getInputStream();
BufferedReader reader = null;
String line = "";
while ((line = reader.readLine()) != null){
stringBuffer.append(line);
}
try{
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
}catch (Exception e){
throw e;
}finally {
reader.close();
}
String param = stringBuffer.toString();
filterIllegal(param);
return param;
}
/**
* 过滤特殊字符 自定义方法
* @param param
*/
public void filterIllegal(String param){
List<String> illegalStrings = JgmesFilterSpecialCharUtil.existsSpecialChar(param);
if(illegalStrings != null && illegalStrings.size() > 0){
String illegalString = StringUtils.join(illegalStrings.toArray(), ",");
throw new RuntimeException("非法字符被拦截:"+ illegalString);
}
}
/**
* 输出流
* @return
* @throws IOException
*/
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
/**
* 重写 输入流
* @return
*/
@Override
public ServletInputStream getInputStream(){
final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return inputStream.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return inputStream.read();
}
};
}
}
创建一个拦截器
import com.alibaba.fastjson.JSONObject;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
/**
* @author Zh
* @version v1.0
* @description:
* @date 2020/8/5 16:21
*/
@WebFilter(filterName = "specialCharFilter", urlPatterns = {"/base-form-template-data/*", "/base-form-template/*", "/base-table/*"})
public class specialCharFilter implements Filter {
private BodyReaderHttpServletRequestWrapper wrapper;
/**
* 初始化拦截器
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化过滤器");
}
/**
* 进行拦截操作
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
// 在wrapper中过滤post请求
wrapper = new BodyReaderHttpServletRequestWrapper(request);
// 过滤get请求
filterGetSpace(request);
filterChain.doFilter(wrapper, servletResponse);
}
/**
* 过滤get请求
* @param request
*/
public void filterGetSpace(HttpServletRequest request){
Map param = request.getParameterMap();
String paramStr = JSONObject.toJSONString(param);
wrapper.filterIllegal(paramStr);
}
/**
* 拦截器销毁
*/
@Override
public void destroy() {
}
}