Spring boot CharacterStreamReadingMessageSource.stdin()和EOF

Spring boot CharacterStreamReadingMessageSource.stdin()和EOF,spring-boot,spring-integration,Spring Boot,Spring Integration,我正在spring集成流中使用CharacterStreamReadingMessageSource: IntegrationFlows.from(CharacterStreamReadingMessageSource.stdin()) 它起作用了。问题是,如果我将文件通过管道传输到进程: cat file | java -jar app.jar 或 java-jarapp.jar

我正在spring集成流中使用
CharacterStreamReadingMessageSource

IntegrationFlows.from(CharacterStreamReadingMessageSource.stdin())
它起作用了。问题是,如果我将文件通过管道传输到进程:

cat file | java -jar app.jar

java-jarapp.jar

读取文件后,EOF不会传播,stdin仍处于活动状态,进程不会结束。我能做些什么让它这样做吗?在命令行上手动输入
ctrl-Z
,按预期工作,关闭应用程序(Spring boot应用程序,无web)。

不幸的是,它在该场景中不起作用;它是为控制台输入而设计的

CharacterStreamReadingMessageSource
系统包装在
BufferedReader
中,并使用
readLine()
。由于
readLine()
阻塞,并且我们不想长时间占用线程,因此我们检查
reader.ready()
,如果没有数据或流关闭,它将返回false

它可能会为这个用例提供一个阻塞选项,但是当与真正的控制台一起使用时,它将永远阻塞

同时,您可以创建类的副本并更改
receive()

@Override
public Message<String> receive() {
    try {
        synchronized (this.monitor) {
//          if (!this.reader.ready()) {            // remove this
//              return null;
//          }
            String line = this.reader.readLine();
            if (line == null) {                    // add this
                ((ConfigurableApplicationContext) getApplicationContext()).close();
            }
            return (line != null) ? new GenericMessage<String>(line) : null;
        }
    }
    catch (IOException e) {
        throw new MessagingException("IO failure occurred in adapter", e);
    }
}
@覆盖
公共消息接收(){
试一试{
已同步(此.monitor){
//如果(!this.reader.ready()){//删除此
//返回null;
//          }
String line=this.reader.readLine();
如果(line==null){//添加此
((ConfigurableApplicationContext)getApplicationContext()).close();
}
返回(行!=null)?新建GenericMessage(行):null;
}
}
捕获(IOE异常){
抛出新的MessaginException(“适配器中发生IO故障”,e);
}
}
(删除就绪检查,并在EOF关闭上下文)


我打开了一个。

只是想补充一点,这个解决方案是有效的,但是人们应该意识到,在更复杂的流中,可能会有消息仍在被处理并通过流,当上下文关闭并且所有bean都被销毁时,这些消息将丢失。不知道如何优雅地避免这种情况。因此,我最终没有使用
字符streamreadingmessagesource
(有一个补丁),而是创建了我自己的
StdinReader
类,该类从实现
命令行运行程序的类调用,并将
ThreadPoolExecutor
自动连接以允许执行器关闭。
@Override
public Message<String> receive() {
    try {
        synchronized (this.monitor) {
//          if (!this.reader.ready()) {            // remove this
//              return null;
//          }
            String line = this.reader.readLine();
            if (line == null) {                    // add this
                ((ConfigurableApplicationContext) getApplicationContext()).close();
            }
            return (line != null) ? new GenericMessage<String>(line) : null;
        }
    }
    catch (IOException e) {
        throw new MessagingException("IO failure occurred in adapter", e);
    }
}