springboot框架对接物联网,配置TCP协议依赖,与设备通信,让TCP变的如此简单

最近在使用 Spring Boot 对接物联网设备,需要通过 TCP 协议进行通信。调研过程中发现,如果使用 Netty 框架并集成到 Spring Boot 中,配置和维护相对较为复杂。综合考虑后,最终选择了 Spring Integration 提供的 TCP/UDP 模块来实现相关功能,整体集成更加简洁,也更符合 Spring 生态的使用习惯。

第一步:

引入依赖

bash 复制代码
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-ip</artifactId>
</dependency>

第二步:

提供两个tcp服务端类文件,这两个类文件大家按需选择即可。

第一个类文件:

单向接收tcp客户端数据:

bash 复制代码
package com.testweb.testweb.tcp.web;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.ip.tcp.TcpReceivingChannelAdapter;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory;
import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;

import java.nio.charset.StandardCharsets;

@Slf4j
@Configuration
public class TcpServerConfig {

    @Value("${tcp.server.port:7788}")
    private int port;

    /**
     * 1. TCP 连接工厂(服务端)
     */
    @Bean
    public AbstractServerConnectionFactory serverConnectionFactory() {
        TcpNioServerConnectionFactory factory =
                new TcpNioServerConnectionFactory(port);

        // 关键:拆包 / 粘包解决方案(行结束符)
        // 按换行符 (\r\n 或 \n) 拆包,常用于文本协议
        ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer();

        // 二进制协议示例:长度头 + 消息内容(常用于物联网)
        // ByteArrayLengthHeaderSerializer serializer =
        //         new ByteArrayLengthHeaderSerializer();

        factory.setSerializer(serializer);
        factory.setDeserializer(serializer);
        factory.setUsingDirectBuffers(true);
        return factory;
    }

    /**
     * 2. 接收同步通道
     */
    @Bean
    public MessageChannel tcpReceiveChannel() {
        return new DirectChannel();
    }

    /**
     * 3. TCP 入站适配器(只接收)
     */
    @Bean
    public TcpReceivingChannelAdapter tcpInboundAdapter(
            AbstractServerConnectionFactory factory,
            MessageChannel tcpReceiveChannel) {

        TcpReceivingChannelAdapter adapter =
                new TcpReceivingChannelAdapter();
        adapter.setConnectionFactory(factory);
        adapter.setOutputChannel(tcpReceiveChannel);
        return adapter;
    }

    /**
     * 4. 业务处理器(单向接收,不能给客户端回复)
     */
    @ServiceActivator(inputChannel = "tcpReceiveChannel")
    public void handleMessage(Message<byte[]> message) {
        String data =
                new String(message.getPayload(), StandardCharsets.UTF_8);
        String connectionId =
                (String) message.getHeaders().get("ip_connectionId");

        log.info("收到 TCP 数据: {}", data);
        log.info("来自连接: {}", connectionId);

        // TODO 业务逻辑处理
    }
}

第二个类文件:

双向类文件:接收客户端消息并回复

bash 复制代码
package com.testweb.testweb.tcp.web;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.ip.tcp.TcpReceivingChannelAdapter;
import org.springframework.integration.ip.tcp.TcpSendingMessageHandler;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory;
import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;

import java.nio.charset.StandardCharsets;

@Slf4j
@Configuration
public class TcpServerReplyConfig {

    @Value("${tcp.server.reply.port:7799}")
    // 与单向服务端端口区分
    private int port;

    // 回复通道
    @Autowired
    @Qualifier("tcpReplySendChannel")
    private MessageChannel tcpReplySendChannel;

    /**
     * 1. TCP 连接工厂(服务端)
     */
    @Bean
    public AbstractServerConnectionFactory replyServerConnectionFactory() {
        TcpNioServerConnectionFactory factory =
                new TcpNioServerConnectionFactory(port);

        // 关键:拆包 / 粘包解决方案
        // 使用换行符拆包(文本协议)或长度头(物联网二进制协议)
        ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer();
        // ByteArrayLengthHeaderSerializer serializer =
        //         new ByteArrayLengthHeaderSerializer();

        factory.setSerializer(serializer);
        factory.setDeserializer(serializer);
        factory.setUsingDirectBuffers(true);
        return factory;
    }

    /**
     * 2. 接收通道
     */
    @Bean
    public MessageChannel tcpReplyReceiveChannel() {
        return new DirectChannel();
    }

    /**
     * 3. TCP 入站适配器(接收客户端消息)
     */
    @Bean
    public TcpReceivingChannelAdapter tcpReplyInboundAdapter(
            AbstractServerConnectionFactory replyServerConnectionFactory,
            MessageChannel tcpReplyReceiveChannel) {

        TcpReceivingChannelAdapter adapter =
                new TcpReceivingChannelAdapter();
        adapter.setConnectionFactory(replyServerConnectionFactory);
        adapter.setOutputChannel(tcpReplyReceiveChannel);
        return adapter;
    }

    /**
     * 4. TCP 出站通道(用于回复客户端)
     */
    @Bean("tcpReplySendChannel")
    public MessageChannel tcpReplySendChannel() {
        return new DirectChannel();
    }

    /**
     * 5. 出站适配器(发送回复)
     */
    @Bean
    @ServiceActivator(inputChannel = "tcpReplySendChannel")
    public TcpSendingMessageHandler tcpReplySender(
            AbstractServerConnectionFactory replyServerConnectionFactory) {

        TcpSendingMessageHandler sender =
                new TcpSendingMessageHandler();
        sender.setConnectionFactory(replyServerConnectionFactory);
        return sender;
    }

    /**
     * 6. 业务处理器:接收客户端消息并回复
     */
    @ServiceActivator(inputChannel = "tcpReplyReceiveChannel")
    public void handleReplyMessage(Message<byte[]> message) {
        String data =
                new String(message.getPayload(), StandardCharsets.UTF_8);
        String connectionId =
                (String) message.getHeaders().get("ip_connectionId");

        log.info("收到客户端消息: {}", data);
        log.info("来自连接: {}", connectionId);

        // 业务逻辑处理完后发送回复
        String reply =
                "服务端已经收到消息,现在给客户端回复: " + data;

        tcpReplySendChannel.send(
                org.springframework.messaging.support.MessageBuilder
                        .withPayload(reply.getBytes(StandardCharsets.UTF_8))
                        .setHeader("ip_connectionId", connectionId)
                        .build()
        );
    }
}

这两个配置文件 大家可以按需选择。第一个类文件就是服务端只负责接收,不会给客户端反馈

第二个类文件,接收后会反馈,如果在使用中发现有需要完善的地方,也欢迎大家留言~

相关推荐
顾安r8 小时前
12.17 脚本网页 创意导航
java·linux·前端·游戏·html
洛阳泰山8 小时前
快速上手 MaxKB4J:开源企业级智能知识库系统在 Sealos 上的完整部署指南
java·开源·llm·agent·rag
risc1234568 小时前
【Elasticsearch】副本恢复机制文件级(file-based)操作级(ops-based)顶级理解
java·mysql·lucene
程序员阿明8 小时前
spring boot 3集成spring security6
spring boot·后端·spring
后端小张8 小时前
【JAVA 进阶】深入拆解SpringBoot自动配置:从原理到实战的完整指南
java·开发语言·spring boot·后端·spring·spring cloud·springboot
Yeniden8 小时前
Deepeek用大白话讲解 → 解释器模式(企业级场景1,规则引擎2,表达式解析3,SQL解析4)
java·sql·解释器模式
草莓熊Lotso8 小时前
C++11 核心进阶:引用折叠、完美转发与可变参数模板实战
开发语言·c++·人工智能·经验分享·后端·visualstudio·gitee
Q_Q5110082858 小时前
小程序springBoot新农村综合风貌旅游展示平台
vue.js·spring boot·后端
一起养小猫8 小时前
《Java数据结构与算法》第四篇(二)二叉树的性质、定义与链式存储实现
java·数据结构·算法