Tio-Boot 集成 Spring Boot 实现即时通讯功能全解析

news/2025/2/23 22:05:34

Tio-Boot 集成 Spring Boot 实现即时通讯功能全解析(详细版)

一、Tio-Boot 简介

Tio-Boot 是基于 Tio 框架的 Spring Boot Starter 扩展,提供高性能、低延迟的网络通信能力,支持 TCP/UDP 协议及 WebSocket 协议,适用于即时通讯、物联网等场景。其核心优势包括:

  • 高性能:基于 Java NIO 实现非阻塞通信
  • 易扩展:支持自定义协议和集群扩展
  • 简化配置:通过自动配置减少冗余代码

二、项目启动配置

1. 添加依赖

pom.xml 中引入 Tio-Boot 依赖(版本 3.6.0.v20200315-RELEASE):

<dependencies>
    <dependency>
        <groupId>org.tio</groupId>
        <artifactId>tio-core-spring-boot-starter</artifactId>
        <version>3.6.0.v20200315-RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.tio</groupId>
        <artifactId>tio-websocket-spring-boot-starter</artifactId>
        <version>3.6.0.v20200315-RELEASE</version>
    </dependency>
</dependencies>

2. 配置文件 application.yml

server:
  port: 8080

tio:
  websocket:
    server:
      ip: 127.0.0.1
      heartbeat-timeout: 600000

3. 启动类配置

在 Spring Boot 主类添加 @EnableTioWebSocketServer 注解:

java">@SpringBootApplication
@EnableTioWebSocketServer
public class TioChatApplication {
    public static void main(String[] args) {
        SpringApplication.run(TioChatApplication.class, args);
    }
}
java">@Configuration
public class TioManualConfig {
    @Value("${tio.websocket.server.port:9326}")
    private int websocketPort;


    @Bean(initMethod = "start")
    public WsServerStarter wsServerStarter() throws IOException {
        return new WsServerStarter(websocketPort, new TioWebSocket());
    }
}


三、核心功能实现

1. 消息处理器(Handler)

创建 ChatServerAioHandler 处理消息收发:

java">@Component
@TioWebSocketMsgHandler
public class ChatServerAioHandler implements IWsMsgHandler {
    private static final String CHARSET = "UTF-8";

    @Override
    public HttpResponse handshake(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) {
        String userId = httpRequest.getParam("uid");
        if (StrUtil.isBlank(userId)) {
            httpResponse.setStatus(HttpResponseStatus.C401);
            return httpResponse;
        }
        // 绑定用户到默认群组
        Tio.bindGroup(channelContext, "default_group");
        Tio.bindUser(channelContext, userId);
        return httpResponse;
    }

    @Override
    public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) {
        System.out.println("用户 " + channelContext.getToken() + " 已连接");
    }

    @Override
    public Object onText(WsRequest wsRequest, String message, ChannelContext channelContext) {
        System.out.println("收到消息: " + message);
        JSONObject json = JSON.parseObject(message);
        String type = json.getString("type");
        String content = json.getString("content");
        String target = json.getString("target");

        if ("private".equals(type)) {
            // 私聊逻辑
            ChannelContext targetContext = Tio.getChannelContextByToken(channelContext.getGroupContext(), target);
            if (targetContext != null) {
                Tio.send(targetContext, content.getBytes(CHARSET));
            }
        } else if ("group".equals(type)) {
            // 群聊逻辑
            Tio.sendToGroup(channelContext, "default_group", content.getBytes(CHARSET));
        } else if ("group_custom".equals(type)) {
            // 组聊逻辑(自定义群组)
            String groupId = json.getString("groupId");
            Tio.sendToGroup(channelContext, groupId, content.getBytes(CHARSET));
        }
        return null;
    }

    @Override
    public void onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) {
        String userId = Tio.getUserContext(channelContext).getToken();
        System.out.println("用户 " + userId + " 已断开");
        Tio.unbindUser(channelContext, userId);
        Tio.unbindGroup(channelContext, "default_group");
    }
}

2. 用户与群组管理

java">@Component
public class UserService {
    private static final Map<String, ChannelContext> USER_MAP = new ConcurrentHashMap<>();

    public void bindUser(ChannelContext channelContext, String userId) {
        USER_MAP.put(userId, channelContext);
    }

    public void unbindUser(String userId) {
        ChannelContext context = USER_MAP.remove(userId);
        if (context != null) {
            Tio.close(context);
        }
    }

    public ChannelContext getUserContext(String userId) {
        return USER_MAP.get(userId);
    }
}

3. 组聊扩展(高级功能)

java">@Component
public class GroupService {
    private static final Map<String, Set<ChannelContext>> GROUP_MAP = new ConcurrentHashMap<>();

    public void joinGroup(ChannelContext context, String groupId) {
        GROUP_MAP.computeIfAbsent(groupId, k -> ConcurrentHashMap.newKeySet()).add(context);
    }

    public void leaveGroup(ChannelContext context, String groupId) {
        GROUP_MAP.getOrDefault(groupId, Collections.emptySet()).remove(context);
    }

    public void sendToGroup(String groupId, byte[] message) {
        GROUP_MAP.getOrDefault(groupId, Collections.emptySet()).forEach(ctx -> {
            try {
                ctx.writeAndFlush(new String(message, CHARSET));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}

四、测试与验证

1. 启动服务

运行 TioChatApplication,控制台输出:

TioWebSocketServer 启动成功,监听端口:8081

2. 客户端连接

使用 WebSocket 客户端连接 ws://localhost:8081,发送测试消息:

{
    "type": "private",
    "target": "user123",
    "content": "Hello Tio!"
}

3. 验证功能

  • 私聊:指定 typeprivatetarget 为目标用户 ID
  • 群聊:发送消息时指定 typegroup
  • 组聊:发送消息时指定 typegroup_custom 并携带 groupId 字段

Tio可以更好的拓展websocket,更方便的实现私聊,组聊和群聊的功能,其内部封装好了许多方法,详细可以查看官方文档


http://www.niftyadmin.cn/n/5863811.html

相关文章

devops 工具 网络安全

&#x1f345; 点击文末小卡片 &#xff0c;免费获取网络安全全套资料&#xff0c;资料在手&#xff0c;涨薪更快 DevOps 是一个结合开发&#xff08;Development&#xff09;和运维&#xff08;Operations&#xff09;的软件开发方法&#xff0c;目的是缩短软件系统的开发周期…

【Deepseek】Linux 本地部署 Deepseek

前言 本文介绍在 Linux 系统上部署 Deepseek AI。本文教程是面向所有想体验 AI 玩家的一个简易教程&#xff0c;因此即使是小白也可以轻松完成体验&#xff0c;话不多说立马着手去干。 [注]&#xff1a;笔者使用的系统为 Ubuntu 24.10 1. 关于 ollama Ollama 是一款开源应用…

小型字符级语言模型的改进方向和策略

小型字符级语言模型的改进方向和策略 一、回顾小型字符级语言模型的处理流程 前文我们已经从零开始构建了一个小型字符级语言模型,那么如何改进和完善我们的模型呢?有哪些改进的方向?我们先回顾一下模型的流程: 图1 小型字符级语言模型的处理流程 (1)核心模块交互过程:…

Unity游戏制作中的C#基础(6)方法和类的知识点深度剖析

1.驼峰命名法 在 C# 编程里&#xff0c;命名规范对于代码的可读性和可维护性至关重要&#xff0c;驼峰命名法便是其中广泛使用的一种命名约定&#xff0c;它主要分为小驼峰命名法和大驼峰命名法&#xff08;帕斯卡命名法&#xff09;。 小驼峰命名法&#xff1a;这种命名方式的…

《算法基础入门:最常用的算法详解与应用(持续更新实战与面试题)》

1. 排序算法 排序算法是将一组数据按特定的顺序排列起来的算法&#xff0c;常见的有&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;选择排序&#xff08;Selection Sort&#xff09;插入排序&#xff08;Insertion Sort&#xff09;归并排序&#xff08;Merge So…

企业数据集成:实现高效调拨出库自动化

调拨出库对接调出单-v&#xff1a;旺店通企业奇门数据集成到用友BIP 在企业信息化管理中&#xff0c;数据的高效流转和准确对接是实现业务流程自动化的关键。本文将分享一个实际案例&#xff0c;展示如何通过轻易云数据集成平台&#xff0c;将旺店通企业奇门的数据无缝集成到用…

webmin配置终端显示样式,模仿UbuntuDesktop终端

webmin配置终端显示样式&#xff0c;模仿UbuntuDesktop终端 在webmin中&#xff0c;默认情况下是没有图形化桌面的&#xff0c;因此终端界面也不会像 Ubuntu Desktop 那样有预设的紫色背景和颜色主题。不过&#xff0c;你可以通过修改 ~/.bashrc 文件&#xff0c;并结合安装和…

ctfshow——phps源码泄露

题目提示&#xff1a;phps源码泄露有时候能帮上忙 题目如下图所示 根据题目提示,本题可以在URL上进行操作&#xff0c;可以查看是否存在index.phps。 当我们输入完后&#xff0c;发现会自动下载一个index.phps的文件&#xff0c;我们可以通过记事本的方式来打开其中的内容&…