具有 Spring WebFlux 的 RestController:所需参数不存在

RestController with Spring WebFlux :Required parameter is not present

我用SpringWebFlux写了一个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>

I wrote the same controller demo with Spring boot(v2.0.1.RELEASE), it can run correctly. Why can't it run correctly in Spring Webflux?

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

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

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

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

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

正如@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 和专用模型 class 处理表单数据的方法看起来容易得多)