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. 验证功能
- 私聊:指定
type
为private
,target
为目标用户 ID - 群聊:发送消息时指定
type
为group
- 组聊:发送消息时指定
type
为group_custom
并携带groupId
字段
Tio可以更好的拓展websocket,更方便的实现私聊,组聊和群聊的功能,其内部封装好了许多方法,详细可以查看官方文档