Spring Integration Java DSL动态TCP Server向客户端发消息问题
解决Spring Integration TCP Server模式错误及多端口动态集成流实现
首先,咱们先搞清楚你遇到的错误根源:你之前的代码里把Tcp.outboundAdapter和Tcp.netServer搭配使用了,这是完全错误的角色组合!
Tcp.netServer是TCP服务端连接工厂,它需要绑定一个入站端点来监听客户端的连接请求;而Tcp.outboundAdapter是为TCP客户端设计的,用来主动发起连接并发送数据。把服务端工厂塞给客户端适配器,自然会出现No listener bound to server connection factory的错误——服务端工厂根本没找到能处理连接的监听器,只能退出。
接下来给你一套正确的实现方案,满足你多端口、多队列对应独立集成流的需求:
核心思路
每个端口(比如1111对应queue1,2222对应queue2)需要一套独立的组件链:
- 一个
TcpNetServerConnectionFactory:监听指定端口,管理客户端连接 - 一个
TcpSendingMessageHandler:负责把JMS队列的消息发送到已连接的客户端 - 一条集成流:JMS入站适配器 → 通道 → TCP发送处理器
修正后的动态创建代码示例
假设你有一个包含端口、队列名、连接ID的HostConnection列表,循环创建每条集成流:
// 遍历所有需要创建的连接配置 for (HostConnection hostConnection : hostConnections) { int port = hostConnection.getPort(); String queueName = hostConnection.getQueueName(); String connectionId = hostConnection.getConnectionNumber(); // 1. 创建TCP服务端连接工厂,监听指定端口 TcpNetServerConnectionFactory serverFactory = Tcp.netServer(port) .serializer(customSerializer) .deserializer(customSerializer) .id(connectionId + "-tcp-server-factory") .soTimeout(10000) .get(); // 2. 创建TCP消息发送处理器,绑定服务端工厂 TcpSendingMessageHandler tcpSender = new TcpSendingMessageHandler(); tcpSender.setConnectionFactory(serverFactory); tcpSender.setId(connectionId + "-tcp-sender"); // 3. 构建集成流:从指定JMS队列取消息,发送到TCP客户端 IntegrationFlow flow = IntegrationFlows .from(Jms.inboundAdapter(connectionFactory()) .destination(queueName) .id(connectionId + "-jms-inbound-adapter")) .channel(MessageChannels.direct(connectionId + "-jms-to-tcp-channel")) .handle(tcpSender) .get(); // 4. 注册并启动这条集成流 FlowRegistration flowRegistration = this.flowContext.registration(flow) .id(connectionId + "-integration-flow") .register(); // 确保服务端工厂启动(如果上下文未自动触发) serverFactory.start(); }
关键注意事项
- 唯一ID标识:所有组件(连接工厂、适配器、通道、流)的ID都要带上
connectionId前缀,避免多流之间的ID冲突 - 连接管理:
TcpSendingMessageHandler会自动管理服务端的客户端连接,当外部VB应用连接上来后,后续JMS队列的消息会自动发送到该连接 - 单端口单客户端:如果你的场景是每个端口只对应一个外部应用,这个方案完全适用;如果需要支持多客户端连接同一端口,可以额外配置
TcpConnectionRouter来实现消息路由
验证步骤
- 启动Spring Boot应用后,用
netstat -ano(Windows)或ss -tulpn(Linux)检查1111、2222端口是否被监听 - 启动VB客户端连接对应端口,然后向queue1/queue2发送测试消息
- 查看日志,确认没有
No listener bound错误,并且能看到类似New connection from /xxx.xxx.xxx.xxx:xxxx to port xxxx的连接成功日志
内容的提问来源于stack exchange,提问作者shivam tiwari
相关产品推荐
相关产品推荐

