- 使用WebSocet连接IM服务端与客户端。
- 使用Redis string存储用户登录令牌,key为"login:"+用户id,value为token。
- 使用Redis list存储群聊消息,key为 "gml:"+群组id,value为群组消息列表(JSON格式)。
- 使用Redis set存储用户加入的群组列表,key为 "ugs:"+用户id,value为用户当前加入的所有群组id集合。
- 使用Redis pub/sub订阅发布功能实现分布式WebSocket推送服务,订阅发布主题管道名称为 "mq:"+群组id(每个群组单独共享一个主题)。
- 分布式WebSocket推送服务,客户端向任意一个IM服务端发送消息,其他IM服务端都可接收到这条消息,并将消息推送给所有在线连接的同群组客户端(基于Redis订阅/发布功能及WebSocket连接实现)。
- 临时群聊快速搭建(适用于直播间聊天、游戏内聊天)。
- 群聊历史聊天记录查询(HTTP接口实现)。
- 自动清除长期废弃的群聊(基于Redis键值过期功能)。
- 实时推送用户所加入的群组列表的最新动态(WebSocket连接实现)。
- 用户登录状态验证(Redis Token)。
- 一定时间内的消息撤回功能(HTTP接口实现)。
- 部署Redis。
- 配置application.yml文件中的参数。
- 启动项目。
- 启动后访问 http://127.0.0.1:9000/test/websocket ,测试WebSocket连接。
- 可在controller/UserController及service/UserService文件中自定义用户登录逻辑。
- 可在config/InterceptorConfig及interceptor/ApiInterceptor文件中自定义http接口拦截器及拦截路由。
groupId:消息所属群组id
userId:发送该条消息的用户id
info:消息主体内容
ts:消息创建时间戳(毫秒级)
为了省内存,没有消息唯一id/uuid,查询某条消息时,按照groupId、userId、ts这三个字段来匹配消息。先根据groupId查找到指定Redis list,再根据userId和ts查找到list中的指定消息(ps:即使有人在同一毫秒内向某群组插入了两条消息,也无大碍,只会略微影响消息撤回功能及获取历史消息记录功能)。
ws://127.0.0.1:9000/group/chat/{groupId}/{userId}/{token}
groupId:群组id
userId:用户id
token:登录令牌,默认不开启websocket令牌验证,可随意填写一串字符(不能为空)
连接建立后服务端将返回该群组最新的一批消息列表list与该群组消息总数total(以JSON字符串形式推送),格式如下:
{
"list":[
{"groupId":"1","userId":"3","info":"1-hello","ts":1648368380132},
{"groupId":"1","userId":"1","info":"2-hello","ts":1648368386964},
{"groupId":"1","userId":"1","info":"3-hello","ts":1648368388389},
{"groupId":"1","userId":"3","info":"4-hello","ts":1648368390249},
{"groupId":"1","userId":"1","info":"5-hello","ts":1648368391742},
{"groupId":"1","userId":"2","info":"6-hello","ts":1648368393362},
{"groupId":"1","userId":"1","info":"7-hello","ts":1648368394696},
{"groupId":"1","userId":"6","info":"8-hello","ts":1648368396091},
{"groupId":"1","userId":"1","info":"9-hello","ts":1648368397434},
{"groupId":"1","userId":"1","info":"0-hello","ts":1648368400179}
],
"total":399
}
groupId:该消息所属群组id
userId:发送该消息的用户id
info:消息主体信息
ts:消息创建时间戳(毫秒级)
注:如果开启了websocket令牌验证,且用户登录令牌token验证失败,则服务端返回"440"代码,并断开连接。
"440"
连接成功后客户端即可向服务端发送消息
- 客户端发送
"im hello"
然后服务端向所有在线的群组成员推送该条消息(以JSON字符串形式推送),格式如下:
{
"groupId":"1",
"userId":1,
"info":"im hello",
"ts":1648380678385
}
ws://127.0.0.1:9000/group/list/{userId}/{token}
userId:用户id
token:登录令牌,默认不开启websocket令牌验证,可随意填写一串字符(不能为空)
连接建立后,服务端将周期性检查用户群组列表中是否有新消息到达,如果有新消息到达,则向客户端发送最新的群组信息列表(以JSON字符串形式推送),推送数据格式如下:
[
{
"newMessage":
{
"groupId":"1",
"userId":"2",
"info":"hi",
"ts":1648380678385
},
"total":1
},
{
"newMessage":
{
"groupId":"1",
"userId":"1",
"info":"hello",
"ts":1648380642476
},
"total":17
}
]
newMessage:该群组当前最新的一条消息
total:该群组当前消息总数
注:如果开启了websocket令牌验证,且用户登录令牌token验证失败,则服务端返回"440"代码,并断开连接。
"440"
根据业务自定义,默认直接通过验证并返回token。
POST
form-data
参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|---|
userId | 1 | Text | 是 | 用户id |
password | 123456 | Text | 是 | 密码 |
{
"code": 200,
"msg": "8f2c1eb2099049eab5cad6a78a1f8285",
"data": "user_info"
}
前端聊天室上拉刷新时,可调用此接口获取历史消息列表。
POST
form-data
参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|---|
userId | 1 | Text | 是 | 用户id |
token | 84e9d36e4c7c44e0a79bb71f1b4ce9c4 | Text | 是 | 登录令牌 |
参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|---|
userId | 1 | Text | 是 | 指定消息的用户id |
groupId | 1 | Text | 是 | 指定消息所属群组id |
ts | 1648443134344 | Text | 是 | 指定消息的创建时间戳 |
count | 4 | Text | 是 | 要获取的历史消息数量 |
{
"code": 200,
"msg": "操作成功",
"data": [
"{\"groupId\":\"1\",\"userId\":\"1\",\"info\":\"1\",\"ts\":1648368380132}",
"{\"groupId\":\"1\",\"userId\":\"1\",\"info\":\"2\",\"ts\":1648368386964}",
"{\"groupId\":\"1\",\"userId\":\"1\",\"info\":\"3\",\"ts\":1648368388389}",
"{\"groupId\":\"1\",\"userId\":\"1\",\"info\":\"4\",\"ts\":1648368390249}"
]
}
可以给管理端用,用于查看群组消息列表。
POST
form-data
参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|---|
userId | 1 | Text | 是 | 用户id |
token | 84e9d36e4c7c44e0a79bb71f1b4ce9c4 | Text | 是 | 登录令牌 |
参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|---|
groupId | 1 | Text | 是 | 群组id |
startPage | 0 | Text | 是 | 起始页 |
endPage | 5 | Text | 是 | 终止页 |
{
"code": 200,
"msg": "操作成功",
"data": [
"{\"groupId\":\"1\",\"userId\":\"1\",\"info\":\"1\",\"ts\":1648368380132}",
"{\"groupId\":\"1\",\"userId\":\"1\",\"info\":\"2\",\"ts\":1648368386964}",
"{\"groupId\":\"1\",\"userId\":\"1\",\"info\":\"3\",\"ts\":1648368388389}",
"{\"groupId\":\"1\",\"userId\":\"1\",\"info\":\"4\",\"ts\":1648368390249}",
"{\"groupId\":\"1\",\"userId\":\"1\",\"info\":\"5\",\"ts\":1648368391742}",
"{\"groupId\":\"1\",\"userId\":\"1\",\"info\":\"6\",\"ts\":1648368393362}"
]
}
默认设定只能撤回两分钟内的消息。
POST
form-data
参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|---|
userId | 1 | Text | 是 | 用户id |
token | 84e9d36e4c7c44e0a79bb71f1b4ce9c4 | Text | 是 | 登录令牌 |
参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|---|
groupId | 1 | Text | 是 | 群组id |
ts | 1648443134344 | Text | 是 | 消息创建时间戳 |
{
"code": 200,
"msg": "撤回消息成功",
"data": null
}
默认设定用户进行WebSocket连接后自动加入群聊,如果改为手动加群,需要先调用此接口,加群后再进行WebSocket连接。
POST
form-data
参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|---|
userId | 1 | Text | 是 | 用户id |
token | 84e9d36e4c7c44e0a79bb71f1b4ce9c4 | Text | 是 | 登录令牌 |
参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|---|
groupId | 3 | Text | 是 | 群组id |
{
"code": 200,
"msg": "操作成功",
"data": null
}
只返回群组id。
POST
form-data
参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
---|---|---|---|---|
userId | 1 | Text | 是 | 用户id |
token | 84e9d36e4c7c44e0a79bb71f1b4ce9c4 | Text | 是 | 登录令牌 |
{
"code": 200,
"msg": "操作成功",
"data": [
"3",
"2",
"1"
]
}
- config
配置层
- IMConfig
IM基础功能配置
- InterceptorConfig
接口拦截器配置
- RedisConfig
Redis配置类
- WebSocketConfig
websocket配置类
- IMConfig
- controller
控制器层
- GroupController
群组操作接口
- UserController
用户操作接口
- GroupController
- dao
模板层
- GroupObject
群组对象
- MessageList
消息列表封装
- MessageObject
消息对象
- GroupObject
- interceptor
AOP拦截器
- ApiInterceptor
接口拦截器
- ApiInterceptor
- server
websocket服务层
- GroupChatServer
群组聊天室连接(监听群内聊天消息更新)
- GroupListServer
首页群组列表连接(监听用户加入的所有群组数据更新)
- RedisListenServer
Redis订阅监听服务(监听所有IM服务器接收到的消息)
- GroupChatServer
- service
控制器服务层
- GroupService
群组操作服务
- UserService
用户操作服务
- GroupService
- util
工具集合
- LoginUtil
登录验证工具
- RedisUtil
Redis工具类
- ResultUtil
http请求返回模板
- LoginUtil
- FastimApplication
启动类