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
作为响应正文?
我不打算解释 map
和 flatMap
之间的区别,因为我已经在这里写了一个非常全面的解释:
上面代码中的问题是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));
我正在使用 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
作为响应正文?
我不打算解释 map
和 flatMap
之间的区别,因为我已经在这里写了一个非常全面的解释:
上面代码中的问题是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));