@内容类型为application/x-www-form-urlencoded的RequestParam在Spring Boot 2.2中不起作用
从Spring Boot 2.1.10迁移到2.2.4后,下面的方法开始为@内容类型为application/x-www-form-urlencoded的RequestParam在Spring Boot 2.2中不起作用,spring,spring-boot,content-type,Spring,Spring Boot,Content Type,从Spring Boot 2.1.10迁移到2.2.4后,下面的方法开始为params参数返回null。它在Spring中不是一个bug,因为它在我制作一个小样本项目时起作用。 它也适用于没有内容类型的普通GET和POST:application/x-www-form-urlencoded @PostMapping(path = "/test", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) public void test(@R
params
参数返回null。它在Spring中不是一个bug,因为它在我制作一个小样本项目时起作用。
它也适用于没有内容类型的普通GET和POST:application/x-www-form-urlencoded
@PostMapping(path = "/test", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void test(@RequestParam Map<String, String> params) {
System.out.println(params);
}
任何帮助或想法都将不胜感激。另外,如果有人能告诉我Spring解析参数的地方,我可以试着调试,看看会发生什么 经过无数个小时的调试后,日志过滤器出现了问题。我是这样读请求的:
private static final class BufferedRequestWrapper extends HttpServletRequestWrapper {
private final byte[] buffer;
BufferedRequestWrapper(HttpServletRequest req) throws IOException {
super(req);
// Read InputStream and store its content in a buffer.
InputStream is = req.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int read;
while ((read = is.read(buf)) > 0) {
baos.write(buf, 0, read);
}
this.buffer = baos.toByteArray();
}
@Override
public ServletInputStream getInputStream() {
return new BufferedServletInputStream(new ByteArrayInputStream(this.buffer));
}
String getRequestBody() throws IOException {
return IOUtils.readLines(this.getInputStream(), StandardCharsets.UTF_8).stream()
.map(String::trim)
.collect(Collectors.joining());
}
}
这正在使用内容类型application/x-www-form-urlencoded
中的查询参数。我的解决方案是排除读取应用程序/x-www-form-urlencoded
的输入流
if (req.getContentType() == null || (req.getContentType() != null && !req.getContentType().startsWith("application/x-www-form-urlencoded"))) {
// Read InputStream and store its content in a buffer.
InputStream is = req.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int read;
while ((read = is.read(buf)) > 0) {
baos.write(buf, 0, read);
}
this.buffer = baos.toByteArray();
} else {
buffer = new byte[0];
}
经过无数个小时的调试,结果证明这是日志过滤器中的一个问题。我是这样读请求的:
private static final class BufferedRequestWrapper extends HttpServletRequestWrapper {
private final byte[] buffer;
BufferedRequestWrapper(HttpServletRequest req) throws IOException {
super(req);
// Read InputStream and store its content in a buffer.
InputStream is = req.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int read;
while ((read = is.read(buf)) > 0) {
baos.write(buf, 0, read);
}
this.buffer = baos.toByteArray();
}
@Override
public ServletInputStream getInputStream() {
return new BufferedServletInputStream(new ByteArrayInputStream(this.buffer));
}
String getRequestBody() throws IOException {
return IOUtils.readLines(this.getInputStream(), StandardCharsets.UTF_8).stream()
.map(String::trim)
.collect(Collectors.joining());
}
}
这正在使用内容类型application/x-www-form-urlencoded
中的查询参数。我的解决方案是排除读取应用程序/x-www-form-urlencoded
的输入流
if (req.getContentType() == null || (req.getContentType() != null && !req.getContentType().startsWith("application/x-www-form-urlencoded"))) {
// Read InputStream and store its content in a buffer.
InputStream is = req.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int read;
while ((read = is.read(buf)) > 0) {
baos.write(buf, 0, read);
}
this.buffer = baos.toByteArray();
} else {
buffer = new byte[0];
}
添加另一个答案,因为我遇到了相同的问题,但以不同的方式解决了它 我也有一个请求日志过滤器,它以Jonas Pedersen在回答中描述的类似方式包装传入请求并缓存响应输入流。Spring Boot已从2.1.2.RELEASE更新为2.3.4.RELEASE 我将传入请求包装在缓存输入流的缓存请求包装器中。 对我来说,问题在于,由于某种原因(到目前为止还不知道),request.getParameterValue(字符串键)方法返回null,即使包装的请求显然有一个非空的参数映射。 简单地访问wrapped requests参数映射就解决了这个问题……非常奇怪 使用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,此版本有效(我删除了一些详细信息):
公共类CachingRequestWrapper扩展了HttpServletRequestWrapper{
私有最终字节[]cachedBody;
私有最终映射参数映射;
公共CachingRequestWrapper(HttpServletRequest请求)引发IOException{
超级(请求);
parameterMap=request.getParameterMap();//添加了另一个答案,因为我遇到了相同的问题,但以不同的方式解决了它
我也有一个请求日志过滤器,它以Jonas Pedersen在回答中描述的类似方式包装传入请求并缓存响应输入流
我将传入请求包装在缓存输入流的缓存请求包装器中。
对我来说,问题在于,由于某种原因(到目前为止还不知道),request.getParameterValue(字符串键)方法返回null,即使包装的请求显然有一个非空的参数映射。
简单地访问wrapped requests参数映射就解决了这个问题……非常奇怪
使用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,此版本有效(我删除了一些细节):
公共类CachingRequestWrapper扩展了HttpServletRequestWrapper{
私有最终字节[]cachedBody;
私有最终映射参数映射;
公共CachingRequestWrapper(HttpServletRequest请求)引发IOException{
超级(请求);
parameterMap=request.getParameterMap();//POST和request参数?没有看到…可能是您应该查找servlet api的实现…但这似乎不是一个错误。POST和request参数?没有看到…可能是您应该查找servlet api的实现…但这似乎不是一个错误。感谢您发布此消息,它为我指出了正确的方向方向,尽管我以不同的方式解决了它。感谢你发布这篇文章,它为我指明了正确的方向,尽管我以不同的方式解决了它。