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

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

第一步:

引入依赖

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

第二步:

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

第一个类文件:

单向接收tcp客户端数据:

java 复制代码
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 业务逻辑处理
    }
}

第二个类文件:

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

java 复制代码
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()
        );
    }
}

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

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

相关推荐
xqqxqxxq6 分钟前
洛谷算法1-1 模拟与高精度(NOIP经典真题解析)java(持续更新)
java·开发语言·算法
MengFly_11 分钟前
Compose 脚手架 Scaffold 完全指南
android·java·数据库
PPPPickup12 分钟前
application.yml或者yaml文件不显示绿色问题
java·数据库·spring
*小海豚*12 分钟前
springcloud项目运行启动类无法启动,IDEA也没有任何提示
java·ide
qq_2562470527 分钟前
Google 账号防封全攻略:从避坑、保号到申诉解封
后端
zhougl99639 分钟前
Java 枚举类(enum)详解
java·开发语言·python
想七想八不如1140840 分钟前
2019机试真题
java·华为od·华为
恋爱绝缘体143 分钟前
Java语言提供了八种基本类型。六种数字类型【函数基数噶】
java·python·算法
LaoZhangGong1231 小时前
学习TCP/IP的第9步:客户端和服务端综合测试
网络·学习·tcp/ip
MX_93591 小时前
使用Spring的BeanFactoryPostProcessor扩展点完成自定义注解扫描
java·后端·spring