添加另一个答案,因为我遇到了同样的问题,但以不同的方式解决了它。
我也有一个请求日志过滤器,它以类似于 Jonas Pedersen 的回答中描述的方式包装传入请求并缓存响应输入流。 Spring Boot 从 2.1.2.RELEASE 更新到 2.3.4.RELEASE
我将传入请求包装在缓存输入流的缓存请求包装器中。
对我来说,问题是由于某些(目前未知)原因,request.getParameterValue(String key) 方法返回 null,即使包装的请求显然具有非空参数映射。
只需访问包装的请求参数映射就解决了我的问题......非常奇怪。
原始包装类,使用 Spring Boot 2.1.2.RELEASE:
public class CachingRequestWrapper extends HttpServletRequestWrapper {
private final byte[] cachedBody;
public CachingRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
InputStream requestInputStream = request.getInputStream();
this.cachedBody = StreamUtils.copyToByteArray(requestInputStream);
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new CachedInputStream(this.cachedBody);
}
@Override
public BufferedReader getReader() throws IOException {
ByteArrayInputStream byteArrayInputStream =
new ByteArrayInputStream(this.cachedBody);
String encoding = StringUtils.isEmpty(this.getCharacterEncoding())
? StandardCharsets.UTF_8.name()
: this.getCharacterEncoding();
return new BufferedReader(new InputStreamReader(byteArrayInputStream, encoding));
}
}
为了简洁,CachedInputStream 类的实现被省略了。
简单地访问打包的请求映射似乎解决了整个问题。对于 Spring Boot 2.3.4.RELEASE,此版本有效(我删除了一些细节):
public class CachingRequestWrapper extends HttpServletRequestWrapper {
private final byte[] cachedBody;
private final Map<String, String[]> parameterMap;
public CachingRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
parameterMap = request.getParameterMap(); // <-- This was the crucial part
InputStream requestInputStream = request.getInputStream();
this.cachedBody = StreamUtils.copyToByteArray(requestInputStream);
}
@Override
public Map<String, String[]> getParameterMap() {
return this.parameterMap; // this was added just to satisfy spotbugs
}
}
我没有费心去深入研究这个问题,所以我不能说两个 Spring Boot 版本之间发生了什么变化,或者在包装器构造函数中访问参数映射解决了什么问题。