话不多说,先上大概的demo代码
Wrapper
public class TestWrapper extends HttpServletRequestWrapper {
private byte[] body;
public TestWrapper(HttpServletRequest request) throws IOException {
super(request);
body = StreamUtils.copyToByteArray(request.getInputStream());
}
...
}
Filter
public class TestFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
TestWrapper testWrapper = new TestWrapper((HttpServletRequest) servletRequest);
filterChain.doFilter(testWrapper,servletResponse);
}
}
由于之前的请求一直是json content-type的,所以没发现任何问题
这次在实现一个form content-type的请求时,发现getParameter or getParameterMap数据都为空。
大概Debug过程:
DispatchServletRequest#doService debug发现参数已丢失,那么在Servlet之前只有filter
TestWrapper 断点发现参数还在,但是wrapper后就丢失了
最后分析发现问题所在与request.getParameter实现有关,下面直接贴代码
//org.apache.catalina.connector.RequeseFacade#getParameter
public String getParameter(String name) {
if (!this.parametersParsed) {
this.parseParameters();
}
return this.coyoteRequest.getParameters().getParameter(name);
}
// parseParameters()
protected void parseParameters() {
this.parametersParsed = true;
Parameters parameters = this.coyoteRequest.getParameters();
boolean success = false;
...
try {
...
//如果input stream被用过,就直接return,不解析part
if (this.usingInputStream || this.usingReader) {
success = true;
return;
}
}
...
//没被调用,所以导致参数为空的原因
this.parseParts(false);
}
private void parseParts(boolean explicit) {
if (this.parts == null && this.partsParseException == null) {
...//重点在这里,parameters = this.coyoteRequest.getParameters(); 而getParameter最终是通过 return this.coyoteRequest.getParameters().getParameter(name); 获取参数
parameters.addParameter(name, value);
}
}
success = true;
} catch (InvalidContentTypeException var29) {
parameters.setParseFailedReason(FailReason.INVALID_CONTENT_TYPE);
this.partsParseException = new ServletException(var29);
} catch (SizeException var30) {
parameters.setParseFailedReason(FailReason.POST_TOO_LARGE);
this.checkSwallowInput();
this.partsParseException = new IllegalStateException(var30);
} catch (IOException var31) {
parameters.setParseFailedReason(FailReason.IO_ERROR);
this.partsParseException = new IOException(var31);
} catch (IllegalStateException var32) {
this.checkSwallowInput();
this.partsParseException = var32;
}
} finally {
if (this.partsParseException != null || !success) {
parameters.setParseFailedReason(FailReason.UNKNOWN);
}
}
}
}
看上面源码就知道原因出在哪了。
所以解决办法:
1、wrapper之前 先 调用下 getParameterMap or getParameter
2、按需wrapper吧~