我有一个要尽快检索并返回的项目列表。
对于每个项目,我还需要检索详细信息,它们可能会在几秒钟后返回。
我当然可以使用HTTP网关创建两个不同的路由,并首先请求列表,然后请求详细信息。但是,我必须等到所有细节都到了。我想立即寄回清单,然后在收到详细资料后立即寄回。
更新
按照Artem Bilan的建议,我的流程将Flux作为有效载荷返回,它将作为Mono的项目列表与作为Flux的已处理项目合并。
请注意,以下示例通过调用toUpperCase
来模拟项目的详细处理;我的实际用例需要路由和拨出电话以获取每个项目的详细信息:
@Bean
public IntegrationFlow sseFlow() {
return IntegrationFlows
.from(WebFlux.inboundGateway("/strings/sse")
.requestMapping(m -> m.produces(MediaType.TEXT_EVENT_STREAM_VALUE))
.mappedResponseHeaders("*"))
.enrichHeaders(Collections.singletonMap("aHeader", new String[]{"foo", "bar"}))
.transform("headers.aHeader")
.<String[]>handle((p, h) -> {
return Flux.merge(
Mono.just(p),
Flux.fromArray(p)
.map(t -> {
return t.toUpperCase();
// return detailsResolver.resolveDetail(t);
}));
})
.get();
}
那更接近我的目标。当我使用curl从该流中请求数据时,我立即获得了项目列表,稍后又获得了处理过的项目:
λ curl http://localhost:8080/strings/sse
data:["foo","bar"]
data:FOO
data:BAR
虽然仅将字符串转换为大写即可,但我很难用WebFlux.outboundGateway
进行详细信息的传出呼叫。上面注释掉的代码中的detailsResolver
定义如下:
@MessagingGateway
public interface DetailsResolver {
@Gateway(requestChannel = "itemDetailsFlow.input")
Object resolveDetail(String item);
}
@Bean
IntegrationFlow itemDetailsFlow() {
return f -> f.handle(WebFlux.<String>outboundGateway(m ->
UriComponentsBuilder.fromUriString("http://localhost:3003/rest/path/")
.path(m.getPayload())
.build()
.toUri())
.httpMethod(HttpMethod.GET)
.expectedResponseType(JsonNode.class)
.replyPayloadToFlux(false));
}
当我在detailsResolver
呼叫中注释并注释掉t.toUpperCase
时,outboundGateway
似乎已正确设置(日志显示订户存在,Demand发出信号),但从未得到回应(在ExchangeFunctions.exchange#91
中未达到断点)。
我通过从上下文中将其作为bean并调用其方法来确保DetailsResolver
本身正在工作-这使我得到了JsonNode响应。
可能是什么原因?
答案 0 :(得分:2)
是的,我不会在这里使用toReactivePublsiher()
,因为您拥有当前请求的上下文。每个请求都需要助焊剂。我会使用类似Flux.merge(Publisher<? extends I>... sources)
的东西,其中第一个Flux
用于项目,第二个用于每个项目的详细信息(类似Tuple2
)。
为此,您确实可以使用以下内容:
IntegrationFlows
.from(WebFlux.inboundGateway("/sse")
.requestMapping(m -> m.produces(MediaType.TEXT_EVENT_STREAM_VALUE)))
您的下游流应产生Flux
作为有效载荷以供回复。
在测试案例中,我有一个这样的样本:
@Bean
public IntegrationFlow sseFlow() {
return IntegrationFlows
.from(WebFlux.inboundGateway("/sse")
.requestMapping(m -> m.produces(MediaType.TEXT_EVENT_STREAM_VALUE))
.mappedResponseHeaders("*"))
.enrichHeaders(Collections.singletonMap("aHeader", new String[] { "foo", "bar", "baz" }))
.handle((p, h) -> Flux.fromArray((String[]) h.get("aHeader")))
.get();
}