Spring integration Spring反应式文件集成
我试图使用spring集成文件轮询一个目录,并从该目录中放置的文件创建一个反应流。这在很大程度上是有效的,但是当我放置一个文件但没有订户时,我会得到一个异常。为了演示这个问题,我编写了一个小型演示应用程序:Spring integration Spring反应式文件集成,spring-integration,reactive,Spring Integration,Reactive,我试图使用spring集成文件轮询一个目录,并从该目录中放置的文件创建一个反应流。这在很大程度上是有效的,但是当我放置一个文件但没有订户时,我会得到一个异常。为了演示这个问题,我编写了一个小型演示应用程序: import org.reactivestreams.Publisher; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootA
import org.reactivestreams.Publisher;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.Pollers;
import org.springframework.integration.file.dsl.Files;
import org.springframework.messaging.Message;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import java.io.File;
@SpringBootApplication
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public Publisher<Message<File>> reactiveSource() {
return IntegrationFlows
.from(Files.inboundAdapter(new File("."))
.patternFilter("*.csv"),
e -> e.poller(Pollers.fixedDelay(1000)))
.channel("processFileChannel")
.toReactivePublisher();
}
@GetMapping(value = "/files", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> files() {
return Flux.from(reactiveSource())
.map(message -> message.getPayload().getAbsolutePath());
}
}
我认为反应流的一个属性是,当没有订户时,流不会启动,因为流是惰性的。但显然情况并非如此。有人能解释一下,如果没有订阅者,我需要做什么才能使流不启动吗?如果您使用的是最新版本,那么您可以使用
FluxMessageChannel
频道,而不是DirectChannel
频道,用于processFileChannel
。这样一来,SourcePollingChannel
适配器将变为反应式,实际上,在订阅该FluxMessageChannel
之前,不会对源进行轮询
然后,您可以从此FluxMessageChannel
在文件()
API中创建Flux
——无需在.toReactivePublisher()中创建
请参阅文档中的更多内容:
关键是,.toReactivePublisher()
正是在这一点上作为发布者
进行了集成。这一点之前的一切都是以常规的、命令式的方式进行的,并且独立于下游逻辑
更新
大概是这样的:
@Bean
FluxMessageChannel filesChannel() {
return new FluxMessageChannel();
}
@Bean
public IntegrationFlow reactiveSource() {
return IntegrationFlows
.from(Files.inboundAdapter(new File("."))
.patternFilter("*.csv"),
e -> e.poller(Pollers.fixedDelay(1000)))
.channel(filesChannel())
.get();
}
@GetMapping(value = "/files", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> files() {
return Flux.from(filesChannel())
.map(message -> ((File) message.getPayload()).getAbsolutePath());
}
@Bean
FluxMessageChannel文件通道(){
返回新的FluxMessageChannel();
}
@豆子
公共集成流反应源(){
返回积分流
.from(Files.inboundAdapter(新文件(“.”))
.patternFilter(“*.csv”),
e->e.poller(Pollers.fixedDelay(1000)))
.channel(文件通道())
.get();
}
@GetMapping(value=“/files”,products=MediaType.TEXT\u EVENT\u STREAM\u value)
公共流量文件(){
从(filescannel())返回通量
.map(message->((文件)message.getPayload()).getAbsolutePath());
}
Hi Artem,非常感谢您的回复。你可以发布一些示例代码吗?我应该怎么做?我已经非常深入地阅读了文档,但我无法从中获得工作。谢谢在我的回答中看到更新。谢谢你,非常感谢!嗨,阿泰姆,如果可以的话,还有一个后续问题。我注意到,在我关闭订阅者后,例如通过终止curl调用,如果我在轮询目录中放置另一个csv文件,那么我再次收到相同的错误消息,即没有订阅者接受消息。似乎当客户端关闭其连接时,这并不意味着订阅被取消。你能告诉我怎么取消订阅吗?是的。。。这就是FluxMessageChannel
的实现方式:一旦订阅,直到应用程序结束才会取消。我们可能应该考虑在那里做些改进。。。请随意提出GH问题!
@Bean
FluxMessageChannel filesChannel() {
return new FluxMessageChannel();
}
@Bean
public IntegrationFlow reactiveSource() {
return IntegrationFlows
.from(Files.inboundAdapter(new File("."))
.patternFilter("*.csv"),
e -> e.poller(Pollers.fixedDelay(1000)))
.channel(filesChannel())
.get();
}
@GetMapping(value = "/files", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> files() {
return Flux.from(filesChannel())
.map(message -> ((File) message.getPayload()).getAbsolutePath());
}