重新连接TCP发送握手的Spring集成

重新连接TCP发送握手的Spring集成,tcp,spring-integration,Tcp,Spring Integration,我正在尝试使用TcpSendingMessageHandler上的ClientMode自动重新连接。此连接需要保持打开状态,因此实现重新连接功能非常重要 private MessageChannel createNewSubflow(Message<?> message) { String host = (String) message.getHeaders().get("host"); Integer port = (Intege

我正在尝试使用TcpSendingMessageHandler上的ClientMode自动重新连接。此连接需要保持打开状态,因此实现重新连接功能非常重要

private MessageChannel createNewSubflow(Message<?> message) {
        String host = (String) message.getHeaders().get("host");
        Integer port = (Integer) message.getHeaders().get("port");
        Assert.state(host != null && port != null, "host and/or port header missing");
        String hostPort = host + port;

        TcpNetClientConnectionFactory cf = new TcpNetClientConnectionFactory(host, port);
        TcpReceivingChannelAdapter messageHandler = new TcpReceivingChannelAdapter();
        cf.setLeaveOpen(true);
        TcpConnectionInterceptorFactoryChain fc = new TcpConnectionInterceptorFactoryChain();

        HelloWorldInterceptorFactory factory = new HelloWorldInterceptorFactory();
        fc.setInterceptors(new TcpConnectionInterceptorFactory[] { factory} );

        cf.setInterceptorFactoryChain(fc);
        cf.setDeserializer(new CustomSerializerDeserializer());
        messageHandler.setErrorChannel(errorChannel);
        messageHandler.setConnectionFactory(cf);
        messageHandler.setOutputChannel(outputChannel);
        TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
        handler.setConnectionFactory(cf);
        handler.setClientMode(true);
        handler.setRetryInterval(5000);
        IntegrationFlow flow = f -> f.handle(handler);
        IntegrationFlowContext.IntegrationFlowRegistration flowRegistration =
                this.flowContext
                        .registration(flow)
                        .addBean(cf)
                        .id(hostPort + ".flow")
                        .register();
        MessageChannel inputChannel = flowRegistration.getInputChannel();
        this.subFlows.put(hostPort, inputChannel);
        return inputChannel;
    }

由于工厂未正确初始化,拦截器发出警告

您还需要为拦截器工厂添加
.addBean()

编辑

正如在评论中提到的,拦截器的另一种选择就是使用事件侦听器

我刚刚用这个进行了测试,没有发现任何问题:

@springboot应用程序
公共类SO65899947应用程序{
公共静态void main(字符串[]args){
SpringApplication.run(So65899947Application.class,args);
}
@豆子
公共集成流(){
返回f->f.handle(Tcp.outboundAdapter(Tcp.netClient(“localhost”,1234))
.clientMode(真)
.retryInterval(5000));
}
}
@组成部分
类初始发件人{
私有最终集成流;
InitialSender(集成流){
这个。流量=流量;
}
@事件监听器
已打开公共作废(TcpConnectionOpenEvent事件){
this.flow.getInputChannel(),
Collections.singletonMap(IpHeaders.CONNECTION_ID,event.getConnectionId());
}
}
EDIT2

当我将其更改为使用网关时,也得到了相同的结果

@springboot应用程序
@集成组件扫描
公共类SO65899947应用程序{
公共静态void main(字符串[]args){
SpringApplication.run(So65899947Application.class,args);
}
@豆子
公共集成流(){
返回f->f.handle(Tcp.outboundAdapter(Tcp.netClient(“localhost”,1234))
.clientMode(真)
.retryInterval(5000));
}
}
@MessagingGateway(defaultRequestChannel=“flow.input”)
接口门{
无效握手(@Payload String message,@Header(IpHeaders.CONNECTION_ID)String conn);
}
@组成部分
类初始发件人{
私人终场门;
初始发送器(闸门){
this.gate=gate;
}
@事件监听器
已打开公共作废(TcpConnectionOpenEvent事件){
this.gate.handShake(“你好,event.getConnectionId());
}
}

我为多个连接创建TcpNetClientConnectionFactory动态。一切正常,包括使用网关发送握手消息时的拦截。我希望在恢复连接套接字后再次自动发送此握手消息。我没有注意到
addBean()
,并且侦听器发出了警告。问题是拦截器工厂没有使用事件发布服务器初始化。它也需要一个
addBean()
。这工作正常,我想我问错了问题。创建套接字时,我希望自动发送消息(这是握手)。那么,这可以做到吗?或者我可以订阅一个频道,以便收到套接字启动的通知吗?您不必使用拦截器,只需添加一个
@EventListener
方法来接收
TcpConnectionOpenEvent
s即可。对事件使用
getConnectionId()
,并使用
IpHeaders.connection\u id
标题中的连接id向出站适配器发送消息。我不知道有任何类似的问题;我只是测试了一下,服务器反弹了很多次,每次都重新连接。请参阅对我的答案的编辑。
HelloWorldInterceptor        : No publisher available to publish TcpConnectionOpenEvent [source=HelloWorldInterceptor
$ nc -l 1234
Hello there
^C

$ nc -l 1234
Hello there
^C

$ nc -l 1234
Hello there
^C

$ nc -l 1234
Hello there
^C

$ nc -l 1234
Hello there
^C