【问题标题】:How to dynamically create multiple TcpOutboundGateways using Spring Integration?如何使用 Spring Integration 动态创建多个 TcpOutboundGateways?
【发布时间】:2019-06-14 16:55:45
【问题描述】:

我有一个场景,我需要一个客户端应用程序才能在应用程序启动时动态创建与可变数量的唯一主机/端口组合的 TCP 连接。我正在尝试使用 Spring Integration TcpOutboundGateway 来完成此操作,但一直无法找到解决方案。我希望每个主机/端口组合都有自己专用的 TcpOutboundGateway。到目前为止,我对 TcpOutboundGateway 的研究使我找到了以下单一网关解决方案……

@MessageGateway(defaultRequestChannel=“sendMessage”)
public interface myMessageGateway {
    byte[] sendMessage(String message);
}

@Bean
@ServiceActivator(inputChannel=“sendMessage”)
public MessageHandler tcpOutboundGateway(AbstractClientConnectionFactory factory) {
    TcpOutboundGateway gateway = new TcpOutboundGateway();
    gateway.setConnectionFactory(factory);
    return gateway;
}

@Bean
public AbstractClientConnectionFactory clientConnectionFactory() {
    return new TcpNetClientConnectionFactory(“123.456.789.0”, 5555);
}

我的理解是调用 sendMessage 函数会将请求消息放在“sendMessage”通道上。然后,该通道会将其传递给 tcpOutboundGateway 服务激活器,该服务激活器将处理消息的发送,并最终将服务器的响应作为 sendMessage 函数的返回值返回。在单一的预定义服务器连接的情况下,此解决方案对我来说效果很好。

我的问题是如何以一种可以支持一组可变的唯一主机/端口的方式动态创建新的消息网关和服务激活器?更具体地说,@MessageGateway 和 @ServiceActivator 注释在后台为我们做了什么?我需要做什么才能复制该功能?

编辑:

所以经过一些试验后,我找到了这个似乎可以解决问题的解决方案......

// Define the Message Gateway without any annotations
public interface MyMessageGateway {
    byte[] sendMessage(String message);
}

...

// Use the GatewayProxyFactoryBean to replicate the functionality of the @MessageGateway annotation
// context is my instance of a ConfigurableApplicationContext
GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean(SenderGateway.class);
gpfb.setDefaultRequestChannel(“sendMessage”);
context.getBeanFactory().registerSingleton(“MyMessageGateway”, gpfb);
context.getBeanFactory().initializeBean(gpfb, “MyMessageGateway”);

// Create and register the ClientConnectionFactory Bean within the Application Context
AbstractClientConnectionFactory clientConnectionFactory = new TcpNetClientConnectionFactory(“123.456.789.0”, 5000);
context.getBeanFactory().registerSingleton(“ClientConnectionFactory”, clientConnectionFactory);
context.getBeanFactory().initializeBean(clientConnectionFactory, “ClientConnectionFactory”);

// Create and register the TcpOutboundGateway Bean within the Application Context
TcpOutboundGateway gateway = new TcpOutboundGateway();
gateway.setConnectionFactory(clientConnectionFactory);
context.getBeanFactory().registerSingleton(“TcpOutboundGateway”, tcpOutboundGateway);
context.getBeanFactory().initializeBean(tcpOutboundGateway, “TcpOutboundGateway”);

// Create and register the Request Channel to connect the Message Gateway and the TCP Outbound Gateway
// This should replicate the functionality of the @ServiceActivator annotation
DirectChannel sendMessage = new DirectChannel();
sendMessage.setBeanName(“sendMessage”);
context.getBeanFactory().registerSingleton(“sendMessage”, sendMessage);
context.getBeanFactory().initializeBean(sendMessage, “sendMessage”);

// Subscribe the TCP Outbound Gateway to the new Message Channel (sendMessage)
// This should replicate the functionality of the @ServiceActivator annotation
sendMessage.subscribe(tcpOutboundGateway);

// Start the ClientConnectionFactory
// This seems to be getting done automatically in the non-dynamic implementation above
clientConnectionFactory.start();

此实现允许消息通过消息网关和 TCP 出站网关以与上述带注释实现相同的方式发送(使用为 MyMessageGateway 接口定义的 sendMessage 函数)。我发现为了将这种方法用于多个主机/端口组合,您需要通过 context.getBeanFactory.getBean() 获取所需的消息网关。

我很好奇这种方法/实现是否有任何缺陷?

【问题讨论】:

    标签: java spring spring-boot tcp spring-integration


    【解决方案1】:

    唯一简单的方法是考虑使用 Spring Integration 提供的带有 Java DSL 的动态 IntegrationFlows:https://docs.spring.io/spring-integration/docs/current/reference/html/#java-dsl-runtime-flows

    我们还为类似的动态 TCP 客户端 用例提供了一个全面的示例:https://github.com/spring-projects/spring-integration-samples/tree/master/advanced/dynamic-tcp-client

    【讨论】:

    • Artem,您能否详细说明您提供的解决方案?我是 IntegrationFlow 的新手,无法完全理解您如何设想将其用于我的场景。如果可能的话,也许是一个示例/伪代码?我还注意到第一个示例使用了函数 convertAndSend,这使得在上面的示例中似乎不需要任何类似于 @MessageGateway 接口的东西。这是一个正确的假设吗?一旦我们为每个主机/端口组合创建并注册了 IntegrationFlow,我将如何引用它?它会成为 ApplicationContext 中的 bean 吗?
    • Artem - 另请参阅我对原始问题的编辑。认为我找到了可能的解决方案。
    • 你自己做了一些类似于我们在 IntegrationFlowContext 背后的框架中所做的事情。您仍然可以使用@MessagingGateway 为特定主机/端口发送消息,并从一些简单的缓存中选择适当的IntegrationFlow 进行交互。我认为我们提到的样本有足够的信息来借用您的请求/回复解决方案。虽然如果您对自己的感到满意,那也没关系:我们一开始也有类似的东西。
    猜你喜欢
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    相关资源
    最近更新 更多