带有 Spring WebFlux 的 RestController:必需参数不存在

Posted

技术标签:

【中文标题】带有 Spring WebFlux 的 RestController:必需参数不存在【英文标题】:RestController with Spring WebFlux :Required parameter is not present 【发布时间】:2018-10-16 23:11:21 【问题描述】:

我用Spring WebFlux写了一个Rest Controller Demo,不能正常运行,源码如下:

@RestController
public class Demo
    @PostMapping(value = "test2")
    public Integer getHashCode(@RequestParam("parameters") String parameters)
        return parameters.hashCode();
    

我用Postman测试了一下,返回:


    "timestamp": "2018-05-07T07:19:05.303+0000",
    "path": "/test2",
    "status": 400,
    "error": "Bad Request",
    "message": "Required String parameter 'parameters' is not present"

依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.projectreactor</groupId>
        <artifactId>reactor-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

我用Spring boot(v2.0.1.RELEASE)写了同样的控制器demo,它可以正常运行。为什么在 Spring Webflux 中不能正常运行?

【问题讨论】:

如何在不更改http请求的情况下获得parameters值? 【参考方案1】:

作为described in the reference documentation,在请求参数方面,基于 Servlet 的应用程序 (Spring MVC) 和 Spring WebFlux 之间存在细微的行为差异。

在 Spring WebFlux 中,@RequestParam 只会绑定查询参数。在您的情况下,您的 HTTP 请求未提供此类查询参数,并且您的方法签名未将其标记为可选。

查看您的 Postman 屏幕截图,您似乎打算将 HTTP 表单数据绑定到该参数,那么您应该改为查看 command objects。

【讨论】:

我把代码改成public Integer getHashCode(@RequestParam("parameters") Optional&lt;String&gt; parameters),为什么parameters.isPresent()返回false? 您是否使用请求 URL 发送了查询参数? 如果我不发送带有请求URL的查询参数,还有其他方法可以正确响应请求吗? 如果您不发送查询参数,那么将该参数声明为可选是正确的方法。 我将其声明为可选,但 parameters.isPresent() 返回 false。【参考方案2】:

您可以将请求发布为 x-www-form-urlencoded 而不是 form-data 吗?我猜 Spring webflux 只接受查询参数而不是表单数据的请求参数。

更新: 我刚刚用 webflux 和 java 10 尝试了相同的代码。我可以清楚地得到正确的响应。所以 webflux 和表单数据没有任何影响。

【讨论】:

也会出现Required String parameter 'parameters' is not present 我试过你的代码,它按预期工作。能否重新检查一下你的代码和tomcat中部署的代码是否相同? 部署在tomcat中可以正常运行。你的代码部署在netty服务器上?@Karthik Netty started on port(s): 20000 Failed to handle request [POST http://localhost:20000/test2]: Response status 400 with reason "Required String parameter 'parameters' is not present" 否 :( Tomcat。这很奇怪,但我们归零到 Netty?为什么会有不同?什么版本的 netty?你能试试最新的吗?【参考方案3】:

正如@brian-clozel 在他的回答中提到的那样,Spring WebFlux 目前不支持@RequestParam 的表单数据和多部分绑定(有一个未解决的问题SPR-16190)。

另一种方法可能是注入ServerWebExchange 并访问其getFormData()

@PostMapping(value = "test2")
public Mono<Integer> getHashCode(ServerWebExchange exchange)
    return exchange.getFormData().map(formData -> 
        if (formData.containsKey("parameters")) 
            return formData.getFirst("parameters").hashCode();
         else 
            throw new ServerWebInputException("Required parameter 'parameters' is not present");
        
    );

(但说实话,使用@ModelAttribute 和表单数据专用模型类的方法看起来要容易得多)

【讨论】:

以上是关于带有 Spring WebFlux 的 RestController:必需参数不存在的主要内容,如果未能解决你的问题,请参考以下文章

带有 MultipartFile 的 Spring Webflux 415

带有 Spring WebFlux 的 RestController:必需参数不存在

带有 Spring 安全 webflux 的 Angular 6 被 CORS 阻止

Spring Security WebFlux - 带有身份验证的主体

带有 WebFlux 的 Spring Boot 总是在测试中抛出 403 状态

带有 Webflux 的 Spring Boot:请求的资源上不存在“Access-Control-Allow-Origin”标头