spring - 内容类型为 application/x-www-form-urlencoded 的 @RequestParam 在 Spring Boot 2.2 中不起作用

标签 spring spring-boot content-type

从 Spring Boot 2.1.10 迁移到 2.2.4 后,以下方法开始为 params 返回 null范围。这不是 Spring 中的错误,因为当我制作一个小示例项目时它可以工作。
它也适用于没有 Content-Type: application/x-www-form-urlencoded 的普通 GET 和 POST。

@PostMapping(path = "/test", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void test(@RequestParam Map<String, String> params) {
    System.out.println(params);
}

我发出下面的请求,该请求在一个项目中有效,但在另一个项目中无效。我试图禁用所有过滤器和参数解析器,但没有任何效果。
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "param1=1&param2=2" http://localhost:8080/test

任何帮助或想法将不胜感激。另外,如果有人可以指出 Spring 解决参数的地方,我可以尝试调试并查看会发生什么。

最佳答案

添加另一个答案,因为我遇到了同样的问题,但以不同的方式解决了它。
我也有一个请求日志过滤器,它包装传入的请求并以类似于 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 版本之间发生了什么变化,或者访问包装器构造函数中的参数映射是什么解决了这个问题。

关于spring - 内容类型为 application/x-www-form-urlencoded 的 @RequestParam 在 Spring Boot 2.2 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60041700/

相关文章:

PHP Curl 和 headers 问题

python - 获取网页字符集的好用、可靠的快捷方式是什么?

spring - 为什么这个 Spring 映射没有注入(inject)到我的 Scala 对象中?

java - 为什么在 Autowiring 期间我的自定义注释记录 bean 为空?

java - 将spring boot maven项目作为依赖添加到另一个项目(本地)

spring - 如何使用 keycloak 和 spring 读取所有用户?

java - 添加WebSecurityConfigurerAdapter时Spring security默认登录表单消失

java - 无法 Autowiring 项目中的实体 Bean

spring-boot - Spring Cloud Netflix 和 Docker Compose - 无法使用 eureka 注册服务

php - 作为 View 结果的 drupal 7 内容类型字段