当我在响应正文中返回值时,Spring WebFlux 抛出“生产者”类型未知

iKh*_*tib 14 kotlin spring-boot reactive spring-webflux

我正在使用带有 Kotlin 的 Spring Boot,现在尝试通过传递响应式服务的处理程序来从 GET 宁静服务中获取状态值。

我可以看到我传递的处理程序在请求中,但是每当我构建主体时,我都会收到此异常:

java.lang.IllegalArgumentException: 'producer' type is unknown to ReactiveAdapterRegistry
    at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException
Run Code Online (Sandbox Code Playgroud)

这是我的代码

@Bean
    fun getReceiptConversionStatus() = router {
        accept(MediaType.APPLICATION_JSON).nest {
            GET("/BsGetStatus/{handler}", ::handleGetStatusRequest)
        }
    }
    private fun handleGetStatusRequest(serverRequest: ServerRequest): Mono<ServerResponse> = ServerResponse
            .ok()
            .contentType(MediaType.APPLICATION_JSON)
            .body(GetStatusViewmodel(fromObject(serverRequest.pathVariable("handler"))), GetStatusViewmodel::class.java)
            .switchIfEmpty(ServerResponse.notFound().build())
Run Code Online (Sandbox Code Playgroud)

这就是我的视图模型:

data class GetStatusViewmodel(
        @JsonProperty("handler") val documentHandler: String
)
Run Code Online (Sandbox Code Playgroud)

Tho*_*olf 26

FluxMonos 是Producers。他们生产东西。您没有在producerbody 中传递 a这就是为什么会出现错误,它无法识别您正在传递的生产者,因为您正在传递 a GetStatusViewmodel

你的身体需要有型Mono<GetStatusViewmodel>。您可以替换bodybodyValue(它会自动为您包装它),或者您可以在将它传递给函数之前将其包装GetStatusViewodelMonousing 中。Mono#justbody

  • 只有在 Spring 生态系统中,这种事情才会是运行时错误而不是编译时错误! (7认同)

Ali*_*zan 20

对我来说,我正在做这样的事情:

webClient.post()
    .uri("/some/endpoint")
    .body(postRequestObj, PostRequest.class) // erroneous line 
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .bodyToMono(PostResponse.class)
    .timeout(Duration.ofMillis(5000))

Run Code Online (Sandbox Code Playgroud)

查看该函数的 springs 文档时,body()解释如下:

Variant of body(Publisher, Class) that allows using any producer that can be resolved to Publisher via ReactiveAdapterRegistry.

Parameters:
     producer - the producer to write to the request
     elementClass - the type of elements produced

Returns:
    this builder
Run Code Online (Sandbox Code Playgroud)

所以第一个参数不能只是任何对象,它必须是一个生产者。更改我上面的代码以将我的对象包裹在 Mono 中为我解决了这个问题。

webClient.post()
    .uri("/some/endpoint")
    .body(Mono.just(postRequestObj), PostRequest.class)
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .bodyToMono(PostResponse.class)
    .timeout(Duration.ofMillis(5000))

Run Code Online (Sandbox Code Playgroud)

参考:https : //docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.RequestBodySpec.html

  • 根据您的示例,您还可以使用“bodyValue”而不是“body”,它可以帮助您避免将对象包装到 **Mono** 中。相关行将类似于“bodyValue(postRequestObj)” (4认同)