Browse Source

im-group logic

master
tangmingyou 4 years ago
parent
commit
e979ad73e3
  1. 2
      .gitignore
  2. 75
      doc/db/.back_so-im/so-im-backup-202263204024.pdma.json
  3. 75
      doc/db/.back_so-im/so-im-backup-202263204042.pdma.json
  4. 75
      doc/db/.back_so-im/so-im-backup-202263204100.pdma.json
  5. 3072
      doc/db/so-im-backup-20220529002839.chnr.json
  6. 75
      doc/db/so-im.chnr.json
  7. 6
      im-client/src/main/java/net/sopod/soim/client/cmd/CmdDispatcher.java
  8. 3
      im-client/src/main/java/net/sopod/soim/client/cmd/CmdEnum.java
  9. 12
      im-client/src/main/java/net/sopod/soim/client/cmd/CmdStarter.java
  10. 32
      im-client/src/main/java/net/sopod/soim/client/cmd/args/ArgsGroup.java
  11. 11
      im-client/src/main/java/net/sopod/soim/client/handler/cmd/AddFriendHandler.java
  12. 15
      im-client/src/main/java/net/sopod/soim/client/handler/cmd/FriendsHandler.java
  13. 123
      im-client/src/main/java/net/sopod/soim/client/handler/cmd/GroupHandler.java
  14. 8
      im-client/src/main/java/net/sopod/soim/client/handler/cmd/LoginHandler.java
  15. 4
      im-client/src/main/java/net/sopod/soim/client/handler/cmd/MeHandler.java
  16. 15
      im-client/src/main/java/net/sopod/soim/client/handler/cmd/SearchHandler.java
  17. 12
      im-client/src/main/java/net/sopod/soim/client/handler/cmd/SendHandler.java
  18. 13
      im-client/src/main/java/net/sopod/soim/client/handler/cmd/UsersHandler.java
  19. 27
      im-client/src/main/java/net/sopod/soim/client/handler/msg/ResAddFriendHandler.java
  20. 30
      im-client/src/main/java/net/sopod/soim/client/handler/msg/ResFriendListHandler.java
  21. 31
      im-client/src/main/java/net/sopod/soim/client/handler/msg/ResFriendSearchHandler.java
  22. 28
      im-client/src/main/java/net/sopod/soim/client/handler/msg/ResOnlineUserListHandler.java
  23. 26
      im-client/src/main/java/net/sopod/soim/client/handler/msg/ResTokenAuthHandler.java
  24. 4
      im-client/src/main/java/net/sopod/soim/client/handler/msg/TextChatHandler.java
  25. 2
      im-client/src/main/java/net/sopod/soim/client/logger/Console.java
  26. 10
      im-client/src/main/java/net/sopod/soim/client/protocol/ImMessageInboundHandler.java
  27. 28
      im-client/src/main/java/net/sopod/soim/client/protocol/ImMessageOutboundHandler.java
  28. 10
      im-client/src/main/java/net/sopod/soim/client/protocol/ImMessageRegistry.java
  29. 46
      im-client/src/main/java/net/sopod/soim/client/protocol/ImMessageReqHolder.java
  30. 29
      im-client/src/main/java/net/sopod/soim/client/protocol/ImProtoDispatcher.java
  31. 107
      im-client/src/main/java/net/sopod/soim/client/session/SoImSession.java
  32. 20
      im-common/src/main/java/net/sopod/soim/common/util/StringUtil.java
  33. 15
      im-das-api/im-das-common/pom.xml
  34. 6
      im-das-api/im-das-common/src/main/java/net/sopod/soim/das/common/config/LogicTables.java
  35. 18
      im-das-api/im-das-group-api/pom.xml
  36. 26
      im-das-api/im-das-group-api/src/main/java/net/sopod/soim/das/group/api/model/dto/GroupUser_0.java
  37. 55
      im-das-api/im-das-group-api/src/main/java/net/sopod/soim/das/group/api/model/entity/ImGroup.java
  38. 8
      im-das-api/im-das-group-api/src/main/java/net/sopod/soim/das/group/api/model/entity/ImGroupUser.java
  39. 21
      im-das-api/im-das-group-api/src/main/java/net/sopod/soim/das/group/api/service/DasGroupService.java
  40. 25
      im-das-api/im-das-group-api/src/main/java/net/sopod/soim/das/group/api/service/DasGroupUserService.java
  41. 42
      im-das-api/im-das-message-api/pom.xml
  42. 4
      im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/config/ChatMQAutoConfiguration.java
  43. 12
      im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/config/ChatPersistentRabbitMQConfiguration.java
  44. 3
      im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/config/package-info.java
  45. 4
      im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/entity/ImGroupMessage.java
  46. 8
      im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/entity/ImMessage.java
  47. 2
      im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/mq/ChatMQMessageConverter.java
  48. 2
      im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/mq/ChatQueue.java
  49. 6
      im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/mq/ChatQueueType.java
  50. 3
      im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/mq/package-info.java
  51. 12
      im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/service/DasMQMessagePersistentService.java
  52. 2
      im-das-api/im-das-message-api/src/main/resources/META-INF/spring.factories
  53. 14
      im-das-api/im-das-user-api/pom.xml
  54. 3
      im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/config/package-info.java
  55. 6
      im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/model/entity/ImFriend.java
  56. 54
      im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/model/entity/ImGroup.java
  57. 2
      im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/model/entity/ImUser.java
  58. 3
      im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/mq/package-info.java
  59. 7
      im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/service/FriendDas.java
  60. 3
      im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/service/UserDas.java
  61. 2
      im-das-api/pom.xml
  62. 27
      im-das/im-das-group/pom.xml
  63. 23
      im-das/im-das-group/src/main/java/net/sopod/soim/das/group/DasGroupApplication.java
  64. 6
      im-das/im-das-group/src/main/java/net/sopod/soim/das/group/dao/ImGroupMapper.java
  65. 14
      im-das/im-das-group/src/main/java/net/sopod/soim/das/group/dao/ImGroupUserMapper.java
  66. 63
      im-das/im-das-group/src/main/java/net/sopod/soim/das/group/service/DasGroupServiceImpl.java
  67. 81
      im-das/im-das-group/src/main/java/net/sopod/soim/das/group/service/DasGroupUserServiceImpl.java
  68. 30
      im-das/im-das-group/src/main/resources/application.properties
  69. 20
      im-das/im-das-group/src/main/resources/application.yml
  70. 9
      im-das/im-das-group/src/main/resources/mapper/ImGroupMapper.xml
  71. 2
      im-das/im-das-group/src/main/resources/mapper/ImGroupUserMapper.xml
  72. 26
      im-das/im-das-message/pom.xml
  73. 21
      im-das/im-das-message/src/main/java/net/sopod/soim/das/message/DasMessageApplication.java
  74. 56
      im-das/im-das-message/src/main/java/net/sopod/soim/das/message/consumer/ImMessagePersistentListener.java
  75. 12
      im-das/im-das-message/src/main/java/net/sopod/soim/das/message/consumer/Sender.java
  76. 6
      im-das/im-das-message/src/main/java/net/sopod/soim/das/message/dao/ImGroupMessageMapper.java
  77. 14
      im-das/im-das-message/src/main/java/net/sopod/soim/das/message/dao/ImMessageMapper.java
  78. 34
      im-das/im-das-message/src/main/resources/application.properties
  79. 25
      im-das/im-das-message/src/main/resources/application.yml
  80. 5
      im-das/im-das-message/src/main/resources/mapper/ImGroupMessageMapper.xml
  81. 2
      im-das/im-das-message/src/main/resources/mapper/ImMessageMapper.xml
  82. 82
      im-das/im-das-user/pom.xml
  83. 44
      im-das/im-das-user/src/main/java/net/sopod/soim/das/user/amqp/Receiver.java
  84. 14
      im-das/im-das-user/src/main/java/net/sopod/soim/das/user/dao/ImMessageMapper.java
  85. 27
      im-das/im-das-user/src/main/java/net/sopod/soim/das/user/service/FriendDasImpl.java
  86. 6
      im-das/im-das-user/src/main/java/net/sopod/soim/das/user/service/UserDasImpl.java
  87. 22
      im-das/im-das-user/src/main/resources/application.properties
  88. 5
      im-das/im-das-user/src/main/resources/application.yml
  89. 5
      im-das/im-das-user/src/main/resources/mapper/ImMessageMapper.xml
  90. 2
      im-das/im-das-user/src/test/java/nets/sopod/soim/das/user/dao/DasImUserShardingTest.java
  91. 83
      im-das/pom.xml
  92. 10
      im-entry/pom.xml
  93. 3
      im-entry/src/main/java/net/sopod/soim/entry/handlers/auth/ReqTokenAuthHandler.java
  94. 24
      im-entry/src/main/java/net/sopod/soim/entry/handlers/chat/ReqGroupMessageHandler.java
  95. 3
      im-entry/src/main/java/net/sopod/soim/entry/handlers/chat/ReqTextChatHandler.java
  96. 41
      im-entry/src/main/java/net/sopod/soim/entry/handlers/group/ReqCreateGroupHandler.java
  97. 44
      im-entry/src/main/java/net/sopod/soim/entry/handlers/group/ReqGroupUsersHandler.java
  98. 41
      im-entry/src/main/java/net/sopod/soim/entry/handlers/group/ReqJoinGroupHandler.java
  99. 43
      im-entry/src/main/java/net/sopod/soim/entry/handlers/group/ReqSearchGroupHandler.java
  100. 3
      im-entry/src/main/java/net/sopod/soim/entry/handlers/task/NetUserDelayCloseHandler.java
  101. Some files were not shown because too many files have changed in this diff Show More

2
.gitignore vendored

@ -55,4 +55,4 @@ yarn-debug.log*
yarn-error.log*
/log
*/.back_so-im/
/doc/db/.back_so-im/

75
doc/db/.back_so-im/so-im-backup-2022528154821.pdma.json → doc/db/.back_so-im/so-im-backup-202263204024.pdma.json

@ -4,7 +4,7 @@
"avatar": "",
"version": "4.1.1",
"createdTime": "2022-3-7 15:11:08",
"updatedTime": "2022-5-28 15:45:45",
"updatedTime": "2022-6-3 20:40:08",
"profile": {
"default": {
"db": "8FE7C65E-40EB-41B6-B60E-79063AFF6273",
@ -398,7 +398,7 @@
"id": "9965DCFB-54BE-4C5A-9518-DF09D4E58140"
}
],
"menuWidth": "306px",
"menuWidth": "279px",
"headers": [
{
"refKey": "defKey",
@ -1401,6 +1401,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "4D5EBBEB-09E6-4D73-8741-5FD759597C9D"
},
{
"defKey": "relation_id",
"defName": "好友关系id(消息存储路由分片)",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "BFA286E3-31EE-4563-B4C4-1B32C8EABB9A"
},
{
"defKey": "uid",
"defName": "用户id",
@ -2210,7 +2227,7 @@
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2219,6 +2236,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "41EA492A-EF92-425A-A5D3-DC68EB912E4C"
},
{
"defKey": "status",
"defName": "状态:0删除,1.正常,2.禁用",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"id": "EBB05A85-0A0B-4F40-B6F4-0DC12D12488F"
},
{
"defKey": "group_name",
"defName": "群聊名称",
@ -2228,7 +2262,7 @@
"len": 128,
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2240,12 +2274,12 @@
"defKey": "user_limit",
"defName": "群聊人数限制",
"comment": "",
"domain": "4159ACB8-2488-4350-9C3B-797336F7246E",
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"type": "",
"len": 32,
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2257,12 +2291,12 @@
"defKey": "user_num",
"defName": "当前群聊人数",
"comment": "",
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2274,12 +2308,12 @@
"defKey": "create_time",
"defName": "创建时间",
"comment": "",
"domain": "4159ACB8-2488-4350-9C3B-797336F7246E",
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"type": "",
"len": 32,
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2473,6 +2507,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "EF408842-EAAB-4289-895A-29BFA8781BC2"
},
{
"defKey": "last_active",
"defName": "最后活跃时间",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"id": "4B886C08-68C9-4386-AD4F-37169054A3C4"
},
{
"defKey": "create_time",
"defName": "创建时间",

75
doc/db/.back_so-im/so-im-backup-2022528160650.pdma.json → doc/db/.back_so-im/so-im-backup-202263204042.pdma.json

@ -4,7 +4,7 @@
"avatar": "",
"version": "4.1.1",
"createdTime": "2022-3-7 15:11:08",
"updatedTime": "2022-5-28 15:48:21",
"updatedTime": "2022-6-3 20:40:24",
"profile": {
"default": {
"db": "8FE7C65E-40EB-41B6-B60E-79063AFF6273",
@ -398,7 +398,7 @@
"id": "9965DCFB-54BE-4C5A-9518-DF09D4E58140"
}
],
"menuWidth": "306px",
"menuWidth": "279px",
"headers": [
{
"refKey": "defKey",
@ -1401,6 +1401,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "4D5EBBEB-09E6-4D73-8741-5FD759597C9D"
},
{
"defKey": "relation_id",
"defName": "好友关系id(消息存储路由分片)",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "BFA286E3-31EE-4563-B4C4-1B32C8EABB9A"
},
{
"defKey": "uid",
"defName": "用户id",
@ -2210,7 +2227,7 @@
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2219,6 +2236,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "41EA492A-EF92-425A-A5D3-DC68EB912E4C"
},
{
"defKey": "status",
"defName": "状态:0删除,1.正常,2.禁用",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"id": "EBB05A85-0A0B-4F40-B6F4-0DC12D12488F"
},
{
"defKey": "group_name",
"defName": "群聊名称",
@ -2228,7 +2262,7 @@
"len": 128,
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2240,12 +2274,12 @@
"defKey": "user_limit",
"defName": "群聊人数限制",
"comment": "",
"domain": "4159ACB8-2488-4350-9C3B-797336F7246E",
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"type": "",
"len": 32,
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2257,12 +2291,12 @@
"defKey": "user_num",
"defName": "当前群聊人数",
"comment": "",
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2274,12 +2308,12 @@
"defKey": "create_time",
"defName": "创建时间",
"comment": "",
"domain": "4159ACB8-2488-4350-9C3B-797336F7246E",
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"type": "",
"len": 32,
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2473,6 +2507,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "EF408842-EAAB-4289-895A-29BFA8781BC2"
},
{
"defKey": "last_active",
"defName": "最后活跃时间",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"id": "4B886C08-68C9-4386-AD4F-37169054A3C4"
},
{
"defKey": "create_time",
"defName": "创建时间",

75
doc/db/.back_so-im/so-im-backup-2022528205253.pdma.json → doc/db/.back_so-im/so-im-backup-202263204100.pdma.json

@ -4,7 +4,7 @@
"avatar": "",
"version": "4.1.1",
"createdTime": "2022-3-7 15:11:08",
"updatedTime": "2022-5-28 16:06:50",
"updatedTime": "2022-6-3 20:40:42",
"profile": {
"default": {
"db": "8FE7C65E-40EB-41B6-B60E-79063AFF6273",
@ -398,7 +398,7 @@
"id": "9965DCFB-54BE-4C5A-9518-DF09D4E58140"
}
],
"menuWidth": "306px",
"menuWidth": "279px",
"headers": [
{
"refKey": "defKey",
@ -1401,6 +1401,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "4D5EBBEB-09E6-4D73-8741-5FD759597C9D"
},
{
"defKey": "relation_id",
"defName": "好友关系id(消息存储路由分片)",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "BFA286E3-31EE-4563-B4C4-1B32C8EABB9A"
},
{
"defKey": "uid",
"defName": "用户id",
@ -2210,7 +2227,7 @@
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2219,6 +2236,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "41EA492A-EF92-425A-A5D3-DC68EB912E4C"
},
{
"defKey": "status",
"defName": "状态:0删除,1.正常,2.解散",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"id": "EBB05A85-0A0B-4F40-B6F4-0DC12D12488F"
},
{
"defKey": "group_name",
"defName": "群聊名称",
@ -2228,7 +2262,7 @@
"len": 128,
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2240,12 +2274,12 @@
"defKey": "user_limit",
"defName": "群聊人数限制",
"comment": "",
"domain": "4159ACB8-2488-4350-9C3B-797336F7246E",
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"type": "",
"len": 32,
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2257,12 +2291,12 @@
"defKey": "user_num",
"defName": "当前群聊人数",
"comment": "",
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2274,12 +2308,12 @@
"defKey": "create_time",
"defName": "创建时间",
"comment": "",
"domain": "4159ACB8-2488-4350-9C3B-797336F7246E",
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"type": "",
"len": 32,
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2473,6 +2507,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "EF408842-EAAB-4289-895A-29BFA8781BC2"
},
{
"defKey": "last_active",
"defName": "最后活跃时间",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"id": "4B886C08-68C9-4386-AD4F-37169054A3C4"
},
{
"defKey": "create_time",
"defName": "创建时间",

3072
doc/db/so-im-backup-20220529002839.chnr.json

File diff suppressed because one or more lines are too long

75
doc/db/so-im.chnr.json

@ -4,7 +4,7 @@
"avatar": "",
"version": "4.1.1",
"createdTime": "2022-3-7 15:11:08",
"updatedTime": "2022-5-28 20:52:53",
"updatedTime": "2022-6-3 20:41:00",
"profile": {
"default": {
"db": "8FE7C65E-40EB-41B6-B60E-79063AFF6273",
@ -398,7 +398,7 @@
"id": "9965DCFB-54BE-4C5A-9518-DF09D4E58140"
}
],
"menuWidth": "306px",
"menuWidth": "279px",
"headers": [
{
"refKey": "defKey",
@ -1401,6 +1401,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "4D5EBBEB-09E6-4D73-8741-5FD759597C9D"
},
{
"defKey": "relation_id",
"defName": "好友关系id(消息存储路由分片)",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "BFA286E3-31EE-4563-B4C4-1B32C8EABB9A"
},
{
"defKey": "uid",
"defName": "用户id",
@ -2210,7 +2227,7 @@
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2219,6 +2236,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "41EA492A-EF92-425A-A5D3-DC68EB912E4C"
},
{
"defKey": "status",
"defName": "状态:0删除,1.正常,3禁用,4.解散",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"id": "EBB05A85-0A0B-4F40-B6F4-0DC12D12488F"
},
{
"defKey": "group_name",
"defName": "群聊名称",
@ -2228,7 +2262,7 @@
"len": 128,
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2240,12 +2274,12 @@
"defKey": "user_limit",
"defName": "群聊人数限制",
"comment": "",
"domain": "4159ACB8-2488-4350-9C3B-797336F7246E",
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"type": "",
"len": 32,
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2257,12 +2291,12 @@
"defKey": "user_num",
"defName": "当前群聊人数",
"comment": "",
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"domain": "CBE2B93C-DD97-4950-86A8-B583971583C8",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2274,12 +2308,12 @@
"defKey": "create_time",
"defName": "创建时间",
"comment": "",
"domain": "4159ACB8-2488-4350-9C3B-797336F7246E",
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"type": "",
"len": 32,
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"notNull": true,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
@ -2473,6 +2507,23 @@
"domain": "1E5537DF-B204-49BC-AC1D-457BC6DEE707",
"id": "EF408842-EAAB-4289-895A-29BFA8781BC2"
},
{
"defKey": "last_active",
"defName": "最后活跃时间",
"comment": "",
"type": "",
"len": "",
"scale": "",
"primaryKey": false,
"notNull": false,
"autoIncrement": false,
"defaultValue": "",
"hideInGraph": false,
"refDict": "",
"extProps": {},
"domain": "4E3ADE61-41F4-4E74-8068-C1E543F9095C",
"id": "4B886C08-68C9-4386-AD4F-37169054A3C4"
},
{
"defKey": "create_time",
"defName": "创建时间",

6
im-client/src/main/java/net/sopod/soim/client/cmd/CmdDispatcher.java

@ -6,7 +6,7 @@ import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import net.sopod.soim.client.cmd.handler.CmdHandler;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.common.util.StringUtil;
/**
@ -45,7 +45,7 @@ public class CmdDispatcher {
}
CmdEnum cmdEnum = CmdEnum.getValue(cmd);
if (cmdEnum == null) {
Logger.error("未知指令: {}", cmd);
Console.error("未知指令: {}", cmd);
return;
}
Class<? extends CmdHandler<?>> handlerClass = cmdEnum.getHandlerClass();
@ -65,7 +65,7 @@ public class CmdDispatcher {
}
private void parseParameterExceptionMessage(String message) {
Logger.error(message);
Console.error(message);
}
}

3
im-client/src/main/java/net/sopod/soim/client/cmd/CmdEnum.java

@ -1,5 +1,6 @@
package net.sopod.soim.client.cmd;
import net.sopod.soim.client.cmd.args.ArgsGroup;
import net.sopod.soim.client.cmd.handler.CmdHandler;
import net.sopod.soim.client.handler.cmd.*;
@ -21,7 +22,7 @@ public enum CmdEnum {
users(UsersHandler.class),
/** 用户分组列表 */
groups,
group(GroupHandler.class),
/** 用户搜索 */
search(SearchHandler.class),

12
im-client/src/main/java/net/sopod/soim/client/cmd/CmdStarter.java

@ -2,7 +2,7 @@ package net.sopod.soim.client.cmd;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.logger.Console;
import java.util.Scanner;
@ -28,20 +28,20 @@ public class CmdStarter {
public void start() {
this.close();
this.scanner = new Scanner(System.in);
Logger.pre("【client】: ");
Console.pre("【client】: ");
while(this.scanner.hasNextLine()) {
String cmd = this.scanner.nextLine();
try {
this.cmdDispatcher.dispatchCmd(cmd);
} catch (Exception e) {
Logger.error("cmd error: ", e.getMessage());
Console.error("cmd error: ", e.getMessage());
}
// 退出
if (CmdEnum.exit.name().equals(cmd.split("[ \t]+")[0])) {
Logger.info("bye bye");
Console.info("bye bye");
break;
}
Logger.pre("【client】: ");
Console.pre("【client】: ");
}
}
@ -52,7 +52,7 @@ public class CmdStarter {
}
public static void printPre() {
Logger.pre("【client】: ");
Console.pre("【client】: ");
}
}

32
im-client/src/main/java/net/sopod/soim/client/cmd/args/ArgsGroup.java

@ -0,0 +1,32 @@
package net.sopod.soim.client.cmd.args;
import com.beust.jcommander.Parameter;
import lombok.Data;
import java.util.List;
/**
* ArgsCreateGroup
*
* @author tmy
* @date 2022-06-05 09:32
*/
@Data
public class ArgsGroup {
// @Parameter
// private List<String> parameters;
@Parameter(names = {"create"}, required = false, description = "群聊名称")
private String groupNameCreate;
@Parameter(names = {"search"}, required = false, description = "群聊名称")
private String groupNameSearch;
@Parameter(names = {"join"}, required = false, description = "群聊id")
private Integer joinGroupId;
@Parameter(names = {"users"}, required = false, description = "群聊id")
private Integer usersGroupId;
}

11
im-client/src/main/java/net/sopod/soim/client/handler/cmd/AddFriendHandler.java

@ -4,9 +4,12 @@ import com.google.inject.Inject;
import com.google.inject.Singleton;
import net.sopod.soim.client.cmd.args.ArgsAddFriend;
import net.sopod.soim.client.cmd.handler.CmdHandler;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.client.session.SoImSession;
import net.sopod.soim.data.msg.user.Friend;
import java.util.concurrent.CompletableFuture;
/**
* AddFriendHandler
*
@ -29,7 +32,13 @@ public class AddFriendHandler implements CmdHandler<ArgsAddFriend> {
Friend.ReqAddFriend req = Friend.ReqAddFriend.newBuilder()
.setFid(args.getFriendId())
.build();
soImSession.send(req);
CompletableFuture<Friend.ResAddFriend> future = soImSession.send(req);
Friend.ResAddFriend res = future.join();
if (res.getSuccess()) {
Console.info("添加好友成功");
} else {
Console.error("添加失败:{}", res.getMsg());
}
}
}

15
im-client/src/main/java/net/sopod/soim/client/handler/cmd/FriendsHandler.java

@ -3,8 +3,14 @@ package net.sopod.soim.client.handler.cmd;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import net.sopod.soim.client.cmd.handler.NonArgsHandler;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.client.session.SoImSession;
import net.sopod.soim.data.msg.user.Friend;
import net.sopod.soim.data.msg.user.UserMsg;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
* FriendsHandler
@ -21,7 +27,14 @@ public class FriendsHandler extends NonArgsHandler {
@Override
public void handle() {
Friend.ReqFriendList req = Friend.ReqFriendList.newBuilder().build();
soImSession.send(req);
CompletableFuture<Friend.ResFriendList> future = soImSession.send(req);
Friend.ResFriendList res = future.join();
List<UserMsg.UserInfo> friendsList = res.getFriendsList();
List<String> userLines = friendsList.stream()
.map(u -> u.getUid() + "|" + u.getAccount() + "|" + u.getNickname() + "|" + u.getOnline())
.collect(Collectors.toList());
Console.logList("好友列表", userLines);
}
}

123
im-client/src/main/java/net/sopod/soim/client/handler/cmd/GroupHandler.java

@ -0,0 +1,123 @@
package net.sopod.soim.client.handler.cmd;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import net.sopod.soim.client.cmd.args.ArgsGroup;
import net.sopod.soim.client.cmd.handler.CmdHandler;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.client.session.SoImSession;
import net.sopod.soim.common.util.ImClock;
import net.sopod.soim.common.util.StringUtil;
import net.sopod.soim.data.msg.common.Res;
import net.sopod.soim.data.msg.group.Group;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
* GroupHandler
*
* @author tmy
* @date 2022-06-05 09:35
*/
@Singleton
public class GroupHandler implements CmdHandler<ArgsGroup> {
@Inject
private SoImSession soImSession;
@Override
public ArgsGroup newArgsInstance() {
return new ArgsGroup();
}
@Override
public void handleArgs(ArgsGroup args) {
if (args.getGroupNameCreate() != null) {
this.handleGroupCreate(args.getGroupNameCreate());
} else if (args.getGroupNameSearch() != null) {
this.handleGroupSearch(args.getGroupNameSearch());
} else if (args.getJoinGroupId() != null) {
this.handleGroupJoin(args.getJoinGroupId());
} else if (args.getUsersGroupId() != null) {
this.handleGroupUsers(args.getUsersGroupId());
}
}
/**
* 创建群聊
*/
private void handleGroupCreate(String groupName) {
if (StringUtil.isBlank(groupName)) {
Console.error("群聊名称不能为空");
return;
}
Group.ReqCreateGroup req = Group.ReqCreateGroup.newBuilder()
.setGroupName(groupName)
.build();
CompletableFuture<Res.ResState> future = soImSession.send(req);
Res.ResState res = future.join();
String message = res.getMessage();
Console.info(message);
}
/**
* 群聊搜索
*/
private void handleGroupSearch(String groupName) {
if (StringUtil.isBlank(groupName)) {
Console.error("群聊名称不能为空");
return;
}
Group.ReqSearchGroup req = Group.ReqSearchGroup.newBuilder()
.setGroupName(groupName)
.build();
CompletableFuture<Group.ResSearchGroup> future = soImSession.send(req);
Group.ResSearchGroup res = future.join();
List<Group.GroupInfo> groupsList = res.getGroupsList();
List<String> userLines = groupsList.stream()
.map(g -> g.getGid() + "|" + g.getGroupName() + "|" + g.getUserLimit() + "|" + g.getUserNum() + "|" + ImClock.millis2time(g.getCreateTime()))
.collect(Collectors.toList());
Console.logList("群聊搜索结果", userLines);
}
/**
* 加入群聊
*/
private void handleGroupJoin(Integer groupId) {
Group.ReqJoinGroup req = Group.ReqJoinGroup.newBuilder()
.setGid(groupId)
.build();
CompletableFuture<Res.ResState> future = soImSession.send(req);
Res.ResState res = future.join();
String message = res.getMessage();
Console.info(message);
}
/**
* 群聊用户列表
*/
private void handleGroupUsers(Integer groupId) {
Group.ReqGroupUsers req = Group.ReqGroupUsers.newBuilder()
.setGid(groupId)
.build();
CompletableFuture<Group.ResGroupUsers> future = soImSession.send(req);
Group.ResGroupUsers res = future.join();
List<Group.UserInfo> usersList = res.getUsersList();
List<String> userLines = usersList.stream()
.map(u -> u.getUid() + "|" + u.getAccount() + "|" +
u.getNickname() + "|" +
u.getOnline() + "|" +
ImClock.millis2time(u.getLastActive())
).collect(Collectors.toList());
Console.logList("群用户列表", userLines);
}
}

8
im-client/src/main/java/net/sopod/soim/client/handler/cmd/LoginHandler.java

@ -5,7 +5,7 @@ import com.google.inject.Singleton;
import net.sopod.soim.client.cmd.args.ArgsLogin;
import net.sopod.soim.client.cmd.handler.CmdHandler;
import net.sopod.soim.client.config.ClientConfig;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.client.model.dto.LoginResDTO;
import net.sopod.soim.client.session.SoImSession;
import net.sopod.soim.client.util.HttpClient;
@ -38,13 +38,13 @@ public class LoginHandler implements CmdHandler<ArgsLogin> {
HashMap<String, String> params = new HashMap<>();
params.put("account", args.getAccount());
params.put("password", args.getPassword());
Logger.info("登录中...");
Console.info("登录中...");
LoginResDTO loginRes = HttpClient.restPost(clientConfig.getLoginUrl(), params, LoginResDTO.class);
if (!Boolean.TRUE.equals(loginRes.getSuccess())) {
Logger.error("登录失败: {}", loginRes.getMessage());
Console.error("登录失败: {}", loginRes.getMessage());
return;
}
Logger.info("登录成功: {}", loginRes.getUid());
Console.info("登录成功: {}", loginRes.getUid());
Auth.ReqTokenAuth reqTokenAuth = Auth.ReqTokenAuth.newBuilder()
.setUid(loginRes.getUid())

4
im-client/src/main/java/net/sopod/soim/client/handler/cmd/MeHandler.java

@ -3,7 +3,7 @@ package net.sopod.soim.client.handler.cmd;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import net.sopod.soim.client.cmd.handler.NonArgsHandler;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.client.session.SoImSession;
/**
@ -22,7 +22,7 @@ public class MeHandler extends NonArgsHandler {
public void handle() {
Long uid = soImSession.getUid();
String account = soImSession.getAccount();
Logger.info("me: " + uid + "|" + account);
Console.info("me: " + uid + "|" + account);
}
}

15
im-client/src/main/java/net/sopod/soim/client/handler/cmd/SearchHandler.java

@ -4,8 +4,14 @@ import com.google.inject.Inject;
import com.google.inject.Singleton;
import net.sopod.soim.client.cmd.args.ArgsSearch;
import net.sopod.soim.client.cmd.handler.CmdHandler;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.client.session.SoImSession;
import net.sopod.soim.data.msg.user.AccountSearch;
import net.sopod.soim.data.msg.user.UserMsg;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
* SearchHandler
@ -28,7 +34,14 @@ public class SearchHandler implements CmdHandler<ArgsSearch> {
public void handleArgs(ArgsSearch args) {
AccountSearch.ReqAccountSearch reqSearch = AccountSearch.ReqAccountSearch
.newBuilder().setKeyword(args.getAccount()).build();
soImSession.send(reqSearch);
CompletableFuture<AccountSearch.ResAccountSearch> future = soImSession.send(reqSearch);
AccountSearch.ResAccountSearch res = future.join();
List<UserMsg.UserInfo> usersList = res.getUsersList();
List<String> userLines = usersList.stream()
.map(u -> u.getUid() + "|" + u.getAccount() + "|" + u.getNickname())
.collect(Collectors.toList());
Console.logList("搜索结果", userLines);
}
}

12
im-client/src/main/java/net/sopod/soim/client/handler/cmd/SendHandler.java

@ -5,9 +5,10 @@ import com.google.inject.Inject;
import com.google.inject.Singleton;
import net.sopod.soim.client.cmd.args.ArgsSend;
import net.sopod.soim.client.cmd.handler.CmdHandler;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.client.session.SoImSession;
import net.sopod.soim.common.util.StringUtil;
import net.sopod.soim.data.msg.chat.Chat;
/**
* SendHandler
@ -30,10 +31,15 @@ public class SendHandler implements CmdHandler<ArgsSend> {
public void handleArgs(ArgsSend args) {
String message = Joiner.on(' ').join(args.getParameters());
if (StringUtil.isEmpty(message)) {
Logger.info("请输入要发送的内容");
Console.info("请输入要发送的内容");
return;
}
soImSession.textChat(args.getAccount(), message);
Chat.TextChat textChat = Chat.TextChat.newBuilder()
.setMessage(message)
.setReceiverAccount(args.getAccount())
.setSender(soImSession.getUid())
.build();
soImSession.justSend(textChat);
}
}

13
im-client/src/main/java/net/sopod/soim/client/handler/cmd/UsersHandler.java

@ -4,9 +4,14 @@ import com.google.inject.Inject;
import com.google.inject.Singleton;
import net.sopod.soim.client.cmd.args.ArgsUsers;
import net.sopod.soim.client.cmd.handler.CmdHandler;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.client.session.SoImSession;
import net.sopod.soim.data.msg.user.UserGroup;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
* UsersHandler
*
@ -29,7 +34,13 @@ public class UsersHandler implements CmdHandler<ArgsUsers> {
UserGroup.ReqOnlineUserList req = UserGroup.ReqOnlineUserList.newBuilder()
.setKeyword(args.getKeyword() != null ? args.getKeyword() : "")
.build();
soImSession.send(req);
CompletableFuture<UserGroup.ResOnlineUserList> future = soImSession.send(req);
UserGroup.ResOnlineUserList res = future.join();
List<String> userLines = res.getUsersList().stream()
.map(user -> user.getUid() + " | " + user.getAccount())
.collect(Collectors.toList());
Console.logList("在线用户", userLines);
}
}

27
im-client/src/main/java/net/sopod/soim/client/handler/msg/ResAddFriendHandler.java

@ -1,27 +0,0 @@
package net.sopod.soim.client.handler.msg;
import com.google.inject.Singleton;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.session.MessageHandler;
import net.sopod.soim.data.msg.user.Friend;
/**
* ResAddFriendHandler
*
* @author tmy
* @date 2022-05-23 21:42
*/
@Singleton
public class ResAddFriendHandler implements MessageHandler<Friend.ResAddFriend> {
@Override
public void handleMsg(Friend.ResAddFriend res) {
System.out.println(res);
if (res.getSuccess()) {
Logger.info("添加好友成功");
} else {
Logger.error("添加失败:{}", res.getMsg());
}
}
}

30
im-client/src/main/java/net/sopod/soim/client/handler/msg/ResFriendListHandler.java

@ -1,30 +0,0 @@
package net.sopod.soim.client.handler.msg;
import com.google.inject.Singleton;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.session.MessageHandler;
import net.sopod.soim.data.msg.user.Friend;
import net.sopod.soim.data.msg.user.UserMsg;
import java.util.List;
import java.util.stream.Collectors;
/**
* ResFriendListHandler
*
* @author tmy
* @date 2022-05-23 22:59
*/
@Singleton
public class ResFriendListHandler implements MessageHandler<Friend.ResFriendList> {
@Override
public void handleMsg(Friend.ResFriendList res) {
List<UserMsg.UserInfo> friendsList = res.getFriendsList();
List<String> userLines = friendsList.stream()
.map(u -> u.getUid() + "|" + u.getAccount() + "|" + u.getNickname() + "|" + u.getOnline())
.collect(Collectors.toList());
Logger.logList("好友列表", userLines);
}
}

31
im-client/src/main/java/net/sopod/soim/client/handler/msg/ResFriendSearchHandler.java

@ -1,31 +0,0 @@
package net.sopod.soim.client.handler.msg;
import com.google.inject.Singleton;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.session.MessageHandler;
import net.sopod.soim.data.msg.user.AccountSearch;
import net.sopod.soim.data.msg.user.UserGroup;
import net.sopod.soim.data.msg.user.UserMsg;
import java.util.List;
import java.util.stream.Collectors;
/**
* ResFriendSearchHandler
*
* @author tmy
* @date 2022-05-17 23:41
*/
@Singleton
public class ResFriendSearchHandler implements MessageHandler<AccountSearch.ResAccountSearch> {
@Override
public void handleMsg(AccountSearch.ResAccountSearch res) {
List<UserMsg.UserInfo> usersList = res.getUsersList();
List<String> userLines = usersList.stream()
.map(u -> u.getUid() + "|" + u.getAccount() + "|" + u.getNickname())
.collect(Collectors.toList());
Logger.logList("搜索结果", userLines);
}
}

28
im-client/src/main/java/net/sopod/soim/client/handler/msg/ResOnlineUserListHandler.java

@ -1,28 +0,0 @@
package net.sopod.soim.client.handler.msg;
import com.google.inject.Singleton;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.session.MessageHandler;
import net.sopod.soim.data.msg.user.UserGroup;
import java.util.List;
import java.util.stream.Collectors;
/**
* ResOnlineUserListHandler
*
* @author tmy
* @date 2022-04-28 12:52
*/
@Singleton
public class ResOnlineUserListHandler implements MessageHandler<UserGroup.ResOnlineUserList> {
@Override
public void handleMsg(UserGroup.ResOnlineUserList res) {
List<String> userLines = res.getUsersList().stream()
.map(user -> user.getUid() + " | " + user.getAccount())
.collect(Collectors.toList());
Logger.logList("在线用户", userLines);
}
}

26
im-client/src/main/java/net/sopod/soim/client/handler/msg/ResTokenAuthHandler.java

@ -1,26 +0,0 @@
package net.sopod.soim.client.handler.msg;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import net.sopod.soim.client.session.MessageHandler;
import net.sopod.soim.client.session.SoImSession;
import net.sopod.soim.data.msg.auth.Auth;
/**
* ResTokenAuthHandler
*
* @author tmy
* @date 2022-04-27 9:46
*/
@Singleton
public class ResTokenAuthHandler implements MessageHandler<Auth.ResTokenAuth> {
@Inject
private SoImSession soImSession;
@Override
public void handleMsg(Auth.ResTokenAuth res) {
soImSession.authResult(res.getSuccess(), res.getMessage(), res.getUid());
}
}

4
im-client/src/main/java/net/sopod/soim/client/handler/msg/TextChatHandler.java

@ -1,7 +1,7 @@
package net.sopod.soim.client.handler.msg;
import com.google.inject.Singleton;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.client.session.MessageHandler;
import net.sopod.soim.data.msg.chat.Chat;
@ -16,7 +16,7 @@ public class TextChatHandler implements MessageHandler<Chat.TextChat> {
@Override
public void handleMsg(Chat.TextChat res) {
Logger.info("{}: {}", res.getSender(), res.getMessage());
Console.info("{}: {}", res.getSender(), res.getMessage());
}
}

2
im-client/src/main/java/net/sopod/soim/client/logger/Logger.java → im-client/src/main/java/net/sopod/soim/client/logger/Console.java

@ -14,7 +14,7 @@ import java.util.List;
* @author tmy
* @date 2022-04-25 11:44
*/
public class Logger {
public class Console {
private static int consoleWidth = 60;

10
im-client/src/main/java/net/sopod/soim/client/protocol/ImMessageInboundHandler.java

@ -1,6 +1,9 @@
package net.sopod.soim.client.protocol;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.sopod.soim.data.serialize.ImMessage;
@ -12,14 +15,19 @@ import net.sopod.soim.data.serialize.ImMessageCodec;
* @author tmy
* @date 2022-06-02 17:51
*/
@Singleton
@ChannelHandler.Sharable
public class ImMessageInboundHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Inject
private ImMessageReqHolder imMessageReqHolder;
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf bytebuf) throws Exception {
ImMessage imMessage = ImMessageCodec.decodeImMessage(bytebuf);
// 请求序列号,complete 对应 CompletableFuture
int serialNo = imMessage.getSerialNo();
MessageQueueHolder.getInstance().futureComplete(serialNo, imMessage.getDecodeBody());
imMessageReqHolder.complete(serialNo, imMessage.getDecodeBody());
}
}

28
im-client/src/main/java/net/sopod/soim/client/protocol/ImMessageOutboundHandler.java

@ -1,28 +0,0 @@
package net.sopod.soim.client.protocol;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import net.sopod.soim.data.serialize.ImMessage;
/**
* ImMessageOutboundHandler
*
* @author tmy
* @date 2022-06-02 17:53
*/
public class ImMessageOutboundHandler extends ChannelOutboundHandlerAdapter {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (!(msg instanceof ImMessage)) {
return;
}
ImMessage imMessage = (ImMessage) msg;
imMessage.setSerialNo(10086);
// queue.add something..., 调用的地方,通过阻塞方式 FastThreadLocal 获取一个 CompletableFuture
super.write(ctx, msg, promise);
}
}

10
im-client/src/main/java/net/sopod/soim/client/protocol/ImMessageRegistry.java

@ -1,10 +0,0 @@
package net.sopod.soim.client.protocol;
/**
* ImMessageRegistry
*
* @author tmy
* @date 2022-06-02 17:32
*/
public class ImMessageRegistry {
}

46
im-client/src/main/java/net/sopod/soim/client/protocol/MessageQueueHolder.java → im-client/src/main/java/net/sopod/soim/client/protocol/ImMessageReqHolder.java

@ -1,5 +1,7 @@
package net.sopod.soim.client.protocol;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.protobuf.MessageLite;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
@ -16,48 +18,48 @@ import java.util.concurrent.atomic.AtomicInteger;
* @author tmy
* @date 2022-06-02 17:29
*/
public class MessageQueueHolder {
@Singleton
public class ImMessageReqHolder {
private static final Logger logger = LoggerFactory.getLogger(MessageQueueHolder.class);
private static final Logger logger = LoggerFactory.getLogger(ImMessageReqHolder.class);
private static MessageQueueHolder INSTANCE;
private final ImProtoDispatcher imProtoDispatcher;
private final AtomicInteger serialNoGen;
// TODO 超时处理
private final ConcurrentHashMap<Integer, CompletableFuture<Object>> futureMap;
private MessageQueueHolder() {
@Inject
public ImMessageReqHolder(ImProtoDispatcher imProtoDispatcher) {
this.serialNoGen = new AtomicInteger();
this.futureMap = new ConcurrentHashMap<>();
}
public static MessageQueueHolder getInstance() {
if (INSTANCE == null) {
synchronized (MessageQueueHolder.class) {
if (INSTANCE == null) {
INSTANCE = new MessageQueueHolder();
}
}
}
return INSTANCE;
this.imProtoDispatcher = imProtoDispatcher;
}
public Pair<Integer, CompletableFuture<Object>> nextSerialNo() {
serialNoGen.compareAndSet(Integer.MAX_VALUE, 0);
int serialNo = serialNoGen.incrementAndGet();
CompletableFuture<Object> future = new CompletableFuture<>();
futureMap.put(serialNo, future);
logger.info("put future: {}", serialNo);
logger.debug("put future: {}", serialNo);
return Pair.of(serialNo, future);
}
public void futureComplete(int serialNo, MessageLite body) {
CompletableFuture<Object> completableFuture = futureMap.remove(serialNo);
if (completableFuture == null) {
logger.error("无等待消息的future: {}, {}", serialNo, body);
} else {
completableFuture.complete(body);
/**
* TODO complete fail
*/
public void complete(int serialNo, MessageLite msg) {
if (serialNo > 0) {
// dispatch
CompletableFuture<Object> completableFuture = futureMap.remove(serialNo);
if (completableFuture != null) {
completableFuture.complete(msg);
return;
}
}
// 无同步等待,通过消息分发处理
imProtoDispatcher.dispatch(msg);
}
}

29
im-client/src/main/java/net/sopod/soim/client/session/MessageDispatcher.java → im-client/src/main/java/net/sopod/soim/client/protocol/ImProtoDispatcher.java

@ -1,4 +1,4 @@
package net.sopod.soim.client.session;
package net.sopod.soim.client.protocol;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@ -6,7 +6,10 @@ import com.google.protobuf.MessageLite;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.sopod.soim.client.session.MessageHandler;
import net.sopod.soim.common.util.Reflects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
@ -15,27 +18,23 @@ import java.util.Set;
/**
* MessageDispatcher
* 通过 protobuf 消息类型分发消息到 MessageHandler
*
* @author tmy
* @date 2022-04-27 9:48
*/
@Singleton
@ChannelHandler.Sharable
public class MessageDispatcher extends SimpleChannelInboundHandler<MessageLite> {
public class ImProtoDispatcher {
private static final Logger logger = LoggerFactory.getLogger(ImProtoDispatcher.class);
private Map<Class<?>, MessageHandler> msgHandlers;
@Inject
public MessageDispatcher(Set<MessageHandler> handlers) {
public ImProtoDispatcher(Set<MessageHandler> handlers) {
this.registryHandlers(handlers);
}
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, MessageLite msg) throws Exception {
MessageHandler messageHandler = msgHandlers.get(msg.getClass());
messageHandler.handleMsg(msg);
}
private void registryHandlers(Set<MessageHandler> handlers) {
Map<Class<?>, MessageHandler> msgHandlers = new HashMap<>();
for (MessageHandler<?> handler : handlers) {
@ -50,4 +49,14 @@ public class MessageDispatcher extends SimpleChannelInboundHandler<MessageLite>
this.msgHandlers = msgHandlers;
}
@SuppressWarnings("unchecked")
public void dispatch(MessageLite msg) {
MessageHandler<Object> messageHandler = msgHandlers.get(msg.getClass());
if (messageHandler == null) {
logger.error("{} 消息, 无对应MessageHandler", msg.getClass());
return;
}
messageHandler.handleMsg(msg);
}
}

107
im-client/src/main/java/net/sopod/soim/client/session/SoImSession.java

@ -6,22 +6,18 @@ import com.google.protobuf.MessageLite;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import net.sopod.soim.client.config.exception.ClientException;
import net.sopod.soim.client.logger.Logger;
import net.sopod.soim.client.logger.Console;
import net.sopod.soim.client.protocol.ImMessageInboundHandler;
import net.sopod.soim.client.protocol.MessageQueueHolder;
import net.sopod.soim.common.util.ImClock;
import net.sopod.soim.client.protocol.ImMessageReqHolder;
import net.sopod.soim.common.util.netty.Varint32FrameCodec;
import net.sopod.soim.data.proto.ProtoMessageManager;
import net.sopod.soim.data.msg.auth.Auth;
import net.sopod.soim.data.serialize.ImMessage;
import net.sopod.soim.data.serialize.ImMessageCodec;
import net.sopod.soim.data.msg.auth.Auth;
import net.sopod.soim.data.msg.chat.Chat;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.LoggerFactory;
@ -39,23 +35,22 @@ public class SoImSession {
private static final org.slf4j.Logger logger = LoggerFactory.getLogger(SoImSession.class);
@Inject
private ImMessageReqHolder imMessageReqHolder;
@Inject
private ImMessageInboundHandler imMessageInboundHandler;
private NioEventLoopGroup eventLoopGroup;
private Channel clientChannel;
private AtomicBoolean auth = new AtomicBoolean(false);
private final MessageDispatcher messageDispatcher;
private Long uid;
private String account;
@Inject
public SoImSession(MessageDispatcher messageDispatcher) {
this.messageDispatcher = messageDispatcher;
}
public void connect(String host, Integer port, Auth.ReqTokenAuth tokenAuth, String account) {
// 关闭旧连接
this.close();
@ -68,41 +63,31 @@ public class SoImSession {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(new LoggingHandler(LogLevel.INFO))
// .addLast(new LoggingHandler(LogLevel.INFO))
.addLast(new Varint32FrameCodec())
// .addLast(new ImMessageCodec())
.addLast(new ImMessageCodec.ImMessage2ByteEncoder())
// .addLast(new ImMessageCodec.ImMessageDecoder())
.addLast(new ImMessageInboundHandler());
// .addLast(messageDispatcher);
.addLast(imMessageInboundHandler);
}
});
})
.option(ChannelOption.TCP_NODELAY, true);
try {
Logger.info("连接中...");
Console.info("连接中...");
clientChannel = b.connect(host, port).await().channel();
// 连接后立即发送认证消息,10s未认证连接关闭
CompletableFuture<?> future = this.send0(tokenAuth);
long start = ImClock.millis();
Object res = future.join();
logger.info("future 响应: {}, {}ms", res, ImClock.millis() - start);
this.account = account;
Auth.ResTokenAuth res = (Auth.ResTokenAuth) future.join();
if (res.getSuccess()) {
this.account = account;
this.auth.set(true);
this.uid = res.getUid();
Console.info("连接服务器成功");
} else {
Console.info("连接服务器失败 {}", res.getMessage());
}
// logger.info("future 响应: {}, {}ms", res, ImClock.millis() - start);
} catch (Exception e) {
Logger.error("连接服务器失败: {}", e.getMessage());
}
}
/**
* 处理登录认证结果
*/
public void authResult(boolean success, String message, Long uid) {
this.auth.set(success);
if (this.auth.get()) {
Logger.info("连接服务器成功");
this.uid = uid;
return;
Console.error("连接服务器失败: {}", e.getMessage());
}
Logger.info("连接服务器失败: {}", message);
this.close();
}
private CompletableFuture<?> send0(MessageLite message) {
@ -111,17 +96,10 @@ public class SoImSession {
throw new ClientException("连接已关闭");
}
// 构建 ImMessage
Integer serialNo = ProtoMessageManager.getSerialNo(message.getClass());
if (serialNo == null) {
throw new ClientException("未知的消息类型:" + message.getClass());
}
ImMessage imMessage = new ImMessage()
.setServiceNo(serialNo)
.setBody(message.toByteArray());
ImMessage imMessage = ImMessageCodec.encodeImProto(message);
// serialNo, Future
Pair<Integer, CompletableFuture<Object>> futurePair = MessageQueueHolder.getInstance().nextSerialNo();
Pair<Integer, CompletableFuture<Object>> futurePair = imMessageReqHolder.nextSerialNo();
imMessage.setSerialNo(futurePair.getLeft());
clientChannel.writeAndFlush(imMessage);
return futurePair.getRight();
}
@ -132,23 +110,24 @@ public class SoImSession {
@SuppressWarnings("unchecked")
public <T> CompletableFuture<T> send(MessageLite message) {
if (!auth.get()) {
Logger.error("请先登录");
Console.error("请先登录");
return null;
}
return (CompletableFuture<T>) send0(message);
}
public void textChat(String receiverName, String message) {
Chat.TextChat textChat = Chat.TextChat.newBuilder()
.setMessage(message)
.setReceiverAccount(receiverName)
.setSender(uid)
.build();
send(textChat);
}
public void textChat(Chat.TextChat textChat) {
this.send(textChat);
public void justSend(MessageLite message) {
if (!auth.get()) {
Console.error("请先登录");
return;
}
if (clientChannel == null
|| !clientChannel.isActive()) {
throw new ClientException("连接已关闭");
}
ImMessage imMessage = ImMessageCodec.encodeImProto(message);
imMessage.setSerialNo(-1);
clientChannel.writeAndFlush(imMessage);
}
public Long getUid() {
@ -166,9 +145,9 @@ public class SoImSession {
if (clientChannel != null) {
try {
clientChannel.close().await();
Logger.info("连接已关闭");
Console.info("连接已关闭");
} catch (InterruptedException e) {
Logger.error("连接关闭失败: {}", e.getMessage());
Console.error("连接关闭失败: {}", e.getMessage());
}
this.clientChannel = null;
}

20
im-common/src/main/java/net/sopod/soim/common/util/StringUtil.java

@ -20,6 +20,26 @@ public class StringUtil {
return content == null || content.length() == 0;
}
public static boolean isBlank(String str) {
return !hasText(str);
}
public static boolean hasText(String str) {
return str != null && !str.isEmpty() && containsText(str);
}
private static boolean containsText(CharSequence str) {
int strLen = str.length();
for(int i = 0; i < strLen; ++i) {
if (!Character.isWhitespace(str.charAt(i))) {
return true;
}
}
return false;
}
public static String toString(Object data) {
return data == null ? null : data.toString();
}

15
im-das-api/im-das-common/pom.xml

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>im-das-api</artifactId>
<groupId>net.sopod</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>im-das-common</artifactId>
</project>

6
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/config/LogicTables.java → im-das-api/im-das-common/src/main/java/net/sopod/soim/das/common/config/LogicTables.java

@ -1,4 +1,4 @@
package net.sopod.soim.das.user.api.config;
package net.sopod.soim.das.common.config;
/**
* LogicTables
@ -12,10 +12,14 @@ public interface LogicTables {
Integer STATUS_NORMAL = 1;
Integer STATUS_DISABLED = 2;
String IM_USER = "im_user";
String IM_FRIEND = "im_friend";
String IM_FRIEND_RELATION = "im_friend_relation_id";
String IM_MESSAGE = "im_message";
String IM_GROUP = "im_group";

18
im-das-api/im-das-group-api/pom.xml

@ -11,5 +11,23 @@
<artifactId>im-das-group-api</artifactId>
<dependencies>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-das-common</artifactId>
<version>${soim.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-common</artifactId>
<version>${soim.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

26
im-das-api/im-das-group-api/src/main/java/net/sopod/soim/das/group/api/model/dto/GroupUser_0.java

@ -0,0 +1,26 @@
package net.sopod.soim.das.group.api.model.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* GroupUser0
*
* @author tmy
* @date 2022-06-03 21:24
*/
@Data
@Accessors(chain = true)
public class GroupUser_0 implements Serializable {
private static final long serialVersionUID = 2795983825784323892L;
private Long uid;
private Long lastActive;
private transient Boolean isOnline;
}

55
im-das-api/im-das-group-api/src/main/java/net/sopod/soim/das/group/api/model/entity/ImGroup.java

@ -1,11 +1,58 @@
package net.sopod.soim.das.group.api.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import net.sopod.soim.das.common.config.LogicTables;
import java.io.Serializable;
import java.util.Date;
/**
* ImGroup
* ImGroup 群聊
*
* @author tmy
* @date 2022-05-28 14:57
* @date 2022-05-28 15:14
*/
public class ImGroup {
@Data
@Accessors(chain = true)
@TableName(LogicTables.IM_GROUP)
public class ImGroup implements Serializable {
private static final long serialVersionUID = 2081139176340955425L;
/** 群聊id */
@TableId(value = "id")
private Long id;
/** 群主id */
@TableField(value = "master_uid")
private Long masterUid;
/** 状态:0删除,1.正常,3禁用,4.解散 */
@TableField(value = "status")
private Integer status;
/** 群聊名称 */
@TableField(value = "group_name")
private String groupName;
/** 群聊人数限制 */
@TableField(value = "user_limit")
private Integer userLimit;
/** 当前群聊人数 */
@TableField(value = "user_num")
private Integer userNum;
/** 创建时间 */
@TableField(value = "create_time")
private Date createTime;
/** 更新时间 */
@TableField(value = "update_time")
private Date updateTime;
}

8
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/model/entity/ImGroupUser.java → im-das-api/im-das-group-api/src/main/java/net/sopod/soim/das/group/api/model/entity/ImGroupUser.java

@ -1,11 +1,11 @@
package net.sopod.soim.das.user.api.model.entity;
package net.sopod.soim.das.group.api.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import net.sopod.soim.das.user.api.config.LogicTables;
import net.sopod.soim.das.common.config.LogicTables;
import java.io.Serializable;
import java.util.Date;
@ -43,6 +43,10 @@ public class ImGroupUser implements Serializable {
@TableField(value = "unread_offset_id")
private Long unreadOffsetId;
/** 最后活跃时间 */
@TableField(value = "last_active")
private Date lastActive;
/** 创建时间 */
@TableField(value = "create_time")
private Date createTime;

21
im-das-api/im-das-group-api/src/main/java/net/sopod/soim/das/group/api/service/DasGroupService.java

@ -0,0 +1,21 @@
package net.sopod.soim.das.group.api.service;
import net.sopod.soim.das.group.api.model.entity.ImGroup;
import java.util.List;
/**
* DasGroupService
*
* @author tmy
* @date 2022-06-03 20:04
*/
public interface DasGroupService {
Boolean isGroupNameNotExists(String groupName);
Long saveGroup(ImGroup imGroup);
List<ImGroup> listGroup(String groupNameLike);
}

25
im-das-api/im-das-group-api/src/main/java/net/sopod/soim/das/group/api/service/DasGroupUserService.java

@ -0,0 +1,25 @@
package net.sopod.soim.das.group.api.service;
import net.sopod.soim.das.group.api.model.dto.GroupUser_0;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* DasGroupUserService
*
* @author tmy
* @date 2022-06-03 20:22
*/
public interface DasGroupUserService {
Boolean isJoined(Long groupId, Long uid);
Long insert(Long groupId, Long uid);
void updateLastActive(Long id, Long millis);
List<GroupUser_0> listGroupUsers(Long groupId);
}

42
im-das-api/im-das-message-api/pom.xml

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>im-das-api</artifactId>
<groupId>net.sopod</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>im-das-message-api</artifactId>
<dependencies>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-das-common</artifactId>
<version>${soim.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-common</artifactId>
<version>${soim.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
</dependency>
</dependencies>
</project>

4
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/config/ChatMQAutoConfiguration.java → im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/config/ChatMQAutoConfiguration.java

@ -1,6 +1,7 @@
package net.sopod.soim.das.user.api.config;
package net.sopod.soim.das.message.api.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
/**
@ -11,6 +12,7 @@ import org.springframework.context.annotation.Import;
*/
@ConditionalOnClass(name = "org.springframework.amqp.core.Queue")
@Import(ChatPersistentRabbitMQConfiguration.class)
@ComponentScan(basePackageClasses = ChatMQAutoConfiguration.class)
public class ChatMQAutoConfiguration {
}

12
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/config/ChatPersistentRabbitMQConfiguration.java → im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/config/ChatPersistentRabbitMQConfiguration.java

@ -1,8 +1,8 @@
package net.sopod.soim.das.user.api.config;
package net.sopod.soim.das.message.api.config;
import net.sopod.soim.das.user.api.mq.ChatMQMessageConverter;
import net.sopod.soim.das.user.api.mq.ChatQueueType;
import net.sopod.soim.das.user.api.service.DasMQPersistentService;
import net.sopod.soim.das.message.api.mq.ChatMQMessageConverter;
import net.sopod.soim.das.message.api.mq.ChatQueueType;
import net.sopod.soim.das.message.api.service.DasMQMessagePersistentService;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
@ -53,8 +53,8 @@ public class ChatPersistentRabbitMQConfiguration implements ImportBeanDefinition
}
@Bean
public DasMQPersistentService dasPersistentService(RabbitTemplate rabbitTemplate) {
return new DasMQPersistentService(rabbitTemplate);
public DasMQMessagePersistentService dasPersistentService(RabbitTemplate rabbitTemplate) {
return new DasMQMessagePersistentService(rabbitTemplate);
}
}

3
im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/config/package-info.java

@ -0,0 +1,3 @@
@org.springframework.lang.NonNullApi
package net.sopod.soim.das.message.api.config;

4
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/model/entity/ImGroupMessage.java → im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/entity/ImGroupMessage.java

@ -1,11 +1,11 @@
package net.sopod.soim.das.user.api.model.entity;
package net.sopod.soim.das.message.api.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import net.sopod.soim.das.user.api.config.LogicTables;
import net.sopod.soim.das.common.config.LogicTables;
import java.io.Serializable;
import java.util.Date;

8
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/model/entity/ImMessage.java → im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/entity/ImMessage.java

@ -1,11 +1,11 @@
package net.sopod.soim.das.user.api.model.entity;
package net.sopod.soim.das.message.api.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import net.sopod.soim.das.user.api.config.LogicTables;
import net.sopod.soim.das.common.config.LogicTables;
import java.io.Serializable;
import java.util.Date;
@ -28,8 +28,8 @@ public class ImMessage implements Serializable {
private Long id;
/** 好友关系id(分片) */
@TableField(value = "friend_id")
private Long friendId;
@TableField(value = "relation_id")
private Long relationId;
/** 发送人id */
@TableField(value = "sender")

2
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/mq/ChatMQMessageConverter.java → im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/mq/ChatMQMessageConverter.java

@ -1,4 +1,4 @@
package net.sopod.soim.das.user.api.mq;
package net.sopod.soim.das.message.api.mq;
import net.sopod.soim.common.constant.Consts;
import net.sopod.soim.common.util.Converter;

2
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/mq/ChatQueue.java → im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/mq/ChatQueue.java

@ -1,4 +1,4 @@
package net.sopod.soim.das.user.api.mq;
package net.sopod.soim.das.message.api.mq;
/**
* ChatQueue

6
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/mq/ChatQueueType.java → im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/mq/ChatQueueType.java

@ -1,9 +1,9 @@
package net.sopod.soim.das.user.api.mq;
package net.sopod.soim.das.message.api.mq;
import net.sopod.soim.common.util.Converter;
import net.sopod.soim.common.util.StringUtil;
import net.sopod.soim.das.user.api.model.entity.ImGroupMessage;
import net.sopod.soim.das.user.api.model.entity.ImMessage;
import net.sopod.soim.das.message.api.entity.ImGroupMessage;
import net.sopod.soim.das.message.api.entity.ImMessage;
import java.util.function.Function;

3
im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/mq/package-info.java

@ -0,0 +1,3 @@
@org.springframework.lang.NonNullApi
package net.sopod.soim.das.message.api.mq;

12
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/service/DasMQPersistentService.java → im-das-api/im-das-message-api/src/main/java/net/sopod/soim/das/message/api/service/DasMQMessagePersistentService.java

@ -1,8 +1,8 @@
package net.sopod.soim.das.user.api.service;
package net.sopod.soim.das.message.api.service;
import net.sopod.soim.das.user.api.model.entity.ImGroupMessage;
import net.sopod.soim.das.user.api.model.entity.ImMessage;
import net.sopod.soim.das.user.api.mq.ChatQueueType;
import net.sopod.soim.das.message.api.entity.ImGroupMessage;
import net.sopod.soim.das.message.api.entity.ImMessage;
import net.sopod.soim.das.message.api.mq.ChatQueueType;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
/**
@ -11,11 +11,11 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
* @author tmy
* @date 2022-06-02 20:28
*/
public class DasMQPersistentService {
public class DasMQMessagePersistentService {
private final RabbitTemplate rabbitTemplate;
public DasMQPersistentService(RabbitTemplate rabbitTemplate) {
public DasMQMessagePersistentService(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}

2
im-das-api/im-das-user-api/src/main/resources/META-INF/spring.factories → im-das-api/im-das-message-api/src/main/resources/META-INF/spring.factories

@ -1 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=net.sopod.soim.das.user.api.config.ChatMQAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=net.sopod.soim.das.message.api.config.ChatMQAutoConfiguration

14
im-das-api/im-das-user-api/pom.xml

@ -12,6 +12,11 @@
<artifactId>im-das-user-api</artifactId>
<dependencies>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-das-common</artifactId>
<version>${soim.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
@ -23,15 +28,6 @@
<version>${soim.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
</dependency>
</dependencies>
</project>

3
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/config/package-info.java

@ -1,3 +0,0 @@
@org.springframework.lang.NonNullApi
package net.sopod.soim.das.user.api.config;

6
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/model/entity/ImFriend.java

@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import net.sopod.soim.das.user.api.config.LogicTables;
import net.sopod.soim.das.common.config.LogicTables;
import java.io.Serializable;
import java.util.Date;
@ -29,6 +29,10 @@ public class ImFriend implements Serializable {
@TableId(value = "id", type = IdType.INPUT)
private Long id;
/** 关系id(消息存储路由分片) */
@TableField(value = "relation_id")
private Long relationId;
/** 用户id */
@TableField(value = "uid")
private Long uid;

54
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/model/entity/ImGroup.java

@ -1,54 +0,0 @@
package net.sopod.soim.das.user.api.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import net.sopod.soim.das.user.api.config.LogicTables;
import java.io.Serializable;
import java.util.Date;
/**
* ImGroup 群聊
*
* @author tmy
* @date 2022-05-28 15:14
*/
@Data
@Accessors(chain = true)
@TableName(LogicTables.IM_GROUP)
public class ImGroup implements Serializable {
private static final long serialVersionUID = 2081139176340955425L;
/** 群聊id */
@TableId(value = "id")
private Long id;
/** 群主id */
@TableField(value = "master_uid")
private Long masterUid;
/** 群聊名称 */
@TableField(value = "group_name")
private String groupName;
/** 群聊人数限制 */
@TableField(value = "user_limit")
private String userLimit;
/** 当前群聊人数 */
@TableField(value = "user_num")
private Date userNum;
/** 创建时间 */
@TableField(value = "create_time")
private String createTime;
/** 更新时间 */
@TableField(value = "update_time")
private Date updateTime;
}

2
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/model/entity/ImUser.java

@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
import net.sopod.soim.das.user.api.config.LogicTables;
import net.sopod.soim.das.common.config.LogicTables;
import java.io.Serializable;
import java.util.Date;

3
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/mq/package-info.java

@ -1,3 +0,0 @@
@org.springframework.lang.NonNullApi
package net.sopod.soim.das.user.api.mq;

7
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/service/FriendDas.java

@ -19,9 +19,12 @@ public interface FriendDas {
* @param fid 好友id
* @return 影响行数
*/
int insert(Long uid, Long fid);
int saveFriendRelation(Long uid, Long fid);
Long getFriendId(Long uid, Long fid);
/**
* 获取好友关系id
*/
Long getRelationId(Long uid, Long fid);
/**
* 好友是否存在

3
im-das-api/im-das-user-api/src/main/java/net/sopod/soim/das/user/api/service/UserDas.java

@ -2,6 +2,7 @@ package net.sopod.soim.das.user.api.service;
import net.sopod.soim.das.user.api.model.entity.ImUser;
import java.util.Collection;
import java.util.List;
/**
@ -18,4 +19,6 @@ public interface UserDas {
List<ImUser> searchImUser(String keyword, Integer limit);
List<ImUser> listUsers(Collection<Long> uids);
}

2
im-das-api/pom.xml

@ -14,6 +14,8 @@
<modules>
<module>im-das-user-api</module>
<module>im-das-group-api</module>
<module>im-das-common</module>
<module>im-das-message-api</module>
</modules>

27
im-das/im-das-group/pom.xml

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>im-das</artifactId>
<groupId>net.sopod</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>im-das-group</artifactId>
<dependencies>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-common</artifactId>
<version>${soim.version}</version>
</dependency>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-das-group-api</artifactId>
<version>${soim.version}</version>
</dependency>
</dependencies>
</project>

23
im-das/im-das-group/src/main/java/net/sopod/soim/das/group/DasGroupApplication.java

@ -0,0 +1,23 @@
package net.sopod.soim.das.group;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* DasGroupApplication
*
* @author tmy
* @date 2022-06-03 11:33
*/
@SpringBootApplication
@EnableDubbo(scanBasePackages = "net.sopod.soim.das.group.service")
@MapperScan("net.sopod.soim.das.group.dao")
public class DasGroupApplication {
public static void main(String[] args) {
SpringApplication.run(DasGroupApplication.class);
}
}

6
im-das/im-das-user/src/main/java/net/sopod/soim/das/user/dao/ImGroupMapper.java → im-das/im-das-group/src/main/java/net/sopod/soim/das/group/dao/ImGroupMapper.java

@ -1,7 +1,7 @@
package net.sopod.soim.das.user.dao;
package net.sopod.soim.das.group.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.sopod.soim.das.user.api.model.entity.ImGroup;
import net.sopod.soim.das.group.api.model.entity.ImGroup;
/**
* ImGroupMapper
@ -11,4 +11,6 @@ import net.sopod.soim.das.user.api.model.entity.ImGroup;
*/
public interface ImGroupMapper extends BaseMapper<ImGroup> {
Long selectExistsGroupByName(String groupName);
}

14
im-das/im-das-group/src/main/java/net/sopod/soim/das/group/dao/ImGroupUserMapper.java

@ -0,0 +1,14 @@
package net.sopod.soim.das.group.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.sopod.soim.das.group.api.model.entity.ImGroupUser;
/**
* ImGroupMessageMapper
*
* @author tmy
* @date 2022-05-31 9:59
*/
public interface ImGroupUserMapper extends BaseMapper<ImGroupUser> {
}

63
im-das/im-das-group/src/main/java/net/sopod/soim/das/group/service/DasGroupServiceImpl.java

@ -0,0 +1,63 @@
package net.sopod.soim.das.group.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import net.sopod.soim.common.util.ImClock;
import net.sopod.soim.das.common.config.LogicTables;
import net.sopod.soim.das.group.api.model.entity.ImGroup;
import net.sopod.soim.das.group.api.service.DasGroupService;
import net.sopod.soim.das.group.dao.ImGroupMapper;
import net.sopod.soim.logic.api.segmentid.core.SegmentIdGenerator;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
/**
* DasGroupServiceImpl
*
* @author tmy
* @date 2022-06-03 20:29
*/
@DubboService
public class DasGroupServiceImpl implements DasGroupService {
@Resource
private ImGroupMapper imGroupMapper;
@Resource
private DasGroupUserServiceImpl dasGroupUserService;
@Resource
private SegmentIdGenerator segmentIdGenerator;
@Override
public Boolean isGroupNameNotExists(String groupName) {
Long groupId = imGroupMapper.selectExistsGroupByName(groupName);
return groupId == null;
}
@Transactional
@Override
public Long saveGroup(ImGroup imGroup) {
long groupId = segmentIdGenerator.nextId(LogicTables.IM_GROUP);
// 添加群数据
imGroup.setId(groupId)
.setStatus(LogicTables.STATUS_NORMAL)
.setUserNum(1)
.setCreateTime(ImClock.date());
imGroupMapper.insert(imGroup);
// 添加群主为群用户
dasGroupUserService.insert(groupId, imGroup.getMasterUid());
return groupId;
}
@Override
public List<ImGroup> listGroup(String groupNameLike) {
LambdaQueryWrapper<ImGroup> imGroupQuery = new QueryWrapper<ImGroup>().lambda()
.likeRight(ImGroup::getGroupName, groupNameLike);
return imGroupMapper.selectList(imGroupQuery);
}
}

81
im-das/im-das-group/src/main/java/net/sopod/soim/das/group/service/DasGroupUserServiceImpl.java

@ -0,0 +1,81 @@
package net.sopod.soim.das.group.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import net.sopod.soim.common.util.Collects;
import net.sopod.soim.common.util.ImClock;
import net.sopod.soim.das.common.config.LogicTables;
import net.sopod.soim.das.group.api.model.dto.GroupUser_0;
import net.sopod.soim.das.group.api.model.entity.ImGroupUser;
import net.sopod.soim.das.group.api.service.DasGroupUserService;
import net.sopod.soim.das.group.dao.ImGroupUserMapper;
import net.sopod.soim.logic.api.segmentid.core.SegmentIdGenerator;
import org.apache.dubbo.config.annotation.DubboService;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* DasGroupUserServiceImpl
*
* @author tmy
* @date 2022-06-03 20:30
*/
@DubboService
public class DasGroupUserServiceImpl implements DasGroupUserService {
@Resource
private ImGroupUserMapper imGroupUserMapper;
@Resource
private SegmentIdGenerator segmentIdGenerator;
@Override
public Boolean isJoined(Long groupId, Long uid) {
LambdaQueryWrapper<ImGroupUser> joinIdQuery = new QueryWrapper<ImGroupUser>().lambda()
.select(ImGroupUser::getId)
.eq(ImGroupUser::getGroupId, groupId)
.eq(ImGroupUser::getUid, uid);
return Collects.isNotEmpty(imGroupUserMapper.selectList(joinIdQuery));
}
@Override
public Long insert(Long groupId, Long uid) {
long id = segmentIdGenerator.nextId(LogicTables.IM_GROUP_USER);
Date now = ImClock.date();
ImGroupUser imGroupUser = new ImGroupUser().setId(id)
.setUid(uid)
.setGroupId(groupId)
.setCreateTime(now)
.setLastActive(now)
.setUnreadNum(0)
.setUnreadOffsetId(0L);
imGroupUserMapper.insert(imGroupUser);
return id;
}
@Override
public void updateLastActive(Long id, Long millis) {
ImGroupUser updateWrapper = new ImGroupUser()
.setId(id)
.setLastActive(new Date(millis));
imGroupUserMapper.updateById(updateWrapper);
}
@Override
public List<GroupUser_0> listGroupUsers(Long groupId) {
LambdaQueryWrapper<ImGroupUser> imGroupUserQueryWrapper = new QueryWrapper<ImGroupUser>().lambda()
.select(ImGroupUser::getUid, ImGroupUser::getLastActive)
.eq(ImGroupUser::getGroupId, groupId);
List<ImGroupUser> imGroupUsers = imGroupUserMapper.selectList(imGroupUserQueryWrapper);
List<GroupUser_0> groupUsers = imGroupUsers.stream().map(gu -> new GroupUser_0()
.setUid(gu.getUid())
.setLastActive(gu.getLastActive() == null ? null : gu.getLastActive().getTime())
).collect(Collectors.toList());
return groupUsers;
}
}

30
im-das/im-das-group/src/main/resources/application.properties

@ -0,0 +1,30 @@
# sharding-jdbc 配置
# 配置数据源
spring.shardingsphere.datasource.names=ds1
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://cd-cdb-mrz9fw80.sql.tencentcdb.com:61843/soim_db?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=sopod@2347#
# 5.1.0 分表
# https://github.com/apache/shardingsphere/blob/master/examples/shardingsphere-jdbc-example/single-feature-example/sharding-example/sharding-raw-jdbc-example/src/main/resources/META-INF/sharding-tables.yaml
# 打开sharding-jdbc sql输出日志
spring.shardingsphere.props.sql-show=true
# 需要sharding处理的表
spring.shardingsphere.rules.sharding.binding-tables=im_group,im_group_user
# im_group
spring.shardingsphere.rules.sharding.tables.im_group.actual-data-nodes=ds1.im_group_$->{0..3}
spring.shardingsphere.rules.sharding.tables.im_group.table-strategy.standard.sharding-column=id
spring.shardingsphere.rules.sharding.tables.im_group.table-strategy.standard.sharding-algorithm-name=im-group-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-inline.props.algorithm-expression=im_group_$->{id & 3}
# im_group_user
spring.shardingsphere.rules.sharding.tables.im_group_user.actual-data-nodes=ds1.im_group_user_$->{0..7}
spring.shardingsphere.rules.sharding.tables.im_group_user.table-strategy.standard.sharding-column=group_id
spring.shardingsphere.rules.sharding.tables.im_group_user.table-strategy.standard.sharding-algorithm-name=im-group-user-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-user-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-user-inline.props.algorithm-expression=im_group_user_$->{group_id & 7}

20
im-das/im-das-group/src/main/resources/application.yml

@ -0,0 +1,20 @@
spring:
application:
name: im-das-group
dubbo:
application:
name: ${spring.application.name}
registry:
address: nacos://124.222.131.236:3848
group: so-im
protocol:
port: 3014
consumer:
check: false
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
im-segment-id:
enabled: true

9
im-das/im-das-group/src/main/resources/mapper/ImGroupMapper.xml

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.sopod.soim.das.group.dao.ImGroupMapper">
<select id="selectExistsGroupByName" resultType="long">
select id from im_group where group_name = #{groupName} limit 1
</select>
</mapper>

2
im-das/im-das-user/src/main/resources/mapper/ImGroupMapper.xml → im-das/im-das-group/src/main/resources/mapper/ImGroupUserMapper.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.sopod.soim.das.user.dao.ImGroupMapper">
<mapper namespace="net.sopod.soim.das.group.dao.ImGroupUserMapper">
</mapper>

26
im-das/im-das-message/pom.xml

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>im-das</artifactId>
<groupId>net.sopod</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>im-das-message</artifactId>
<dependencies>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-common</artifactId>
<version>${soim.version}</version>
</dependency>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-das-message-api</artifactId>
<version>${soim.version}</version>
</dependency>
</dependencies>
</project>

21
im-das/im-das-message/src/main/java/net/sopod/soim/das/message/DasMessageApplication.java

@ -0,0 +1,21 @@
package net.sopod.soim.das.message;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* DasMessageApplication
*
* @author tmy
* @date 2022-06-03 11:53
*/
@MapperScan("net.sopod.soim.das.message.dao")
@SpringBootApplication
public class DasMessageApplication {
public static void main(String[] args) {
SpringApplication.run(DasMessageApplication.class);
}
}

56
im-das/im-das-message/src/main/java/net/sopod/soim/das/message/consumer/ImMessagePersistentListener.java

@ -0,0 +1,56 @@
package net.sopod.soim.das.message.consumer;
import lombok.AllArgsConstructor;
import net.sopod.soim.das.message.api.entity.ImGroupMessage;
import net.sopod.soim.das.message.api.entity.ImMessage;
import net.sopod.soim.das.message.api.mq.ChatQueue;
import net.sopod.soim.das.message.dao.ImGroupMessageMapper;
import net.sopod.soim.das.message.dao.ImMessageMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
/**
* Listener
* 只能接受字符串和字节数组
*
* @author tmy
* @date 2022-05-28 16:26
*/
@Service
@AllArgsConstructor
@RabbitListener(queues = {
ChatQueue.IM_MESSAGE_PERSISTENT,
ChatQueue.IM_GROUP_MESSAGE_PERSISTENT
})
public class ImMessagePersistentListener {
private static final Logger logger = LoggerFactory.getLogger(ImMessagePersistentListener.class);
ImMessageMapper imMessageMapper;
ImGroupMessageMapper imGroupMessageMapper;
@RabbitHandler
public void process(ImGroupMessage imGroupMessage) {
// System.out.println("receiver2: " + imGroupMessage);
try {
imGroupMessageMapper.insert(imGroupMessage);
} catch (Exception e) {
logger.error("ImGroupMessage insert 失败: {}", imGroupMessage);
}
}
@RabbitHandler
public void process(ImMessage imMessage) {
// System.out.println("receive3: " + imMessage);
try {
imMessageMapper.insert(imMessage);
} catch (Exception e) {
logger.error("ImMessage insert 失败: {}", imMessage);
}
}
}

12
im-das/im-das-user/src/main/java/net/sopod/soim/das/user/amqp/Sender.java → im-das/im-das-message/src/main/java/net/sopod/soim/das/message/consumer/Sender.java

@ -1,11 +1,11 @@
package net.sopod.soim.das.user.amqp;
package net.sopod.soim.das.message.consumer;
import lombok.AllArgsConstructor;
import net.sopod.soim.common.util.ImClock;
import net.sopod.soim.das.user.api.config.LogicTables;
import net.sopod.soim.das.user.api.model.entity.ImGroupMessage;
import net.sopod.soim.das.user.api.model.entity.ImMessage;
import net.sopod.soim.das.user.api.mq.ChatQueueType;
import net.sopod.soim.das.common.config.LogicTables;
import net.sopod.soim.das.message.api.entity.ImGroupMessage;
import net.sopod.soim.das.message.api.entity.ImMessage;
import net.sopod.soim.das.message.api.mq.ChatQueueType;
import net.sopod.soim.logic.api.segmentid.core.SegmentIdGenerator;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.boot.context.event.ApplicationReadyEvent;
@ -54,7 +54,7 @@ public class Sender implements ApplicationListener<ApplicationReadyEvent> {
.setId(id)
.setSender(10808L)
.setReceiver(180002L)
.setFriendId(101010L)
.setRelationId(101010L)
.setContent(content)
.setCreateTime(ImClock.date());
amqpTemplate.convertAndSend(ChatQueueType.IM_MESSAGE.getQueueName(), imMessage);

6
im-das/im-das-user/src/main/java/net/sopod/soim/das/user/dao/ImGroupMessageMapper.java → im-das/im-das-message/src/main/java/net/sopod/soim/das/message/dao/ImGroupMessageMapper.java

@ -1,13 +1,13 @@
package net.sopod.soim.das.user.dao;
package net.sopod.soim.das.message.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.sopod.soim.das.user.api.model.entity.ImGroupMessage;
import net.sopod.soim.das.message.api.entity.ImGroupMessage;
/**
* ImGroupMessageMapper
*
* @author tmy
* @date 2022-05-31 9:59
* @date 2022-06-03 17:16
*/
public interface ImGroupMessageMapper extends BaseMapper<ImGroupMessage> {

14
im-das/im-das-message/src/main/java/net/sopod/soim/das/message/dao/ImMessageMapper.java

@ -0,0 +1,14 @@
package net.sopod.soim.das.message.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.sopod.soim.das.message.api.entity.ImMessage;
/**
* ImMessageMapper
*
* @author tmy
* @date 2022-06-03 17:16
*/
public interface ImMessageMapper extends BaseMapper<ImMessage> {
}

34
im-das/im-das-message/src/main/resources/application.properties

@ -0,0 +1,34 @@
# sharding-jdbc 配置
# 配置数据源
spring.shardingsphere.datasource.names=ds1
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://cd-cdb-mrz9fw80.sql.tencentcdb.com:61843/soim_db?serverTimezone=GMT%2B8
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=sopod@2347#
# 分表
#spring.shardingsphere.sharding.tables.im_user.actual-data-nodes=db1.im_user_$->{0..2}
## 指定im_user表的分片策略,分片策略包括分片键和分片算法
#spring.shardingsphere.sharding.tables.im_user.table-strategy.inline.sharding-column=id
#spring.shardingsphere.sharding.tables.im_user.table-strategy.inline.algorithm-expression=im_user_$->{id % 3}
# 5.1.0 分表
# https://github.com/apache/shardingsphere/blob/master/examples/shardingsphere-jdbc-example/single-feature-example/sharding-example/sharding-raw-jdbc-example/src/main/resources/META-INF/sharding-tables.yaml
# 打开sharding-jdbc sql输出日志
spring.shardingsphere.props.sql-show=true
# 需要sharding处理的表
spring.shardingsphere.rules.sharding.binding-tables=im_message,im_group_message
# im_message
spring.shardingsphere.rules.sharding.tables.im_message.actual-data-nodes=ds1.im_message_$->{0..7}
spring.shardingsphere.rules.sharding.tables.im_message.table-strategy.standard.sharding-column=relation_id
spring.shardingsphere.rules.sharding.tables.im_message.table-strategy.standard.sharding-algorithm-name=im-message-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.im-message-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.im-message-inline.props.algorithm-expression=im_message_$->{relation_id & 7}
# im_group_message
spring.shardingsphere.rules.sharding.tables.im_group_message.actual-data-nodes=ds1.im_group_message_$->{0..15}
spring.shardingsphere.rules.sharding.tables.im_group_message.table-strategy.standard.sharding-column=group_id
spring.shardingsphere.rules.sharding.tables.im_group_message.table-strategy.standard.sharding-algorithm-name=im-group-message-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-message-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-message-inline.props.algorithm-expression=im_group_message_$->{group_id & 15}

25
im-das/im-das-message/src/main/resources/application.yml

@ -0,0 +1,25 @@
spring:
application:
name: im-das-message
rabbitmq:
host: 124.222.131.236
port: 3672
username: soim
password: sopod@rabbit#
dubbo:
application:
name: ${spring.application.name}
registry:
address: nacos://124.222.131.236:3848
group: so-im
protocol:
port: 3011
consumer:
check: false
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
im-segment-id:
enabled: true

5
im-das/im-das-message/src/main/resources/mapper/ImGroupMessageMapper.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.sopod.soim.das.message.dao.ImGroupMessageMapper">
</mapper>

2
im-das/im-das-user/src/main/resources/mapper/ImGroupMessageMapper.xml → im-das/im-das-message/src/main/resources/mapper/ImMessageMapper.xml

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.sopod.soim.das.user.dao.ImGroupMessageMapper">
<mapper namespace="net.sopod.soim.das.message.dao.ImMessageMapper">
</mapper>

82
im-das/im-das-user/pom.xml

@ -22,88 +22,6 @@
<artifactId>im-das-user-api</artifactId>
<version>${soim.version}</version>
</dependency>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-segment-id-api</artifactId>
<version>${soim.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions><!-- 去掉springboot默认logback日志配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
</dependency>
<!--<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-sharding-spring-boot-starter</artifactId>
</dependency>-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>jackson-dataformat-msgpack</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

44
im-das/im-das-user/src/main/java/net/sopod/soim/das/user/amqp/Receiver.java

@ -1,44 +0,0 @@
package net.sopod.soim.das.user.amqp;
import lombok.AllArgsConstructor;
import net.sopod.soim.das.user.api.model.entity.ImGroupMessage;
import net.sopod.soim.das.user.api.model.entity.ImMessage;
import net.sopod.soim.das.user.api.mq.ChatQueue;
import net.sopod.soim.das.user.dao.ImGroupMessageMapper;
import net.sopod.soim.das.user.dao.ImMessageMapper;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
/**
* Listener
* 只能接受字符串和字节数组
*
* @author tmy
* @date 2022-05-28 16:26
*/
@Service
@AllArgsConstructor
@RabbitListener(queues = {
ChatQueue.IM_MESSAGE_PERSISTENT,
ChatQueue.IM_GROUP_MESSAGE_PERSISTENT
})
public class Receiver {
ImMessageMapper imMessageMapper;
ImGroupMessageMapper imGroupMessageMapper;
@RabbitHandler
public void process(ImGroupMessage imGroupMessage) {
System.out.println("receiver2: " + imGroupMessage);
imGroupMessageMapper.insert(imGroupMessage);
}
@RabbitHandler
public void process(ImMessage imMessage) {
System.out.println("receive3: " + imMessage);
imMessageMapper.insert(imMessage);
}
}

14
im-das/im-das-user/src/main/java/net/sopod/soim/das/user/dao/ImMessageMapper.java

@ -1,14 +0,0 @@
package net.sopod.soim.das.user.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.sopod.soim.das.user.api.model.entity.ImMessage;
/**
* ImMessageMapper
*
* @author tmy
* @date 2022-05-31 9:47
*/
public interface ImMessageMapper extends BaseMapper<ImMessage> {
}

27
im-das/im-das-user/src/main/java/net/sopod/soim/das/user/service/FriendDasImpl.java

@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;
import net.sopod.soim.common.util.Collects;
import net.sopod.soim.common.util.ImClock;
import net.sopod.soim.das.user.api.config.LogicTables;
import net.sopod.soim.das.common.config.LogicTables;
import net.sopod.soim.das.user.api.model.entity.ImFriend;
import net.sopod.soim.das.user.api.model.entity.ImUser;
import net.sopod.soim.das.user.api.service.FriendDas;
@ -37,27 +37,40 @@ public class FriendDasImpl implements FriendDas {
private UserMapper userMapper;
@Override
public int insert(Long uid, Long fid) {
public int saveFriendRelation(Long uid, Long fid) {
long id = segmentIdGenerator.nextId(LogicTables.IM_FRIEND);
long relationId = segmentIdGenerator.nextId(LogicTables.IM_FRIEND_RELATION);
ImFriend imFriend = new ImFriend()
.setId(id)
.setRelationId(relationId)
.setUid(uid)
.setFid(fid)
.setStatus(1)
.setUnreadNum(0)
.setUnreadOffsetId(0L)
.setCreateTime(ImClock.date());
return friendMapper.insert(imFriend);
// 相互添加好友
ImFriend imFriend2 = new ImFriend()
.setId(id)
.setRelationId(relationId)
.setUid(fid)
.setFid(uid)
.setStatus(1)
.setUnreadNum(0)
.setUnreadOffsetId(0L)
.setCreateTime(ImClock.date());
friendMapper.insert(imFriend);
return friendMapper.insert(imFriend2);
}
/**
* TODO cache
*/
@Override
public Long getFriendId(Long uid, Long fid) {
public Long getRelationId(Long uid, Long fid) {
LambdaQueryWrapper<ImFriend> friendQuery = new QueryWrapper<ImFriend>().lambda()
.select(ImFriend::getId, ImFriend::getRelationId)
.eq(ImFriend::getUid, uid)
.eq(ImFriend::getFid, fid)
.eq(ImFriend::getStatus, LogicTables.STATUS_NORMAL);
@ -68,12 +81,12 @@ public class FriendDasImpl implements FriendDas {
if (imFriends.size() > 1) {
logger.warn("重复的好友数据: user={}, friend={}", uid, fid);
}
return imFriends.get(0).getId();
return imFriends.get(0).getRelationId();
}
@Override
public Boolean isExists(Long uid, Long fid) {
return getFriendId(uid, fid) != null;
return getRelationId(uid, fid) != null;
}
@Override

6
im-das/im-das-user/src/main/java/net/sopod/soim/das/user/service/UserDasImpl.java

@ -10,6 +10,7 @@ import net.sopod.soim.das.user.api.service.UserDas;
import net.sopod.soim.das.user.dao.UserMapper;
import org.apache.dubbo.config.annotation.DubboService;
import java.util.Collection;
import java.util.List;
/**
@ -49,5 +50,10 @@ public class UserDasImpl implements UserDas {
return imUserPage.getRecords();
}
@Override
public List<ImUser> listUsers(Collection<Long> uids) {
return userMapper.selectBatchIds(uids);
}
}

22
im-das/im-das-user/src/main/resources/application.properties

@ -1,5 +1,3 @@
spring.profiles.active=${SPRING_PROFILES_ACTIVE:dev}
# sharding-jdbc 配置
# 配置数据源
spring.shardingsphere.datasource.names=ds1
@ -21,7 +19,7 @@ spring.shardingsphere.datasource.ds1.password=sopod@2347#
# 打开sharding-jdbc sql输出日志
spring.shardingsphere.props.sql-show=true
# 需要sharding处理的表
spring.shardingsphere.rules.sharding.binding-tables=im_user,im_friend,im_message,im_group,im_group_user,im_group_message
spring.shardingsphere.rules.sharding.binding-tables=im_user,im_friend,im_message
# im_user
spring.shardingsphere.rules.sharding.tables.im_user.actual-data-nodes=ds1.im_user_$->{0..3}
spring.shardingsphere.rules.sharding.tables.im_user.table-strategy.standard.sharding-column=id
@ -40,21 +38,3 @@ spring.shardingsphere.rules.sharding.tables.im_message.table-strategy.standard.s
spring.shardingsphere.rules.sharding.tables.im_message.table-strategy.standard.sharding-algorithm-name=im-message-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.im-message-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.im-message-inline.props.algorithm-expression=im_message_$->{friend_id & 7}
# im_group
spring.shardingsphere.rules.sharding.tables.im_group.actual-data-nodes=ds1.im_group_$->{0..3}
spring.shardingsphere.rules.sharding.tables.im_group.table-strategy.standard.sharding-column=id
spring.shardingsphere.rules.sharding.tables.im_group.table-strategy.standard.sharding-algorithm-name=im-group-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-inline.props.algorithm-expression=im_group_$->{id & 3}
# im_group_user
spring.shardingsphere.rules.sharding.tables.im_group_user.actual-data-nodes=ds1.im_group_user_$->{0..7}
spring.shardingsphere.rules.sharding.tables.im_group_user.table-strategy.standard.sharding-column=uid
spring.shardingsphere.rules.sharding.tables.im_group_user.table-strategy.standard.sharding-algorithm-name=im-group-user-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-user-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-user-inline.props.algorithm-expression=im_group_user_$->{uid & 7}
# im_group_message
spring.shardingsphere.rules.sharding.tables.im_group_message.actual-data-nodes=ds1.im_group_message_$->{0..15}
spring.shardingsphere.rules.sharding.tables.im_group_message.table-strategy.standard.sharding-column=group_id
spring.shardingsphere.rules.sharding.tables.im_group_message.table-strategy.standard.sharding-algorithm-name=im-group-message-inline
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-message-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.im-group-message-inline.props.algorithm-expression=im_group_message_$->{group_id & 15}

5
im-das/im-das-user/src/main/resources/application.yml

@ -1,11 +1,6 @@
spring:
application:
name: im-das-user
rabbitmq:
host: 124.222.131.236
port: 3672
username: soim
password: sopod@rabbit#
dubbo:
application:

5
im-das/im-das-user/src/main/resources/mapper/ImMessageMapper.xml

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="net.sopod.soim.das.user.dao.ImMessageMapper">
</mapper>

2
im-das/im-das-user/src/test/java/nets/sopod/soim/das/user/dao/DasImUserShardingTest.java

@ -2,9 +2,9 @@ package nets.sopod.soim.das.user.dao;
import com.google.common.base.Preconditions;
import net.sopod.soim.common.util.ImClock;
import net.sopod.soim.das.common.config.LogicTables;
import net.sopod.soim.das.user.DasUserApplication;
import net.sopod.soim.das.user.api.model.entity.ImUser;
import net.sopod.soim.das.user.api.config.LogicTables;
import net.sopod.soim.das.user.dao.UserMapper;
import net.sopod.soim.logic.api.segmentid.core.SegmentIdGenerator;
import org.junit.Test;

83
im-das/pom.xml

@ -13,6 +13,89 @@
<packaging>pom</packaging>
<modules>
<module>im-das-user</module>
<module>im-das-group</module>
<module>im-das-message</module>
</modules>
<dependencies>
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-segment-id-api</artifactId>
<version>${soim.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions><!-- 去掉springboot默认logback日志配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.msgpack</groupId>
<artifactId>jackson-dataformat-msgpack</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

10
im-entry/pom.xml

@ -36,11 +36,11 @@
<artifactId>im-logic-user-api</artifactId>
<version>${soim.version}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>net.sopod</groupId>-->
<!-- <artifactId>im-logic-friend-api</artifactId>-->
<!-- <version>${soim.version}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>net.sopod</groupId>
<artifactId>im-logic-group-api</artifactId>
<version>${soim.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>

3
im-entry/src/main/java/net/sopod/soim/entry/handlers/auth/ReqTokenAuthHandler.java

@ -2,6 +2,7 @@ package net.sopod.soim.entry.handlers.auth;
import com.google.protobuf.MessageLite;
import net.sopod.soim.entry.config.ImEntryAppContextHolder;
import net.sopod.soim.entry.server.handler.ImContext;
import net.sopod.soim.entry.server.handler.NetUserMessageHandler;
import net.sopod.soim.entry.server.session.Account;
import net.sopod.soim.entry.server.session.NetUser;
@ -43,7 +44,7 @@ public class ReqTokenAuthHandler extends NetUserMessageHandler<Auth.ReqTokenAuth
private AccountRegistry accountRegistry;
@Override
public MessageLite handle(NetUser netUser, Auth.ReqTokenAuth msg) {
public MessageLite handle(ImContext ctx, NetUser netUser, Auth.ReqTokenAuth msg) {
logger.info("ReqTokenAuth: uid={}", msg.getUid());
// 校验 token,
// TODO 更新 router 状态成功后再升级为 account,主动关闭时发送一个消息到客户端,校验错误/超时

24
im-entry/src/main/java/net/sopod/soim/entry/handlers/chat/ReqGroupMessageHandler.java

@ -0,0 +1,24 @@
package net.sopod.soim.entry.handlers.chat;
import com.google.protobuf.MessageLite;
import net.sopod.soim.data.msg.group.Group;
import net.sopod.soim.entry.server.handler.AccountMessageHandler;
import net.sopod.soim.entry.server.handler.ImContext;
import net.sopod.soim.entry.server.session.Account;
import org.springframework.stereotype.Service;
/**
* ReqGroupMessageHandler
*
* @author tmy
* @date 2022-06-05 11:05
*/
@Service
public class ReqGroupMessageHandler extends AccountMessageHandler<Group.ReqGroupMessage> {
@Override
public MessageLite handle(ImContext ctx, Account account, Group.ReqGroupMessage req) {
return null;
}
}

3
im-entry/src/main/java/net/sopod/soim/entry/handlers/chat/ReqTextChatHandler.java

@ -2,6 +2,7 @@ package net.sopod.soim.entry.handlers.chat;
import com.google.protobuf.MessageLite;
import net.sopod.soim.entry.server.handler.AccountMessageHandler;
import net.sopod.soim.entry.server.handler.ImContext;
import net.sopod.soim.entry.server.session.Account;
import net.sopod.soim.data.msg.chat.Chat;
import net.sopod.soim.logic.common.model.TextChat;
@ -26,7 +27,7 @@ public class ReqTextChatHandler extends AccountMessageHandler<Chat.TextChat> {
private ChatService chatService;
@Override
public MessageLite handle(Account account, Chat.TextChat msg) {
public MessageLite handle(ImContext ctx, Account account, Chat.TextChat msg) {
TextChat textChat = new TextChat()
.setUid(msg.getSender())
.setReceiverUid(msg.getReceiver())

41
im-entry/src/main/java/net/sopod/soim/entry/handlers/group/ReqCreateGroupHandler.java

@ -0,0 +1,41 @@
package net.sopod.soim.entry.handlers.group;
import com.google.protobuf.MessageLite;
import net.sopod.soim.common.dubbo.exception.SoimException;
import net.sopod.soim.data.msg.common.Res;
import net.sopod.soim.data.msg.group.Group;
import net.sopod.soim.entry.server.handler.AccountMessageHandler;
import net.sopod.soim.entry.server.handler.ImContext;
import net.sopod.soim.entry.server.session.Account;
import net.sopod.soim.logic.api.group.service.ImGroupService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
/**
* ReqCreateGroupHandler
*
* @author tmy
* @date 2022-06-03 10:43
*/
@Service
public class ReqCreateGroupHandler extends AccountMessageHandler<Group.ReqCreateGroup> {
@DubboReference
private ImGroupService imGroupService;
@Override
public MessageLite handle(ImContext ctx, Account account, Group.ReqCreateGroup req) {
String groupName = req.getGroupName();
Res.ResState.Builder resBuilder = Res.ResState.newBuilder();
try {
Long groupId = imGroupService.createGroup(account.getUid(), groupName);
resBuilder.setSuccess(true)
.setMessage("群聊创建成功:" + groupId);
} catch (SoimException e) {
resBuilder.setSuccess(false)
.setMessage(e.getMessage());
}
return resBuilder.build();
}
}

44
im-entry/src/main/java/net/sopod/soim/entry/handlers/group/ReqGroupUsersHandler.java

@ -0,0 +1,44 @@
package net.sopod.soim.entry.handlers.group;
import com.google.protobuf.MessageLite;
import net.sopod.soim.data.msg.group.Group;
import net.sopod.soim.entry.server.handler.AccountMessageHandler;
import net.sopod.soim.entry.server.handler.ImContext;
import net.sopod.soim.entry.server.session.Account;
import net.sopod.soim.logic.api.group.model.dto.GroupUserInfo;
import net.sopod.soim.logic.api.group.service.ImGroupService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* ReqGroupUsersHandler
*
* @author tmy
* @date 2022-06-05 10:33
*/
@Service
public class ReqGroupUsersHandler extends AccountMessageHandler<Group.ReqGroupUsers> {
@DubboReference
private ImGroupService imGroupService;
@Override
public MessageLite handle(ImContext ctx, Account account, Group.ReqGroupUsers req) {
List<GroupUserInfo> groupUserInfos = imGroupService.listGroupUsers(req.getGid());
List<Group.UserInfo> userInfos = groupUserInfos.stream().map(gu -> Group.UserInfo.newBuilder()
.setUid(gu.getUid())
.setAccount(gu.getAccount())
.setNickname(gu.getNickname())
.setOnline(Boolean.TRUE.equals(gu.getOnline()))
.setLastActive(gu.getLastActive())
.build()
).collect(Collectors.toList());
return Group.ResGroupUsers.newBuilder()
.addAllUsers(userInfos)
.build();
}
}

41
im-entry/src/main/java/net/sopod/soim/entry/handlers/group/ReqJoinGroupHandler.java

@ -0,0 +1,41 @@
package net.sopod.soim.entry.handlers.group;
import com.google.protobuf.MessageLite;
import net.sopod.soim.common.dubbo.exception.SoimException;
import net.sopod.soim.data.msg.common.Res;
import net.sopod.soim.data.msg.group.Group;
import net.sopod.soim.entry.server.handler.AccountMessageHandler;
import net.sopod.soim.entry.server.handler.ImContext;
import net.sopod.soim.entry.server.session.Account;
import net.sopod.soim.logic.api.group.service.ImGroupService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
/**
* ReqJoinGroupHandler
*
* @author tmy
* @date 2022-06-05 10:28
*/
@Service
public class ReqJoinGroupHandler extends AccountMessageHandler<Group.ReqJoinGroup> {
@DubboReference
private ImGroupService imGroupService;
@Override
public MessageLite handle(ImContext ctx, Account account, Group.ReqJoinGroup req) {
long groupId = req.getGid();
Res.ResState.Builder resBuilder = Res.ResState.newBuilder();
try {
Long joinId = imGroupService.joinGroup(groupId, account.getUid());
resBuilder.setSuccess(true)
.setMessage("加入群聊成功:" + joinId);
} catch (SoimException e) {
resBuilder.setSuccess(false)
.setMessage(e.getMessage());
}
return resBuilder.build();
}
}

43
im-entry/src/main/java/net/sopod/soim/entry/handlers/group/ReqSearchGroupHandler.java

@ -0,0 +1,43 @@
package net.sopod.soim.entry.handlers.group;
import com.google.protobuf.MessageLite;
import net.sopod.soim.das.group.api.model.entity.ImGroup;
import net.sopod.soim.data.msg.group.Group;
import net.sopod.soim.entry.server.handler.AccountMessageHandler;
import net.sopod.soim.entry.server.handler.ImContext;
import net.sopod.soim.entry.server.session.Account;
import net.sopod.soim.logic.api.group.service.ImGroupService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* ReqSearchGroupHandler
*
* @author tmy
* @date 2022-06-05 09:20
*/
@Service
public class ReqSearchGroupHandler extends AccountMessageHandler<Group.ReqSearchGroup> {
@DubboReference
private ImGroupService imGroupService;
@Override
public MessageLite handle(ImContext ctx, Account account, Group.ReqSearchGroup req) {
String groupName = req.getGroupName();
List<ImGroup> imGroups = imGroupService.searchGroup(groupName);
List<Group.GroupInfo> groupInfos = imGroups.stream().map(imGroup -> Group.GroupInfo.newBuilder()
.setGid(imGroup.getId())
.setGroupName(imGroup.getGroupName())
.setUserLimit(imGroup.getUserLimit())
.setUserNum(imGroup.getUserNum())
.setCreateTime(imGroup.getCreateTime().getTime())
.build()
).collect(Collectors.toList());
return Group.ResSearchGroup.newBuilder().addAllGroups(groupInfos).build();
}
}

3
im-entry/src/main/java/net/sopod/soim/entry/handlers/task/NetUserDelayCloseHandler.java

@ -1,6 +1,7 @@
package net.sopod.soim.entry.handlers.task;
import com.google.protobuf.MessageLite;
import net.sopod.soim.entry.server.handler.ImContext;
import net.sopod.soim.entry.server.handler.NetUserMessageHandler;
import net.sopod.soim.entry.server.session.NetUser;
import net.sopod.soim.data.msg.task.Tasks;
@ -16,7 +17,7 @@ import org.springframework.stereotype.Service;
public class NetUserDelayCloseHandler extends NetUserMessageHandler<Tasks.NetUserDelayCloseTask> {
@Override
public MessageLite handle(NetUser netUser, Tasks.NetUserDelayCloseTask msg) {
public MessageLite handle(ImContext ctx, NetUser netUser, Tasks.NetUserDelayCloseTask msg) {
if (netUser.isAccount()) {
return null;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save