Spring Webflux - "scanAvailable":正确

Spring Webflux - "scanAvailable": true

我正在使用 RouterFunction 在我的 Spring 启动应用程序中定义端点。我的服务 return 是 Mono<Object>,我想在调用端点时 return 结果。我还需要进行身份验证,所以我传递了一个 UserPrinciple 对象。

路由器

@Bean
RouterFunction<ServerResponse> router() {
    return route()
            .GET("/api/endpoint-name", this::getExample)
            .build();
}

private Mono<ServerResponse> getExample(ServerRequest request) {
    return ServerResponse.ok().body(fromPublisher(getUserPrincipal().map(service::getSomething), Object.class)).log();
}

private Mono<UserPrincipal> getUserPrincipal() {
    return ReactiveSecurityContextHolder.getContext()
            .map(ctx -> ctx.getAuthentication())
            .map(auth -> auth.getPrincipal())
            .map(UserPrincipal.class::cast);
}

服务

public Mono<Object> getSomething(UserPrincipal userPrincipal) {
    WebClient webClient = getWebClient(userPrincipal.getJwt());

    return webClient.get()
            .uri(uriBuilder -> uriBuilder.path("another/server/endpoint").build())
            .retrieve()
            .bodyToMono(Object.class);
}

端点正在return发送:

{
    "scanAvailable": true
}

这表明我将 Mono 传递到响应正文而不是传递结果。但是我使用了 fromPublisher 我认为可以解决这个问题。

我找不到任何示例,其中服务 return 是 Mono 并且路由正确 return 是 Mono 的结果。

如何正确传递 Mono/Flux 作为响应正文?

我不打算解释 mapflatMap 之间的区别,因为我已经在这里写了一个非常全面的解释:

上面代码中的问题是Object的return。并将Object的参数输入到某些函数中。第一个函数非常简单

Mono<UserPrincipal> = getUserPrincipal();

虽然第二个变得有点毛茸茸:

Mono<Mono<Object> value = getUserPrincipal().map(service::getSomething);

那么,为什么我们要得到一个嵌套的 Mono?,好吧,根据 api 得到一些 returns a Mono<Object>Map return是 Mono<R> 其中 R 是我们 return 从 getSomething.

然后我们将其粘贴到 fromPublisher 中,它将解开第一个 Mono 最终尝试序列化 Mono<Object> 导致奇怪的响应。

{
    "scanAvailable": true
}

这里的答案是更加密切地关注类型系统。 body 函数采用 Publisher(Mono 或 Flux),因此您不需要 fromPublisher 函数。

并且还将 map 更改为 flatMap,因为 flatMap 中的 return 类型是 publisher.

ServerResponse.ok()
    .body(getUserPrincipal()
    .flatMap(service::getSomething), Object.class));