【问题标题】:Spring WebFlux throws 'producer' type is unknow when I return value in the response body当我在响应正文中返回值时,Spring WebFlux 抛出“生产者”类型未知
【发布时间】:2020-02-19 11:24:51
【问题描述】:

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

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

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

这是我的代码:

@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())

这就是我的视图模型:

data class GetStatusViewmodel(
        @JsonProperty("handler") val documentHandler: String
)

【问题讨论】:

    标签: spring-boot kotlin spring-webflux reactive


    【解决方案1】:

    Flux 和 Monos 是 Producers。他们生产东西。您没有在正文中传递producer,这就是您收到错误的原因,它无法识别您传递的生产者,因为您传递的是GetStatusViewmodel。

    您的身体需要是Mono&lt;GetStatusViewmodel&gt; 类型。您可以将body 替换为bodyValue(它会自动为您包装),也可以使用Mono#just 将GetStatusViewodel 包装在Mono 中,然后再将其传递给body 函数。

    【讨论】:

    • syncBody 现已弃用
    • 只有在Spring生态中这种事情才会是运行时错误而不是编译时错误!
    【解决方案2】:

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

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

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

    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
    

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

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

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

    【讨论】:

    • 根据您的示例,您还可以使用bodyValue 代替body,它可以帮助您避免将对象包装成Mono。相关行看起来像bodyValue(postRequestObj)
    • @ValdèseKamdem 'bodyValue' 功能对我有用。
    【解决方案3】:

    我确实解决了它,我会在这里发布它,以防有人会犯我曾经犯过的错误:(对于使用 Java 的人来说,这是一个典型的错误,这是一个错误的导入.

    我在我的应用程序中使用了fromObject() 方法“我更新了问题以匹配我的实际代码”。你可以在这两个导入中找到这个函数,我使用了一个重载的 body() 函数来传递这个错误放置的函数:

    //this is the wrong import I was using
    import org.springframework.web.reactive.function.server.EntityResponse.fromObject
    //this is the correct one for building the mono body
    import org.springframework.web.reactive.function.BodyInserters.fromObject
    

    通过使用来自BodyInserters 的方法,您将能够将fromObject(T) 传递给body 方法,它会返回单声道结果​​。

    【讨论】:

      【解决方案4】:

      指定的代码解决了问题

      public Mono<ServerResponse> getName(ServerRequest request) {
      
          return ServerResponse.ok()
                  .contentType(MediaType.APPLICATION_JSON)
                  .bodyValue(birthday);
      
      }
      

      【讨论】:

        猜你喜欢
        • 2023-02-08
        • 1970-01-01
        • 2018-11-16
        • 1970-01-01
        • 2022-01-03
        • 2021-03-29
        • 1970-01-01
        • 2021-11-26
        • 2018-12-19
        相关资源
        最近更新 更多