Browse Source

过滤html标签

master
Andrews 2 years ago
parent
commit
a442ac2f80
  1. 2
      im-client/src/main/java/com/bx/imclient/IMClient.java
  2. 3
      im-client/src/main/java/com/bx/imclient/config/RedisConfig.java
  3. 12
      im-client/src/main/java/com/bx/imclient/sender/IMSender.java
  4. 19
      im-client/src/main/java/com/bx/imclient/task/AbstractMessageResultTask.java
  5. 2
      im-client/src/main/java/com/bx/imclient/task/GroupMessageResultResultTask.java
  6. 4
      im-client/src/main/java/com/bx/imclient/task/PrivateMessageResultResultTask.java
  7. 12
      im-commom/src/main/java/com/bx/imcommon/contant/IMConstant.java
  8. 40
      im-commom/src/main/java/com/bx/imcommon/contant/IMRedisKey.java
  9. 16
      im-commom/src/main/java/com/bx/imcommon/enums/IMCmdType.java
  10. 11
      im-commom/src/main/java/com/bx/imcommon/enums/IMListenerType.java
  11. 12
      im-commom/src/main/java/com/bx/imcommon/enums/IMSendCode.java
  12. 6
      im-commom/src/main/java/com/bx/imcommon/enums/IMTerminalType.java
  13. 17
      im-commom/src/main/java/com/bx/imcommon/util/JwtUtil.java
  14. 100
      im-commom/src/main/java/com/bx/imcommon/util/ThreadPoolExecutorFactory.java
  15. 1
      im-platform/src/main/java/com/bx/implatform/IMPlatformApp.java
  16. 2
      im-platform/src/main/java/com/bx/implatform/config/ICEServer.java
  17. 1
      im-platform/src/main/java/com/bx/implatform/config/JwtProperties.java
  18. 1
      im-platform/src/main/java/com/bx/implatform/config/MinIoClientConfig.java
  19. 1
      im-platform/src/main/java/com/bx/implatform/config/MvcConfig.java
  20. 4
      im-platform/src/main/java/com/bx/implatform/config/RedisConfig.java
  21. 1
      im-platform/src/main/java/com/bx/implatform/config/SwaggerConfig.java
  22. 17
      im-platform/src/main/java/com/bx/implatform/contant/Constant.java
  23. 41
      im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java
  24. 7
      im-platform/src/main/java/com/bx/implatform/controller/FileController.java
  25. 7
      im-platform/src/main/java/com/bx/implatform/controller/FriendController.java
  26. 7
      im-platform/src/main/java/com/bx/implatform/controller/GroupController.java
  27. 9
      im-platform/src/main/java/com/bx/implatform/controller/GroupMessageController.java
  28. 8
      im-platform/src/main/java/com/bx/implatform/controller/LoginController.java
  29. 7
      im-platform/src/main/java/com/bx/implatform/controller/PrivateMessageController.java
  30. 9
      im-platform/src/main/java/com/bx/implatform/controller/UserController.java
  31. 6
      im-platform/src/main/java/com/bx/implatform/controller/WebrtcController.java
  32. 2
      im-platform/src/main/java/com/bx/implatform/dto/PrivateMessageDTO.java
  33. 1
      im-platform/src/main/java/com/bx/implatform/entity/Group.java
  34. 1
      im-platform/src/main/java/com/bx/implatform/entity/GroupMember.java
  35. 14
      im-platform/src/main/java/com/bx/implatform/enums/FileType.java
  36. 12
      im-platform/src/main/java/com/bx/implatform/enums/MessageStatus.java
  37. 42
      im-platform/src/main/java/com/bx/implatform/enums/MessageType.java
  38. 29
      im-platform/src/main/java/com/bx/implatform/enums/ResultCode.java
  39. 1
      im-platform/src/main/java/com/bx/implatform/exception/GlobalException.java
  40. 5
      im-platform/src/main/java/com/bx/implatform/exception/GlobalExceptionHandler.java
  41. 6
      im-platform/src/main/java/com/bx/implatform/filter/CacheFilter.java
  42. 3
      im-platform/src/main/java/com/bx/implatform/interceptor/AuthInterceptor.java
  43. 3
      im-platform/src/main/java/com/bx/implatform/interceptor/XssInterceptor.java
  44. 4
      im-platform/src/main/java/com/bx/implatform/listener/GroupMessageListener.java
  45. 1
      im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java
  46. 1
      im-platform/src/main/java/com/bx/implatform/mapper/FriendMapper.java
  47. 1
      im-platform/src/main/java/com/bx/implatform/mapper/GroupMapper.java
  48. 1
      im-platform/src/main/java/com/bx/implatform/mapper/GroupMemberMapper.java
  49. 1
      im-platform/src/main/java/com/bx/implatform/mapper/GroupMessageMapper.java
  50. 1
      im-platform/src/main/java/com/bx/implatform/mapper/PrivateMessageMapper.java
  51. 1
      im-platform/src/main/java/com/bx/implatform/mapper/UserMapper.java
  52. 2
      im-platform/src/main/java/com/bx/implatform/result/Result.java
  53. 7
      im-platform/src/main/java/com/bx/implatform/result/ResultUtils.java
  54. 1
      im-platform/src/main/java/com/bx/implatform/service/IFriendService.java
  55. 2
      im-platform/src/main/java/com/bx/implatform/service/IGroupMemberService.java
  56. 2
      im-platform/src/main/java/com/bx/implatform/service/IGroupMessageService.java
  57. 1
      im-platform/src/main/java/com/bx/implatform/service/IGroupService.java
  58. 1
      im-platform/src/main/java/com/bx/implatform/service/IPrivateMessageService.java
  59. 1
      im-platform/src/main/java/com/bx/implatform/service/IUserService.java
  60. 3
      im-platform/src/main/java/com/bx/implatform/service/IWebrtcService.java
  61. 10
      im-platform/src/main/java/com/bx/implatform/service/impl/FriendServiceImpl.java
  62. 1
      im-platform/src/main/java/com/bx/implatform/service/impl/GroupMemberServiceImpl.java
  63. 19
      im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java
  64. 11
      im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java
  65. 8
      im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java
  66. 6
      im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java
  67. 4
      im-platform/src/main/java/com/bx/implatform/service/impl/WebrtcServiceImpl.java
  68. 7
      im-platform/src/main/java/com/bx/implatform/service/thirdparty/FileService.java
  69. 7
      im-platform/src/main/java/com/bx/implatform/session/SessionContext.java
  70. 8
      im-platform/src/main/java/com/bx/implatform/session/UserSession.java
  71. 11
      im-platform/src/main/java/com/bx/implatform/util/BeanUtils.java
  72. 5
      im-platform/src/main/java/com/bx/implatform/util/DateTimeUtils.java
  73. 5
      im-platform/src/main/java/com/bx/implatform/util/FileUtil.java
  74. 8
      im-platform/src/main/java/com/bx/implatform/util/ImageUtil.java
  75. 9
      im-platform/src/main/java/com/bx/implatform/util/MinioUtil.java
  76. 5
      im-platform/src/main/java/com/bx/implatform/util/XssUtil.java
  77. 1
      im-platform/src/main/java/com/bx/implatform/vo/FriendVO.java
  78. 1
      im-platform/src/main/java/com/bx/implatform/vo/GroupMemberVO.java
  79. 1
      im-platform/src/main/java/com/bx/implatform/vo/GroupVO.java
  80. 1
      im-platform/src/main/java/com/bx/implatform/vo/UserVO.java
  81. 3
      im-server/src/main/java/com/bx/imserver/IMServerApp.java
  82. 17
      im-server/src/main/java/com/bx/imserver/constant/ChannelAttrKey.java
  83. 1
      im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java
  84. 2
      im-server/src/main/java/com/bx/imserver/netty/IMServerGroup.java
  85. 5
      im-server/src/main/java/com/bx/imserver/netty/UserChannelCtxMap.java
  86. 7
      im-server/src/main/java/com/bx/imserver/netty/processor/AbstractMessageProcessor.java
  87. 4
      im-server/src/main/java/com/bx/imserver/netty/processor/GroupMessageProcessor.java
  88. 7
      im-server/src/main/java/com/bx/imserver/netty/processor/HeartbeatProcessor.java
  89. 2
      im-server/src/main/java/com/bx/imserver/netty/processor/LoginProcessor.java
  90. 4
      im-server/src/main/java/com/bx/imserver/netty/processor/PrivateMessageProcessor.java
  91. 5
      im-server/src/main/java/com/bx/imserver/netty/tcp/TcpSocketServer.java
  92. 4
      im-server/src/main/java/com/bx/imserver/netty/tcp/endecode/MessageProtocolEncoder.java
  93. 1
      im-server/src/main/java/com/bx/imserver/netty/ws/WebSocketServer.java
  94. 27
      im-server/src/main/java/com/bx/imserver/task/AbstractPullMessageTask.java
  95. 4
      im-server/src/main/java/com/bx/imserver/task/PullGroupMessageTask.java
  96. 4
      im-server/src/main/java/com/bx/imserver/task/PullPrivateMessageTask.java
  97. 1
      im-server/src/main/java/com/bx/imserver/util/SpringContextHolder.java
  98. 4
      im-ui/src/components/chat/ChatBox.vue
  99. 2
      pom.xml

2
im-client/src/main/java/com/bx/imclient/IMClient.java

@ -14,7 +14,7 @@ import java.util.Map;
@AllArgsConstructor @AllArgsConstructor
public class IMClient { public class IMClient {
private IMSender imSender; private final IMSender imSender;
/** /**
* 判断用户是否在线 * 判断用户是否在线

3
im-client/src/main/java/com/bx/imclient/config/RedisConfig.java

@ -25,8 +25,7 @@ public class RedisConfig {
} }
public FastJsonRedisSerializer fastJsonRedisSerializer(){ public FastJsonRedisSerializer fastJsonRedisSerializer(){
FastJsonRedisSerializer <Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class); return new FastJsonRedisSerializer<>(Object.class);
return fastJsonRedisSerializer;
} }
} }

12
im-client/src/main/java/com/bx/imclient/sender/IMSender.java

@ -1,6 +1,6 @@
package com.bx.imclient.sender; package com.bx.imclient.sender;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollUtil;
import com.bx.imclient.listener.MessageListenerMulticaster; import com.bx.imclient.listener.MessageListenerMulticaster;
import com.bx.imcommon.contant.IMRedisKey; import com.bx.imcommon.contant.IMRedisKey;
import com.bx.imcommon.enums.IMCmdType; import com.bx.imcommon.enums.IMCmdType;
@ -79,7 +79,7 @@ public class IMSender {
// 根据群聊每个成员所连的IM-server,进行分组 // 根据群聊每个成员所连的IM-server,进行分组
Map<String, IMUserInfo> sendMap = new HashMap<>(); Map<String, IMUserInfo> sendMap = new HashMap<>();
for (Integer terminal : message.getRecvTerminals()) { for (Integer terminal : message.getRecvTerminals()) {
message.getRecvIds().stream().forEach(id -> { message.getRecvIds().forEach(id -> {
String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, id.toString(), terminal.toString()); String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, id.toString(), terminal.toString());
sendMap.put(key,new IMUserInfo(id, terminal)); sendMap.put(key,new IMUserInfo(id, terminal));
}); });
@ -99,7 +99,7 @@ public class IMSender {
// 加入离线列表 // 加入离线列表
offLineUsers.add(entry.getValue()); offLineUsers.add(entry.getValue());
} }
}; }
// 逐个server发送 // 逐个server发送
for (Map.Entry<Integer, List<IMUserInfo>> entry : serverMap.entrySet()) { for (Map.Entry<Integer, List<IMUserInfo>> entry : serverMap.entrySet()) {
IMRecvInfo recvInfo = new IMRecvInfo(); IMRecvInfo recvInfo = new IMRecvInfo();
@ -149,8 +149,8 @@ public class IMSender {
} }
public Map<Long,List<IMTerminalType>> getOnlineTerminal(List<Long> userIds){ public Map<Long,List<IMTerminalType>> getOnlineTerminal(List<Long> userIds){
if(CollectionUtil.isEmpty(userIds)){ if(CollUtil.isEmpty(userIds)){
return Collections.EMPTY_MAP; return Collections.emptyMap();
} }
// 把所有用户的key都存起来 // 把所有用户的key都存起来
Map<String,IMUserInfo> userMap = new HashMap<>(); Map<String,IMUserInfo> userMap = new HashMap<>();
@ -178,7 +178,7 @@ public class IMSender {
public Boolean isOnline(Long userId) { public Boolean isOnline(Long userId) {
String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, userId.toString(), "*"); String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, userId.toString(), "*");
return !redisTemplate.keys(key).isEmpty(); return !Objects.requireNonNull(redisTemplate.keys(key)).isEmpty();
} }
public List<Long> getOnlineUser(List<Long> userIds){ public List<Long> getOnlineUser(List<Long> userIds){

19
im-client/src/main/java/com/bx/imclient/task/AbstractMessageResultTask.java

@ -1,26 +1,22 @@
package com.bx.imclient.task; package com.bx.imclient.task;
import com.bx.imcommon.util.ThreadPoolExecutorFactory;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.CommandLineRunner;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j @Slf4j
public abstract class AbstractMessageResultTask implements CommandLineRunner { public abstract class AbstractMessageResultTask implements CommandLineRunner {
private int threadNum = 8; private static final ExecutorService EXECUTOR_SERVICE = ThreadPoolExecutorFactory.getThreadPoolExecutor();
private ExecutorService executorService = Executors.newFixedThreadPool(threadNum);
@Override @Override
public void run(String... args) throws Exception { public void run(String... args) {
// 初始化定时器 // 初始化定时器
for(int i=0;i<threadNum;i++){ EXECUTOR_SERVICE.execute(new Runnable() {
executorService.execute(new Runnable() {
@SneakyThrows @SneakyThrows
@Override @Override
public void run() { public void run() {
@ -30,19 +26,18 @@ public abstract class AbstractMessageResultTask implements CommandLineRunner {
log.error("任务调度异常",e); log.error("任务调度异常",e);
Thread.sleep(200); Thread.sleep(200);
} }
if(!executorService.isShutdown()){ if(!EXECUTOR_SERVICE.isShutdown()){
executorService.execute(this); EXECUTOR_SERVICE.execute(this);
} }
} }
}); });
} }
}
@PreDestroy @PreDestroy
public void destroy(){ public void destroy(){
log.info("{}线程任务关闭",this.getClass().getSimpleName()); log.info("{}线程任务关闭",this.getClass().getSimpleName());
executorService.shutdown(); EXECUTOR_SERVICE.shutdown();
} }
public abstract void pullMessage(); public abstract void pullMessage();

2
im-client/src/main/java/com/bx/imclient/task/GroupMessageResultResultTask.java

@ -19,7 +19,7 @@ public class GroupMessageResultResultTask extends AbstractMessageResultTask {
@Resource(name = "IMRedisTemplate") @Resource(name = "IMRedisTemplate")
private RedisTemplate<String,Object> redisTemplate; private RedisTemplate<String,Object> redisTemplate;
private MessageListenerMulticaster listenerMulticaster; private final MessageListenerMulticaster listenerMulticaster;
@Override @Override
public void pullMessage() { public void pullMessage() {

4
im-client/src/main/java/com/bx/imclient/task/PrivateMessageResultResultTask.java

@ -13,8 +13,6 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
;
@Slf4j @Slf4j
@Component @Component
@AllArgsConstructor @AllArgsConstructor
@ -24,7 +22,7 @@ public class PrivateMessageResultResultTask extends AbstractMessageResultTask {
@Resource(name = "IMRedisTemplate") @Resource(name = "IMRedisTemplate")
private RedisTemplate<String,Object> redisTemplate; private RedisTemplate<String,Object> redisTemplate;
private MessageListenerMulticaster listenerMulticaster; private final MessageListenerMulticaster listenerMulticaster;
@Override @Override
public void pullMessage() { public void pullMessage() {

12
im-commom/src/main/java/com/bx/imcommon/contant/IMConstant.java

@ -1,11 +1,17 @@
package com.bx.imcommon.contant; package com.bx.imcommon.contant;
public final class IMConstant {
public class IMConstant { private IMConstant() {
}
// 在线状态过期时间 600s /**
* 在线状态过期时间 600s
*/
public static final long ONLINE_TIMEOUT_SECOND = 600; public static final long ONLINE_TIMEOUT_SECOND = 600;
// 消息允许撤回时间 300s /**
* 消息允许撤回时间 300s
*/
public static final long ALLOW_RECALL_SECOND = 300; public static final long ALLOW_RECALL_SECOND = 300;

40
im-commom/src/main/java/com/bx/imcommon/contant/IMRedisKey.java

@ -1,18 +1,32 @@
package com.bx.imcommon.contant; package com.bx.imcommon.contant;
public class IMRedisKey { public final class IMRedisKey {
// im-server最大id,从0开始递增 private IMRedisKey() {}
public final static String IM_MAX_SERVER_ID = "im:max_server_id";
// 用户ID所连接的IM-server的ID /**
public final static String IM_USER_SERVER_ID = "im:user:server_id"; * im-server最大id,从0开始递增
// 未读私聊消息队列 */
public final static String IM_MESSAGE_PRIVATE_QUEUE = "im:message:private"; public static final String IM_MAX_SERVER_ID = "im:max_server_id";
// 未读群聊消息队列 /**
public final static String IM_MESSAGE_GROUP_QUEUE = "im:message:group"; * 用户ID所连接的IM-server的ID
// 私聊消息发送结果队列 */
public final static String IM_RESULT_PRIVATE_QUEUE = "im:result:private"; public static final String IM_USER_SERVER_ID = "im:user:server_id";
// 群聊消息发送结果队列 /**
public final static String IM_RESULT_GROUP_QUEUE = "im:result:group"; * 未读私聊消息队列
*/
public static final String IM_MESSAGE_PRIVATE_QUEUE = "im:message:private";
/**
* 未读群聊消息队列
*/
public static final String IM_MESSAGE_GROUP_QUEUE = "im:message:group";
/**
* 私聊消息发送结果队列
*/
public static final String IM_RESULT_PRIVATE_QUEUE = "im:result:private";
/**
* 群聊消息发送结果队列
*/
public static final String IM_RESULT_GROUP_QUEUE = "im:result:group";
} }

16
im-commom/src/main/java/com/bx/imcommon/enums/IMCmdType.java

@ -1,15 +1,29 @@
package com.bx.imcommon.enums; package com.bx.imcommon.enums;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
public enum IMCmdType { public enum IMCmdType {
/**
* 登陆
*/
LOGIN(0, "登陆"), LOGIN(0, "登陆"),
/**
* 心跳
*/
HEART_BEAT(1, "心跳"), HEART_BEAT(1, "心跳"),
/**
* 强制下线
*/
FORCE_LOGUT(2, "强制下线"), FORCE_LOGUT(2, "强制下线"),
/**
* 私聊消息
*/
PRIVATE_MESSAGE(3, "私聊消息"), PRIVATE_MESSAGE(3, "私聊消息"),
/**
* 群发消息
*/
GROUP_MESSAGE(4, "群发消息"); GROUP_MESSAGE(4, "群发消息");

11
im-commom/src/main/java/com/bx/imcommon/enums/IMListenerType.java

@ -4,16 +4,23 @@ import lombok.AllArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
public enum IMListenerType { public enum IMListenerType {
/**
* 全部消息
*/
ALL(0, "全部消息"), ALL(0, "全部消息"),
/**
* 私聊消息
*/
PRIVATE_MESSAGE(1, "私聊消息"), PRIVATE_MESSAGE(1, "私聊消息"),
/**
* 群聊消息
*/
GROUP_MESSAGE(2, "群聊消息"); GROUP_MESSAGE(2, "群聊消息");
private final Integer code; private final Integer code;
private final String desc; private final String desc;
public Integer code() { public Integer code() {
return this.code; return this.code;
} }

12
im-commom/src/main/java/com/bx/imcommon/enums/IMSendCode.java

@ -5,9 +5,21 @@ import lombok.AllArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
public enum IMSendCode { public enum IMSendCode {
/**
* 发送成功
*/
SUCCESS(0, "发送成功"), SUCCESS(0, "发送成功"),
/**
* 对方当前不在线
*/
NOT_ONLINE(1, "对方当前不在线"), NOT_ONLINE(1, "对方当前不在线"),
/**
* 未找到对方的channel
*/
NOT_FIND_CHANNEL(2, "未找到对方的channel"), NOT_FIND_CHANNEL(2, "未找到对方的channel"),
/**
* 未知异常
*/
UNKONW_ERROR(9999, "未知异常"); UNKONW_ERROR(9999, "未知异常");
private final Integer code; private final Integer code;

6
im-commom/src/main/java/com/bx/imcommon/enums/IMTerminalType.java

@ -9,7 +9,13 @@ import java.util.stream.Collectors;
@AllArgsConstructor @AllArgsConstructor
public enum IMTerminalType { public enum IMTerminalType {
/**
* web
*/
WEB(0, "web"), WEB(0, "web"),
/**
* app
*/
APP(1, "app"); APP(1, "app");
private final Integer code; private final Integer code;

17
im-commom/src/main/java/com/bx/imcommon/util/JwtUtil.java

@ -8,16 +8,20 @@ import com.auth0.jwt.exceptions.JWTVerificationException;
import java.util.Date; import java.util.Date;
public class JwtUtil { public final class JwtUtil {
private JwtUtil() {
}
/** /**
* 生成jwt字符串 JWT(json web token) * 生成jwt字符串 JWT(json web token)
*
* @param userId 用户id * @param userId 用户id
* @param info 用户细腻系 * @param info 用户细腻系
* @param expireIn 过期时间 * @param expireIn 过期时间
* @param secret 秘钥 * @param secret 秘钥
* @return token * @return token
* */ */
public static String sign(Long userId, String info, long expireIn, String secret) { public static String sign(Long userId, String info, long expireIn, String secret) {
try { try {
Date date = new Date(System.currentTimeMillis() + expireIn * 1000); Date date = new Date(System.currentTimeMillis() + expireIn * 1000);
@ -38,9 +42,10 @@ public class JwtUtil {
/** /**
* 根据token获取userId * 根据token获取userId
*
* @param token 登录token * @param token 登录token
* @return 用户id * @return 用户id
* */ */
public static Long getUserId(String token) { public static Long getUserId(String token) {
try { try {
String userId = JWT.decode(token).getAudience().get(0); String userId = JWT.decode(token).getAudience().get(0);
@ -52,9 +57,10 @@ public class JwtUtil {
/** /**
* 根据token获取用户数据 * 根据token获取用户数据
*
* @param token 用户登录token * @param token 用户登录token
* @return 用户数据 * @return 用户数据
* */ */
public static String getInfo(String token) { public static String getInfo(String token) {
try { try {
return JWT.decode(token).getClaim("info").asString(); return JWT.decode(token).getClaim("info").asString();
@ -65,10 +71,11 @@ public class JwtUtil {
/** /**
* 校验token * 校验token
*
* @param token 用户登录token * @param token 用户登录token
* @param secret 秘钥 * @param secret 秘钥
* @return true/false * @return true/false
* */ */
public static Boolean checkSign(String token, String secret) { public static Boolean checkSign(String token, String secret) {
try { try {
Algorithm algorithm = Algorithm.HMAC256(secret); Algorithm algorithm = Algorithm.HMAC256(secret);

100
im-commom/src/main/java/com/bx/imcommon/util/ThreadPoolExecutorFactory.java

@ -0,0 +1,100 @@
package com.bx.imcommon.util;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 创建单例线程池
* @author Andrews
* @date 2023/11/30 11:12
*/
public final class ThreadPoolExecutorFactory {
/**
* 机器的CPU核数:Runtime.getRuntime().availableProcessors()
* corePoolSize 池中所保存的线程数包括空闲线程
* CPU 密集型核心线程数 = CPU核数 + 1
* IO 密集型核心线程数 = CPU核数 * 2
*/
private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 2;
/**
* maximumPoolSize - 池中允许的最大线程数(采用LinkedBlockingQueue时没有作用)
*/
private static final int MAX_IMUM_POOL_SIZE = 100;
/**
* keepAliveTime -当线程数大于核心时此为终止前多余的空闲线程等待新任务的最长时间线程池维护线程所允许的空闲时间
*/
private static final int KEEP_ALIVE_TIME = 1000;
/**
* 等待队列的大小默认是无界的性能损耗的关键
*/
private static final int QUEUE_SIZE = 200;
/**
* 线程池对象
*/
private static volatile ThreadPoolExecutor threadPoolExecutor = null;
/**
* 构造方法私有化
*/
private ThreadPoolExecutorFactory() {
if (null == threadPoolExecutor) {
threadPoolExecutor = ThreadPoolExecutorFactory.getThreadPoolExecutor();
}
}
/**
* 重写readResolve方法
*/
private Object readResolve() {
//重写readResolve方法,防止序列化破坏单例
return ThreadPoolExecutorFactory.getThreadPoolExecutor();
}
/**
* 双检锁创建线程安全的单例
*/
public static ThreadPoolExecutor getThreadPoolExecutor() {
if (null == threadPoolExecutor) {
synchronized (ThreadPoolExecutorFactory.class) {
if (null == threadPoolExecutor) {
threadPoolExecutor = new ThreadPoolExecutor(
//核心线程数
CORE_POOL_SIZE,
//最大线程数,包含临时线程
MAX_IMUM_POOL_SIZE,
//临时线程的存活时间
KEEP_ALIVE_TIME,
//时间单位(毫秒)
TimeUnit.MILLISECONDS,
//等待队列
new LinkedBlockingQueue<>(QUEUE_SIZE),
//拒绝策略
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
}
}
return threadPoolExecutor;
}
/**
* 关闭线程池
*/
public void shutDown() {
if (threadPoolExecutor != null) {
threadPoolExecutor.shutdown();
}
}
public void execute(Runnable runnable) {
if (runnable == null) {
return;
}
threadPoolExecutor.execute(runnable);
}
}

1
im-platform/src/main/java/com/bx/implatform/IMPlatformApp.java

@ -7,7 +7,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Slf4j @Slf4j
@EnableAspectJAutoProxy(exposeProxy = true) @EnableAspectJAutoProxy(exposeProxy = true)
@MapperScan(basePackages = {"com.bx.implatform.mapper"}) @MapperScan(basePackages = {"com.bx.implatform.mapper"})

2
im-platform/src/main/java/com/bx/implatform/config/ICEServer.java

@ -1,9 +1,7 @@
package com.bx.implatform.config; package com.bx.implatform.config;
import lombok.Data; import lombok.Data;
@Data @Data
public class ICEServer { public class ICEServer {
private String urls; private String urls;

1
im-platform/src/main/java/com/bx/implatform/config/JwtProperties.java

@ -1,6 +1,5 @@
package com.bx.implatform.config; package com.bx.implatform.config;
import lombok.Data; import lombok.Data;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

1
im-platform/src/main/java/com/bx/implatform/config/MinIoClientConfig.java

@ -5,7 +5,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@Configuration @Configuration
public class MinIoClientConfig { public class MinIoClientConfig {

1
im-platform/src/main/java/com/bx/implatform/config/MvcConfig.java

@ -10,7 +10,6 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration @Configuration
@AllArgsConstructor @AllArgsConstructor
public class MvcConfig implements WebMvcConfigurer { public class MvcConfig implements WebMvcConfigurer {

4
im-platform/src/main/java/com/bx/implatform/config/RedisConfig.java

@ -26,7 +26,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.Duration; import java.time.Duration;
import java.util.Objects;
@EnableCaching @EnableCaching
@Configuration @Configuration
@ -68,7 +68,7 @@ public class RedisConfig extends CachingConfigurerSupport {
@Bean @Bean
@Override @Override
public CacheResolver cacheResolver() { public CacheResolver cacheResolver() {
return new SimpleCacheResolver(cacheManager()); return new SimpleCacheResolver(Objects.requireNonNull(cacheManager()));
} }
@Bean @Bean

1
im-platform/src/main/java/com/bx/implatform/config/SwaggerConfig.java

@ -11,7 +11,6 @@ import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2; import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration @Configuration
@EnableSwagger2 @EnableSwagger2
public class SwaggerConfig { public class SwaggerConfig {

17
im-platform/src/main/java/com/bx/implatform/contant/Constant.java

@ -1,12 +1,21 @@
package com.bx.implatform.contant; package com.bx.implatform.contant;
public final class Constant {
public class Constant { private Constant() {
// 最大图片上传大小 }
/**
* 最大图片上传大小
*/
public static final long MAX_IMAGE_SIZE = 5 * 1024 * 1024; public static final long MAX_IMAGE_SIZE = 5 * 1024 * 1024;
// 最大上传文件大小 /**
* 最大上传文件大小
*/
public static final long MAX_FILE_SIZE = 10 * 1024 * 1024; public static final long MAX_FILE_SIZE = 10 * 1024 * 1024;
// 群聊最大人数 /**
* 群聊最大人数
*/
public static final long MAX_GROUP_MEMBER = 500; public static final long MAX_GROUP_MEMBER = 500;
} }

41
im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java

@ -1,18 +1,33 @@
package com.bx.implatform.contant; package com.bx.implatform.contant;
public class RedisKey { public final class RedisKey {
// 已读群聊消息位置(已读最大id) private RedisKey() {
public final static String IM_GROUP_READED_POSITION = "im:readed:group:position"; }
// webrtc 会话信息
public final static String IM_WEBRTC_SESSION = "im:webrtc:session"; /**
// 缓存前缀 * 已读群聊消息位置(已读最大id)
public final static String IM_CACHE = "im:cache:"; */
// 缓存是否好友:bool public static final String IM_GROUP_READED_POSITION = "im:readed:group:position";
public final static String IM_CACHE_FRIEND = IM_CACHE+"friend"; /**
// 缓存群聊信息 * webrtc 会话信息
public final static String IM_CACHE_GROUP = IM_CACHE+"group"; */
// 缓存群聊成员id public static final String IM_WEBRTC_SESSION = "im:webrtc:session";
public final static String IM_CACHE_GROUP_MEMBER_ID = IM_CACHE+"group_member_ids"; /**
* 缓存前缀
*/
public static final String IM_CACHE = "im:cache:";
/**
* 缓存是否好友bool
*/
public static final String IM_CACHE_FRIEND = IM_CACHE + "friend";
/**
* 缓存群聊信息
*/
public static final String IM_CACHE_GROUP = IM_CACHE + "group";
/**
* 缓存群聊成员id
*/
public static final String IM_CACHE_GROUP_MEMBER_ID = IM_CACHE + "group_member_ids";
} }

7
im-platform/src/main/java/com/bx/implatform/controller/FileController.java

@ -6,20 +6,19 @@ import com.bx.implatform.service.thirdparty.FileService;
import com.bx.implatform.vo.UploadImageVO; import com.bx.implatform.vo.UploadImageVO;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@Slf4j @Slf4j
@RestController @RestController
@Api(tags = "文件上传") @Api(tags = "文件上传")
@AllArgsConstructor @RequiredArgsConstructor
public class FileController { public class FileController {
private FileService fileService; private final FileService fileService;
@ApiOperation(value = "上传图片", notes = "上传图片,上传后返回原图和缩略图的url") @ApiOperation(value = "上传图片", notes = "上传图片,上传后返回原图和缩略图的url")
@PostMapping("/image/upload") @PostMapping("/image/upload")

7
im-platform/src/main/java/com/bx/implatform/controller/FriendController.java

@ -8,7 +8,7 @@ import com.bx.implatform.session.SessionContext;
import com.bx.implatform.vo.FriendVO; import com.bx.implatform.vo.FriendVO;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
@ -19,10 +19,10 @@ import java.util.stream.Collectors;
@Api(tags = "好友") @Api(tags = "好友")
@RestController @RestController
@RequestMapping("/friend") @RequestMapping("/friend")
@AllArgsConstructor @RequiredArgsConstructor
public class FriendController { public class FriendController {
private IFriendService friendService; private final IFriendService friendService;
@GetMapping("/list") @GetMapping("/list")
@ApiOperation(value = "好友列表", notes = "获取好友列表") @ApiOperation(value = "好友列表", notes = "获取好友列表")
@ -39,7 +39,6 @@ public class FriendController {
} }
@PostMapping("/add") @PostMapping("/add")
@ApiOperation(value = "添加好友", notes = "双方建立好友关系") @ApiOperation(value = "添加好友", notes = "双方建立好友关系")
public Result addFriend(@NotEmpty(message = "好友id不可为空") @RequestParam("friendId") Long friendId) { public Result addFriend(@NotEmpty(message = "好友id不可为空") @RequestParam("friendId") Long friendId) {

7
im-platform/src/main/java/com/bx/implatform/controller/GroupController.java

@ -8,21 +8,20 @@ import com.bx.implatform.vo.GroupMemberVO;
import com.bx.implatform.vo.GroupVO; import com.bx.implatform.vo.GroupVO;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.util.List; import java.util.List;
@Api(tags = "群聊") @Api(tags = "群聊")
@RestController @RestController
@RequestMapping("/group") @RequestMapping("/group")
@AllArgsConstructor @RequiredArgsConstructor
public class GroupController { public class GroupController {
private IGroupService groupService; private final IGroupService groupService;
@ApiOperation(value = "创建群聊", notes = "创建群聊") @ApiOperation(value = "创建群聊", notes = "创建群聊")
@PostMapping("/create") @PostMapping("/create")

9
im-platform/src/main/java/com/bx/implatform/controller/GroupMessageController.java

@ -7,22 +7,20 @@ import com.bx.implatform.service.IGroupMessageService;
import com.bx.implatform.vo.GroupMessageVO; import com.bx.implatform.vo.GroupMessageVO;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.util.List; import java.util.List;
@Api(tags = "群聊消息") @Api(tags = "群聊消息")
@RestController @RestController
@RequestMapping("/message/group") @RequestMapping("/message/group")
@AllArgsConstructor @RequiredArgsConstructor
public class GroupMessageController { public class GroupMessageController {
private IGroupMessageService groupMessageService; private final IGroupMessageService groupMessageService;
@PostMapping("/send") @PostMapping("/send")
@ApiOperation(value = "发送群聊消息", notes = "发送群聊消息") @ApiOperation(value = "发送群聊消息", notes = "发送群聊消息")
@ -60,7 +58,6 @@ public class GroupMessageController {
} }
@GetMapping("/history") @GetMapping("/history")
@ApiOperation(value = "查询聊天记录", notes = "查询聊天记录") @ApiOperation(value = "查询聊天记录", notes = "查询聊天记录")
public Result<List<GroupMessageVO>> recallMessage(@NotNull(message = "群聊id不能为空") @RequestParam Long groupId, public Result<List<GroupMessageVO>> recallMessage(@NotNull(message = "群聊id不能为空") @RequestParam Long groupId,

8
im-platform/src/main/java/com/bx/implatform/controller/LoginController.java

@ -9,19 +9,17 @@ import com.bx.implatform.service.IUserService;
import com.bx.implatform.vo.LoginVO; import com.bx.implatform.vo.LoginVO;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
@Api(tags = "用户登录和注册") @Api(tags = "用户登录和注册")
@RestController @RestController
@AllArgsConstructor @RequiredArgsConstructor
public class LoginController { public class LoginController {
private IUserService userService; private final IUserService userService;
@PostMapping("/login") @PostMapping("/login")
@ApiOperation(value = "用户注册", notes = "用户注册") @ApiOperation(value = "用户注册", notes = "用户注册")

7
im-platform/src/main/java/com/bx/implatform/controller/PrivateMessageController.java

@ -7,7 +7,7 @@ import com.bx.implatform.service.IPrivateMessageService;
import com.bx.implatform.vo.PrivateMessageVO; import com.bx.implatform.vo.PrivateMessageVO;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
@ -17,10 +17,10 @@ import java.util.List;
@Api(tags = "私聊消息") @Api(tags = "私聊消息")
@RestController @RestController
@RequestMapping("/message/private") @RequestMapping("/message/private")
@AllArgsConstructor @RequiredArgsConstructor
public class PrivateMessageController { public class PrivateMessageController {
private IPrivateMessageService privateMessageService; private final IPrivateMessageService privateMessageService;
@PostMapping("/send") @PostMapping("/send")
@ApiOperation(value = "发送消息", notes = "发送私聊消息") @ApiOperation(value = "发送消息", notes = "发送私聊消息")
@ -36,7 +36,6 @@ public class PrivateMessageController {
return ResultUtils.success(); return ResultUtils.success();
} }
// todo 删除
@PostMapping("/pullUnreadMessage") @PostMapping("/pullUnreadMessage")
@ApiOperation(value = "拉取未读消息", notes = "拉取未读消息") @ApiOperation(value = "拉取未读消息", notes = "拉取未读消息")
public Result pullUnreadMessage() { public Result pullUnreadMessage() {

9
im-platform/src/main/java/com/bx/implatform/controller/UserController.java

@ -11,23 +11,20 @@ import com.bx.implatform.vo.OnlineTerminalVO;
import com.bx.implatform.vo.UserVO; import com.bx.implatform.vo.UserVO;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import java.util.List; import java.util.List;
@Api(tags = "用户") @Api(tags = "用户")
@RestController @RestController
@RequestMapping("/user") @RequestMapping("/user")
@AllArgsConstructor @RequiredArgsConstructor
public class UserController { public class UserController {
private IUserService userService; private final IUserService userService;
@GetMapping("/terminal/online") @GetMapping("/terminal/online")
@ApiOperation(value = "判断用户哪个终端在线", notes = "返回在线的用户id的终端集合") @ApiOperation(value = "判断用户哪个终端在线", notes = "返回在线的用户id的终端集合")

6
im-platform/src/main/java/com/bx/implatform/controller/WebrtcController.java

@ -6,7 +6,7 @@ import com.bx.implatform.result.ResultUtils;
import com.bx.implatform.service.IWebrtcService; import com.bx.implatform.service.IWebrtcService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@ -14,10 +14,10 @@ import java.util.List;
@Api(tags = "webrtc视频单人通话") @Api(tags = "webrtc视频单人通话")
@RestController @RestController
@RequestMapping("/webrtc/private") @RequestMapping("/webrtc/private")
@AllArgsConstructor @RequiredArgsConstructor
public class WebrtcController { public class WebrtcController {
private IWebrtcService webrtcService; private final IWebrtcService webrtcService;
@ApiOperation(httpMethod = "POST", value = "呼叫视频通话") @ApiOperation(httpMethod = "POST", value = "呼叫视频通话")
@PostMapping("/call") @PostMapping("/call")

2
im-platform/src/main/java/com/bx/implatform/dto/PrivateMessageDTO.java

@ -1,6 +1,5 @@
package com.bx.implatform.dto; package com.bx.implatform.dto;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@ -13,7 +12,6 @@ import javax.validation.constraints.NotNull;
@ApiModel("私聊消息DTO") @ApiModel("私聊消息DTO")
public class PrivateMessageDTO { public class PrivateMessageDTO {
@NotNull(message = "接收用户id不可为空") @NotNull(message = "接收用户id不可为空")
@ApiModelProperty(value = "接收用户id") @ApiModelProperty(value = "接收用户id")
private Long recvId; private Long recvId;

1
im-platform/src/main/java/com/bx/implatform/entity/Group.java

@ -13,6 +13,7 @@ import java.util.Date;
/** /**
* *
*
* @author blue * @author blue
* @since 2022-10-31 * @since 2022-10-31
*/ */

1
im-platform/src/main/java/com/bx/implatform/entity/GroupMember.java

@ -57,7 +57,6 @@ public class GroupMember extends Model<GroupMember> {
private String headImage; private String headImage;
/** /**
* 备注 * 备注
*/ */

14
im-platform/src/main/java/com/bx/implatform/enums/FileType.java

@ -5,13 +5,23 @@ import lombok.AllArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
public enum FileType { public enum FileType {
/**
* 文件
*/
FILE(0, "文件"), FILE(0, "文件"),
/**
* 图片
*/
IMAGE(1, "图片"), IMAGE(1, "图片"),
/**
* 视频
*/
VIDEO(2, "视频"), VIDEO(2, "视频"),
/**
* 声音
*/
AUDIO(3, "声音"); AUDIO(3, "声音");
private final Integer code; private final Integer code;
private final String desc; private final String desc;

12
im-platform/src/main/java/com/bx/implatform/enums/MessageStatus.java

@ -5,9 +5,21 @@ import lombok.AllArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
public enum MessageStatus { public enum MessageStatus {
/**
* 文件
*/
UNSEND(0, "未送达"), UNSEND(0, "未送达"),
/**
* 文件
*/
SENDED(1, "送达"), SENDED(1, "送达"),
/**
* 撤回
*/
RECALL(2, "撤回"), RECALL(2, "撤回"),
/**
* 已读
*/
READED(3, "已读"); READED(3, "已读");
private final Integer code; private final Integer code;

42
im-platform/src/main/java/com/bx/implatform/enums/MessageType.java

@ -5,20 +5,62 @@ import lombok.AllArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
public enum MessageType { public enum MessageType {
/**
* 文字
*/
TEXT(0, "文字"), TEXT(0, "文字"),
/**
* 图片
*/
IMAGE(1, "图片"), IMAGE(1, "图片"),
/**
* 文件
*/
FILE(2, "文件"), FILE(2, "文件"),
/**
* 音频
*/
AUDIO(3, "音频"), AUDIO(3, "音频"),
/**
* 视频
*/
VIDEO(4, "视频"), VIDEO(4, "视频"),
/**
* 撤回
*/
RECALL(10, "撤回"), RECALL(10, "撤回"),
/**
* 已读
*/
READED(11, "已读"), READED(11, "已读"),
/**
* 呼叫
*/
RTC_CALL(101, "呼叫"), RTC_CALL(101, "呼叫"),
/**
* 接受
*/
RTC_ACCEPT(102, "接受"), RTC_ACCEPT(102, "接受"),
/**
* 拒绝
*/
RTC_REJECT(103, "拒绝"), RTC_REJECT(103, "拒绝"),
/**
* 取消呼叫
*/
RTC_CANCEL(104, "取消呼叫"), RTC_CANCEL(104, "取消呼叫"),
/**
* 呼叫失败
*/
RTC_FAILED(105, "呼叫失败"), RTC_FAILED(105, "呼叫失败"),
/**
* 挂断
*/
RTC_HANDUP(106, "挂断"), RTC_HANDUP(106, "挂断"),
/**
* 同步candidate
*/
RTC_CANDIDATE(107, "同步candidate"); RTC_CANDIDATE(107, "同步candidate");
private final Integer code; private final Integer code;

29
im-platform/src/main/java/com/bx/implatform/enums/ResultCode.java

@ -8,23 +8,42 @@ import lombok.Getter;
* *
* @author Blue * @author Blue
* @date 2020/10/19 * @date 2020/10/19
*
**/ **/
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public enum ResultCode { public enum ResultCode {
/**
* 成功
*/
SUCCESS(200, "成功"), SUCCESS(200, "成功"),
/**
* 未登录
*/
NO_LOGIN(400, "未登录"), NO_LOGIN(400, "未登录"),
/**
* token无效或已过期
*/
INVALID_TOKEN(401, "token无效或已过期"), INVALID_TOKEN(401, "token无效或已过期"),
/**
* 系统繁忙请稍后再试
*/
PROGRAM_ERROR(500, "系统繁忙,请稍后再试"), PROGRAM_ERROR(500, "系统繁忙,请稍后再试"),
/**
* 密码不正确
*/
PASSWOR_ERROR(10001, "密码不正确"), PASSWOR_ERROR(10001, "密码不正确"),
/**
* 该用户名已注册
*/
USERNAME_ALREADY_REGISTER(10003, "该用户名已注册"), USERNAME_ALREADY_REGISTER(10003, "该用户名已注册"),
XSS_PARAM_ERROR(10004,"请不要输入非法内容"), /**
; * 请不要输入非法内容
*/
XSS_PARAM_ERROR(10004, "请不要输入非法内容");
private int code; private final int code;
private String msg; private final String msg;
} }

1
im-platform/src/main/java/com/bx/implatform/exception/GlobalException.java

@ -5,7 +5,6 @@ import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
@Data @Data
public class GlobalException extends RuntimeException implements Serializable { public class GlobalException extends RuntimeException implements Serializable {
private static final long serialVersionUID = 8134030011662574394L; private static final long serialVersionUID = 8134030011662574394L;

5
im-platform/src/main/java/com/bx/implatform/exception/GlobalExceptionHandler.java

@ -20,7 +20,6 @@ import java.lang.reflect.UndeclaredThrowableException;
import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException;
import java.util.List; import java.util.List;
@ControllerAdvice @ControllerAdvice
@ResponseBody @ResponseBody
@Slf4j @Slf4j
@ -32,8 +31,7 @@ public class GlobalExceptionHandler {
GlobalException ex = (GlobalException) e; GlobalException ex = (GlobalException) e;
log.error("全局异常捕获:msg:{},log:{},{}", ex.getMessage(), e); log.error("全局异常捕获:msg:{},log:{},{}", ex.getMessage(), e);
return ResultUtils.error(ex.getCode(), ex.getMessage()); return ResultUtils.error(ex.getCode(), ex.getMessage());
} } else if (e instanceof UndeclaredThrowableException) {
else if(e instanceof UndeclaredThrowableException) {
GlobalException ex = (GlobalException) e.getCause(); GlobalException ex = (GlobalException) e.getCause();
log.error("全局异常捕获:msg:{},log:{},{}", ex.getMessage(), e); log.error("全局异常捕获:msg:{},log:{},{}", ex.getMessage(), e);
return ResultUtils.error(ex.getCode(), ex.getMessage()); return ResultUtils.error(ex.getCode(), ex.getMessage());
@ -63,6 +61,7 @@ public class GlobalExceptionHandler {
/** /**
* 处理请求参数格式错误 @RequestBody上validate失败后抛出的异常 * 处理请求参数格式错误 @RequestBody上validate失败后抛出的异常
*
* @param exception * @param exception
* @return * @return
*/ */

6
im-platform/src/main/java/com/bx/implatform/filter/CacheFilter.java

@ -14,10 +14,12 @@ import java.io.IOException;
public class CacheFilter implements Filter { public class CacheFilter implements Filter {
@Override @Override
public void init(FilterConfig filterConfig) {} public void init(FilterConfig filterConfig) {
}
@Override @Override
public void destroy() {} public void destroy() {
}
@Override @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

3
im-platform/src/main/java/com/bx/implatform/interceptor/AuthInterceptor.java

@ -9,6 +9,7 @@ import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.session.UserSession; import com.bx.implatform.session.UserSession;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;
@ -24,7 +25,7 @@ public class AuthInterceptor implements HandlerInterceptor {
private final JwtProperties jwtProperties; private final JwtProperties jwtProperties;
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
//如果不是映射到方法直接通过 //如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) { if (!(handler instanceof HandlerMethod)) {
return true; return true;

3
im-platform/src/main/java/com/bx/implatform/interceptor/XssInterceptor.java

@ -5,6 +5,7 @@ import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.util.XssUtil; import com.bx.implatform.util.XssUtil;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;
@ -18,7 +19,7 @@ import java.util.Map;
public class XssInterceptor implements HandlerInterceptor { public class XssInterceptor implements HandlerInterceptor {
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) {
// 检查参数 // 检查参数
Map<String, String[]> paramMap = request.getParameterMap(); Map<String, String[]> paramMap = request.getParameterMap();
for (String[] values : paramMap.values()) { for (String[] values : paramMap.values()) {

4
im-platform/src/main/java/com/bx/implatform/listener/GroupMessageListener.java

@ -11,18 +11,16 @@ import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@Slf4j @Slf4j
@IMListener(type = IMListenerType.GROUP_MESSAGE) @IMListener(type = IMListenerType.GROUP_MESSAGE)
@AllArgsConstructor @AllArgsConstructor
public class GroupMessageListener implements MessageListener<GroupMessageVO> { public class GroupMessageListener implements MessageListener<GroupMessageVO> {
private RedisTemplate<String,Object> redisTemplate; private final RedisTemplate<String, Object> redisTemplate;
@Override @Override
public void process(IMSendResult<GroupMessageVO> result) { public void process(IMSendResult<GroupMessageVO> result) {
GroupMessageVO messageInfo = result.getData(); GroupMessageVO messageInfo = result.getData();
// todo 删除
// 保存该用户已拉取的最大消息id // 保存该用户已拉取的最大消息id
if (result.getCode().equals(IMSendCode.SUCCESS.code())) { if (result.getCode().equals(IMSendCode.SUCCESS.code())) {
String key = String.join(":", RedisKey.IM_GROUP_READED_POSITION, messageInfo.getGroupId().toString(), result.getReceiver().getId().toString()); String key = String.join(":", RedisKey.IM_GROUP_READED_POSITION, messageInfo.getGroupId().toString(), result.getReceiver().getId().toString());

1
im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java

@ -14,7 +14,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@Slf4j @Slf4j
@IMListener(type = IMListenerType.PRIVATE_MESSAGE) @IMListener(type = IMListenerType.PRIVATE_MESSAGE)
public class PrivateMessageListener implements MessageListener<PrivateMessageVO> { public class PrivateMessageListener implements MessageListener<PrivateMessageVO> {

1
im-platform/src/main/java/com/bx/implatform/mapper/FriendMapper.java

@ -3,7 +3,6 @@ package com.bx.implatform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.Friend; import com.bx.implatform.entity.Friend;
public interface FriendMapper extends BaseMapper<Friend> { public interface FriendMapper extends BaseMapper<Friend> {
} }

1
im-platform/src/main/java/com/bx/implatform/mapper/GroupMapper.java

@ -3,7 +3,6 @@ package com.bx.implatform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.Group; import com.bx.implatform.entity.Group;
public interface GroupMapper extends BaseMapper<Group> { public interface GroupMapper extends BaseMapper<Group> {
} }

1
im-platform/src/main/java/com/bx/implatform/mapper/GroupMemberMapper.java

@ -3,7 +3,6 @@ package com.bx.implatform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.GroupMember; import com.bx.implatform.entity.GroupMember;
public interface GroupMemberMapper extends BaseMapper<GroupMember> { public interface GroupMemberMapper extends BaseMapper<GroupMember> {
} }

1
im-platform/src/main/java/com/bx/implatform/mapper/GroupMessageMapper.java

@ -3,7 +3,6 @@ package com.bx.implatform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.GroupMessage; import com.bx.implatform.entity.GroupMessage;
public interface GroupMessageMapper extends BaseMapper<GroupMessage> { public interface GroupMessageMapper extends BaseMapper<GroupMessage> {
} }

1
im-platform/src/main/java/com/bx/implatform/mapper/PrivateMessageMapper.java

@ -3,7 +3,6 @@ package com.bx.implatform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.PrivateMessage; import com.bx.implatform.entity.PrivateMessage;
public interface PrivateMessageMapper extends BaseMapper<PrivateMessage> { public interface PrivateMessageMapper extends BaseMapper<PrivateMessage> {
} }

1
im-platform/src/main/java/com/bx/implatform/mapper/UserMapper.java

@ -3,7 +3,6 @@ package com.bx.implatform.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bx.implatform.entity.User; import com.bx.implatform.entity.User;
public interface UserMapper extends BaseMapper<User> { public interface UserMapper extends BaseMapper<User> {
} }

2
im-platform/src/main/java/com/bx/implatform/result/Result.java

@ -2,11 +2,9 @@ package com.bx.implatform.result;
import lombok.Data; import lombok.Data;
@Data @Data
public class Result<T> { public class Result<T> {
private int code; private int code;
private String message; private String message;

7
im-platform/src/main/java/com/bx/implatform/result/ResultUtils.java

@ -1,9 +1,11 @@
package com.bx.implatform.result; package com.bx.implatform.result;
import com.bx.implatform.enums.ResultCode; import com.bx.implatform.enums.ResultCode;
public class ResultUtils { public final class ResultUtils {
private ResultUtils() {
}
public static <T> Result<T> success() { public static <T> Result<T> success() {
Result<T> result = new Result<>(); Result<T> result = new Result<>();
@ -58,5 +60,4 @@ public class ResultUtils {
} }
} }

1
im-platform/src/main/java/com/bx/implatform/service/IFriendService.java

@ -6,7 +6,6 @@ import com.bx.implatform.vo.FriendVO;
import java.util.List; import java.util.List;
public interface IFriendService extends IService<Friend> { public interface IFriendService extends IService<Friend> {
/** /**

2
im-platform/src/main/java/com/bx/implatform/service/IGroupMemberService.java

@ -5,10 +5,8 @@ import com.bx.implatform.entity.GroupMember;
import java.util.List; import java.util.List;
public interface IGroupMemberService extends IService<GroupMember> { public interface IGroupMemberService extends IService<GroupMember> {
/** /**
* 根据群聊id和用户id查询群聊成员 * 根据群聊id和用户id查询群聊成员
* *

2
im-platform/src/main/java/com/bx/implatform/service/IGroupMessageService.java

@ -7,7 +7,6 @@ import com.bx.implatform.vo.GroupMessageVO;
import java.util.List; import java.util.List;
public interface IGroupMessageService extends IService<GroupMessage> { public interface IGroupMessageService extends IService<GroupMessage> {
/** /**
@ -26,7 +25,6 @@ public interface IGroupMessageService extends IService<GroupMessage> {
void recallMessage(Long id); void recallMessage(Long id);
/** /**
*
* 异步拉取群聊消息通过websocket异步推送 * 异步拉取群聊消息通过websocket异步推送
*/ */
void pullUnreadMessage(); void pullUnreadMessage();

1
im-platform/src/main/java/com/bx/implatform/service/IGroupService.java

@ -8,7 +8,6 @@ import com.bx.implatform.vo.GroupVO;
import java.util.List; import java.util.List;
public interface IGroupService extends IService<Group> { public interface IGroupService extends IService<Group> {
/** /**

1
im-platform/src/main/java/com/bx/implatform/service/IPrivateMessageService.java

@ -7,7 +7,6 @@ import com.bx.implatform.vo.PrivateMessageVO;
import java.util.List; import java.util.List;
public interface IPrivateMessageService extends IService<PrivateMessage> { public interface IPrivateMessageService extends IService<PrivateMessage> {
/** /**

1
im-platform/src/main/java/com/bx/implatform/service/IUserService.java

@ -11,7 +11,6 @@ import com.bx.implatform.vo.UserVO;
import java.util.List; import java.util.List;
public interface IUserService extends IService<User> { public interface IUserService extends IService<User> {
/** /**

3
im-platform/src/main/java/com/bx/implatform/service/IWebrtcService.java

@ -5,9 +5,9 @@ import org.springframework.web.bind.annotation.RequestBody;
import java.util.List; import java.util.List;
/** /**
* webrtc 通信服务 * webrtc 通信服务
*
* @author * @author
*/ */
public interface IWebrtcService { public interface IWebrtcService {
@ -29,5 +29,4 @@ public interface IWebrtcService {
List<ICEServer> getIceServers(); List<ICEServer> getIceServers();
} }

10
im-platform/src/main/java/com/bx/implatform/service/impl/FriendServiceImpl.java

@ -15,7 +15,7 @@ import com.bx.implatform.service.IFriendService;
import com.bx.implatform.session.SessionContext; import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession; import com.bx.implatform.session.UserSession;
import com.bx.implatform.vo.FriendVO; import com.bx.implatform.vo.FriendVO;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext; import org.springframework.aop.framework.AopContext;
import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheConfig;
@ -26,10 +26,9 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
@Slf4j @Slf4j
@Service @Service
@AllArgsConstructor @RequiredArgsConstructor
@CacheConfig(cacheNames = RedisKey.IM_CACHE_FRIEND) @CacheConfig(cacheNames = RedisKey.IM_CACHE_FRIEND)
public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> implements IFriendService { public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> implements IFriendService {
@ -43,7 +42,6 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
} }
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public void addFriend(Long friendId) { public void addFriend(Long friendId) {
@ -59,7 +57,6 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
} }
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public void delFriend(Long friendId) { public void delFriend(Long friendId) {
@ -72,7 +69,6 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
} }
@Cacheable(key = "#userId1+':'+#userId2") @Cacheable(key = "#userId1+':'+#userId2")
@Override @Override
public Boolean isFriend(Long userId1, Long userId2) { public Boolean isFriend(Long userId1, Long userId2) {
@ -84,7 +80,6 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
} }
@Override @Override
public void update(FriendVO vo) { public void update(FriendVO vo) {
long userId = SessionContext.getSession().getUserId(); long userId = SessionContext.getSession().getUserId();
@ -145,7 +140,6 @@ public class FriendServiceImpl extends ServiceImpl<FriendMapper, Friend> impleme
} }
@Override @Override
public FriendVO findFriend(Long friendId) { public FriendVO findFriend(Long friendId) {
UserSession session = SessionContext.getSession(); UserSession session = SessionContext.getSession();

1
im-platform/src/main/java/com/bx/implatform/service/impl/GroupMemberServiceImpl.java

@ -17,7 +17,6 @@ import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@CacheConfig(cacheNames = RedisKey.IM_CACHE_GROUP_MEMBER_ID) @CacheConfig(cacheNames = RedisKey.IM_CACHE_GROUP_MEMBER_ID)
public class GroupMemberServiceImpl extends ServiceImpl<GroupMemberMapper, GroupMember> implements IGroupMemberService { public class GroupMemberServiceImpl extends ServiceImpl<GroupMemberMapper, GroupMember> implements IGroupMemberService {

19
im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java

@ -1,7 +1,8 @@
package com.bx.implatform.service.impl; package com.bx.implatform.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@ -28,8 +29,10 @@ import com.bx.implatform.session.UserSession;
import com.bx.implatform.util.BeanUtils; import com.bx.implatform.util.BeanUtils;
import com.bx.implatform.util.DateTimeUtils; import com.bx.implatform.util.DateTimeUtils;
import com.bx.implatform.vo.GroupMessageVO; import com.bx.implatform.vo.GroupMessageVO;
import lombok.AllArgsConstructor; import com.google.common.base.Splitter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -38,7 +41,7 @@ import java.util.stream.Collectors;
@Slf4j @Slf4j
@Service @Service
@AllArgsConstructor @RequiredArgsConstructor
public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, GroupMessage> implements IGroupMessageService { public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, GroupMessage> implements IGroupMessageService {
private final IGroupService groupService; private final IGroupService groupService;
private final IGroupMemberService groupMemberService; private final IGroupMemberService groupMemberService;
@ -69,8 +72,8 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
msg.setSendId(session.getUserId()); msg.setSendId(session.getUserId());
msg.setSendTime(new Date()); msg.setSendTime(new Date());
msg.setSendNickName(member.getAliasName()); msg.setSendNickName(member.getAliasName());
if (CollectionUtil.isNotEmpty(dto.getAtUserIds())) { if (CollUtil.isNotEmpty(dto.getAtUserIds())) {
msg.setAtUserIds(StrUtil.join(",", dto.getAtUserIds())); msg.setAtUserIds(CharSequenceUtil.join(",", dto.getAtUserIds()));
} }
this.save(msg); this.save(msg);
// 群发 // 群发
@ -188,8 +191,10 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
List<GroupMessageVO> vos = messages.stream().map(m -> { List<GroupMessageVO> vos = messages.stream().map(m -> {
GroupMessageVO vo = BeanUtils.copyProperties(m, GroupMessageVO.class); GroupMessageVO vo = BeanUtils.copyProperties(m, GroupMessageVO.class);
// 被@用户列表 // 被@用户列表
List<String> atIds = Arrays.asList(StrUtil.split(m.getAtUserIds(), ",")); if (StringUtils.isNotBlank(m.getAtUserIds())) {
List<String> atIds = Splitter.on(",").trimResults().splitToList(m.getAtUserIds());
vo.setAtUserIds(atIds.stream().map(Long::parseLong).collect(Collectors.toList())); vo.setAtUserIds(atIds.stream().map(Long::parseLong).collect(Collectors.toList()));
}
return vo; return vo;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
// 消息状态,数据库没有存群聊的消息状态,需要从redis取 // 消息状态,数据库没有存群聊的消息状态,需要从redis取
@ -237,7 +242,7 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
sendMessage.setSendResult(false); sendMessage.setSendResult(false);
imClient.sendGroupMessage(sendMessage); imClient.sendGroupMessage(sendMessage);
// 记录已读消息位置 // 记录已读消息位置
String key = StrUtil.join(":", RedisKey.IM_GROUP_READED_POSITION, groupId, session.getUserId()); String key = CharSequenceUtil.join(":", RedisKey.IM_GROUP_READED_POSITION, groupId, session.getUserId());
redisTemplate.opsForValue().set(key, message.getId()); redisTemplate.opsForValue().set(key, message.getId());
} }

11
im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java

@ -23,7 +23,7 @@ import com.bx.implatform.util.BeanUtils;
import com.bx.implatform.vo.GroupInviteVO; import com.bx.implatform.vo.GroupInviteVO;
import com.bx.implatform.vo.GroupMemberVO; import com.bx.implatform.vo.GroupMemberVO;
import com.bx.implatform.vo.GroupVO; import com.bx.implatform.vo.GroupVO;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheConfig;
@ -32,16 +32,13 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.Date; import java.util.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Slf4j @Slf4j
@CacheConfig(cacheNames = RedisKey.IM_CACHE_GROUP) @CacheConfig(cacheNames = RedisKey.IM_CACHE_GROUP)
@Service @Service
@AllArgsConstructor @RequiredArgsConstructor
public class GroupServiceImpl extends ServiceImpl<GroupMapper, Group> implements IGroupService { public class GroupServiceImpl extends ServiceImpl<GroupMapper, Group> implements IGroupService {
private final IUserService userService; private final IUserService userService;
private final IGroupMemberService groupMemberService; private final IGroupMemberService groupMemberService;
@ -90,7 +87,7 @@ public class GroupServiceImpl extends ServiceImpl<GroupMapper, Group> implements
throw new GlobalException(ResultCode.PROGRAM_ERROR, "您不是群聊的成员"); throw new GlobalException(ResultCode.PROGRAM_ERROR, "您不是群聊的成员");
} }
member.setAliasName(StringUtils.isEmpty(vo.getAliasName()) ? session.getNickName() : vo.getAliasName()); member.setAliasName(StringUtils.isEmpty(vo.getAliasName()) ? session.getNickName() : vo.getAliasName());
member.setRemark(StringUtils.isEmpty(vo.getRemark()) ? group.getName() : vo.getRemark()); member.setRemark(StringUtils.isEmpty(vo.getRemark()) ? Objects.requireNonNull(group).getName() : vo.getRemark());
groupMemberService.updateById(member); groupMemberService.updateById(member);
log.info("修改群聊,群聊id:{},群聊名称:{}", group.getId(), group.getName()); log.info("修改群聊,群聊id:{},群聊名称:{}", group.getId(), group.getName());
return vo; return vo;

8
im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java

@ -25,6 +25,7 @@ import com.bx.implatform.util.BeanUtils;
import com.bx.implatform.util.DateTimeUtils; import com.bx.implatform.util.DateTimeUtils;
import com.bx.implatform.vo.PrivateMessageVO; import com.bx.implatform.vo.PrivateMessageVO;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -37,7 +38,7 @@ import java.util.stream.Collectors;
@Slf4j @Slf4j
@Service @Service
@AllArgsConstructor @RequiredArgsConstructor
public class PrivateMessageServiceImpl extends ServiceImpl<PrivateMessageMapper, PrivateMessage> implements IPrivateMessageService { public class PrivateMessageServiceImpl extends ServiceImpl<PrivateMessageMapper, PrivateMessage> implements IPrivateMessageService {
private final IFriendService friendService; private final IFriendService friendService;
@ -47,7 +48,7 @@ public class PrivateMessageServiceImpl extends ServiceImpl<PrivateMessageMapper,
public Long sendMessage(PrivateMessageDTO dto) { public Long sendMessage(PrivateMessageDTO dto) {
UserSession session = SessionContext.getSession(); UserSession session = SessionContext.getSession();
Boolean isFriends = friendService.isFriend(session.getUserId(), dto.getRecvId()); Boolean isFriends = friendService.isFriend(session.getUserId(), dto.getRecvId());
if (!isFriends) { if (Boolean.FALSE.equals(isFriends)) {
throw new GlobalException(ResultCode.PROGRAM_ERROR, "您已不是对方好友,无法发送消息"); throw new GlobalException(ResultCode.PROGRAM_ERROR, "您已不是对方好友,无法发送消息");
} }
// 保存消息 // 保存消息
@ -107,7 +108,6 @@ public class PrivateMessageServiceImpl extends ServiceImpl<PrivateMessageMapper,
} }
@Override @Override
public List<PrivateMessageVO> findHistoryMessage(Long friendId, Long page, Long size) { public List<PrivateMessageVO> findHistoryMessage(Long friendId, Long page, Long size) {
page = page > 0 ? page : 1; page = page > 0 ? page : 1;
@ -167,7 +167,6 @@ public class PrivateMessageServiceImpl extends ServiceImpl<PrivateMessageMapper,
} }
@Override @Override
public List<PrivateMessageVO> loadMessage(Long minId) { public List<PrivateMessageVO> loadMessage(Long minId) {
UserSession session = SessionContext.getSession(); UserSession session = SessionContext.getSession();
@ -208,7 +207,6 @@ public class PrivateMessageServiceImpl extends ServiceImpl<PrivateMessageMapper,
} }
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public void readedMessage(Long friendId) { public void readedMessage(Long friendId) {

6
im-platform/src/main/java/com/bx/implatform/service/impl/UserServiceImpl.java

@ -27,9 +27,8 @@ import com.bx.implatform.util.BeanUtils;
import com.bx.implatform.vo.LoginVO; import com.bx.implatform.vo.LoginVO;
import com.bx.implatform.vo.OnlineTerminalVO; import com.bx.implatform.vo.OnlineTerminalVO;
import com.bx.implatform.vo.UserVO; import com.bx.implatform.vo.UserVO;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -39,10 +38,9 @@ import java.util.stream.Collectors;
@Slf4j @Slf4j
@Service @Service
@AllArgsConstructor @RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
private final RedisTemplate<String, Object> redisTemplate;
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
private final IGroupMemberService groupMemberService; private final IGroupMemberService groupMemberService;
private final IFriendService friendService; private final IFriendService friendService;

4
im-platform/src/main/java/com/bx/implatform/service/impl/WebrtcServiceImpl.java

@ -13,7 +13,7 @@ import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession; import com.bx.implatform.session.UserSession;
import com.bx.implatform.session.WebrtcSession; import com.bx.implatform.session.WebrtcSession;
import com.bx.implatform.vo.PrivateMessageVO; import com.bx.implatform.vo.PrivateMessageVO;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
@Service @Service
@AllArgsConstructor @RequiredArgsConstructor
public class WebrtcServiceImpl implements IWebrtcService { public class WebrtcServiceImpl implements IWebrtcService {
private final IMClient imClient; private final IMClient imClient;

7
im-platform/src/main/java/com/bx/implatform/service/thirdparty/FileService.java

@ -18,13 +18,14 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
/** /**
* todo 通过校验文件MD5实现重复文件秒传 * 通过校验文件MD5实现重复文件秒传
* 文件上传服务 * 文件上传服务
*
* @author Blue * @author Blue
* @date 2022/10/28 * @date 2022/10/28
*
*/ */
@Slf4j @Slf4j
@Service @Service
@ -89,7 +90,7 @@ public class FileService {
// 大于30K的文件需上传缩略图 // 大于30K的文件需上传缩略图
if (file.getSize() > 30 * 1024) { if (file.getSize() > 30 * 1024) {
byte[] imageByte = ImageUtil.compressForScale(file.getBytes(), 30); byte[] imageByte = ImageUtil.compressForScale(file.getBytes(), 30);
fileName = minioUtil.upload(bucketName,imagePath,file.getOriginalFilename(),imageByte,file.getContentType()); fileName = minioUtil.upload(bucketName, imagePath, Objects.requireNonNull(file.getOriginalFilename()), imageByte, file.getContentType());
if (StringUtils.isEmpty(fileName)) { if (StringUtils.isEmpty(fileName)) {
throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片上传失败"); throw new GlobalException(ResultCode.PROGRAM_ERROR, "图片上传失败");
} }

7
im-platform/src/main/java/com/bx/implatform/session/SessionContext.java

@ -12,14 +12,11 @@ import javax.servlet.http.HttpServletRequest;
*/ */
public class SessionContext { public class SessionContext {
public static UserSession getSession() { public static UserSession getSession() {
// 从请求上下文里获取Request对象 // 从请求上下文里获取Request对象
ServletRequestAttributes requestAttributes = ServletRequestAttributes.class. ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
cast(RequestContextHolder.getRequestAttributes());
HttpServletRequest request = requestAttributes.getRequest(); HttpServletRequest request = requestAttributes.getRequest();
UserSession userSession = (UserSession) request.getAttribute("session"); return (UserSession) request.getAttribute("session");
return userSession;
} }
} }

8
im-platform/src/main/java/com/bx/implatform/session/UserSession.java

@ -2,18 +2,18 @@ package com.bx.implatform.session;
import com.bx.imcommon.model.IMSessionInfo; import com.bx.imcommon.model.IMSessionInfo;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data @Data
public class UserSession extends IMSessionInfo { public class UserSession extends IMSessionInfo {
/* /**
* 用户名称 * 用户名称
*/ */
private String userName; private String userName;
/* /**
* 用户昵称 * 用户昵称
*/ */
private String nickName; private String nickName;

11
im-platform/src/main/java/com/bx/implatform/util/BeanUtils.java

@ -1,9 +1,11 @@
package com.bx.implatform.util; package com.bx.implatform.util;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils;
public class BeanUtils { public final class BeanUtils {
private BeanUtils() {
}
private static void handleReflectionException(Exception e) { private static void handleReflectionException(Exception e) {
ReflectionUtils.handleReflectionException(e); ReflectionUtils.handleReflectionException(e);
@ -12,18 +14,19 @@ public class BeanUtils {
/** /**
* 属性拷贝 * 属性拷贝
*
* @param orig 源对象 * @param orig 源对象
* @param destClass 目标 * @param destClass 目标
* @return T * @return T
*/ */
public static <T> T copyProperties(Object orig, Class<T> destClass) { public static <T> T copyProperties(Object orig, Class<T> destClass) {
try { try {
Object target = destClass.newInstance(); T target = destClass.newInstance();
if (orig == null) { if (orig == null) {
return null; return null;
} }
copyProperties(orig, target); copyProperties(orig, target);
return (T) target; return target;
} catch (Exception e) { } catch (Exception e) {
handleReflectionException(e); handleReflectionException(e);
return null; return null;

5
im-platform/src/main/java/com/bx/implatform/util/DateTimeUtils.java

@ -11,7 +11,10 @@ import java.util.Date;
* *
* @version 1.0 * @version 1.0
*/ */
public class DateTimeUtils extends DateUtils { public final class DateTimeUtils extends DateUtils {
private DateTimeUtils() {
}
public static final String FULL_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; public static final String FULL_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String PARTDATEFORMAT = "yyyyMMdd"; public static final String PARTDATEFORMAT = "yyyyMMdd";

5
im-platform/src/main/java/com/bx/implatform/util/FileUtil.java

@ -1,6 +1,9 @@
package com.bx.implatform.util; package com.bx.implatform.util;
public class FileUtil { public final class FileUtil {
private FileUtil() {
}
/** /**
* 获取文件后缀 * 获取文件后缀

8
im-platform/src/main/java/com/bx/implatform/util/ImageUtil.java

@ -1,6 +1,5 @@
package com.bx.implatform.util; package com.bx.implatform.util;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails; import net.coobird.thumbnailator.Thumbnails;
@ -8,7 +7,10 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@Slf4j @Slf4j
public class ImageUtil { public final class ImageUtil {
private ImageUtil() {
}
//以下是常量,按照阿里代码开发规范,不允许代码中出现魔法值 //以下是常量,按照阿里代码开发规范,不允许代码中出现魔法值
private static final Integer ZERO = 0; private static final Integer ZERO = 0;
@ -53,8 +55,6 @@ public class ImageUtil {
} }
/** /**
* 自动调节精度(经验数值) * 自动调节精度(经验数值)
* *

9
im-platform/src/main/java/com/bx/implatform/util/MinioUtil.java

@ -1,8 +1,7 @@
package com.bx.implatform.util; package com.bx.implatform.util;
import io.minio.*; import io.minio.*;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -14,13 +13,14 @@ import java.util.Date;
@Slf4j @Slf4j
@Component @Component
@AllArgsConstructor @RequiredArgsConstructor
public class MinioUtil { public class MinioUtil {
private final MinioClient minioClient; private final MinioClient minioClient;
/** /**
* 查看存储bucket是否存在 * 查看存储bucket是否存在
*
* @return boolean * @return boolean
*/ */
public Boolean bucketExists(String bucketName) { public Boolean bucketExists(String bucketName) {
@ -70,6 +70,7 @@ public class MinioUtil {
/** /**
* 文件上传 * 文件上传
*
* @param bucketName bucket名称 * @param bucketName bucket名称
* @param path 路径 * @param path 路径
* @param file 文件 * @param file 文件
@ -99,6 +100,7 @@ public class MinioUtil {
/** /**
* 文件上传 * 文件上传
*
* @param bucketName bucket名称 * @param bucketName bucket名称
* @param path 路径 * @param path 路径
* @param name 文件名 * @param name 文件名
@ -126,6 +128,7 @@ public class MinioUtil {
/** /**
* 删除 * 删除
*
* @param bucketName bucket名称 * @param bucketName bucket名称
* @param path 路径 * @param path 路径
* @param fileName 文件名 * @param fileName 文件名

5
im-platform/src/main/java/com/bx/implatform/util/XssUtil.java

@ -3,7 +3,10 @@ package com.bx.implatform.util;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class XssUtil { public final class XssUtil {
private XssUtil() {
}
private static final String XSS_PATTERN = "((?i)<script.*?>)|((?i)alert\\s*\\()|((?i)prompt\\s*\\()|((?i)document\\.cookie)|((?i)location\\.href)|((?i)window\\.location)|((?i)onerror\\s*\\()|((?i)eval\\s*\\()|((?i)window\\.open\\s*\\()|((?i)innerHTML)|((?i)onclick\\s*\\()|((?i)onmouseover\\s*\\()|((?i)onsubmit\\s*\\()|((?i)onload\\s*\\()|((?i)onfocus\\s*\\()|((?i)onblur\\s*\\()|((?i)onkeyup\\s*\\()|((?i)onkeydown\\s*\\()|((?i)onkeypress\\s*\\()|((?i)onmouseout\\s*\\()|((?i)src=)|((?i)href=)|((?i)style=)|((?i)background=)|((?i)expression\\s*\\()|((?i)XMLHttpRequest\\s*\\()|((?i)ActiveXObject\\s*\\()|((?i)iframe)|((?i)document\\.write\\s*\\()|((?i)document\\.writeln\\s*\\()|((?i)setTimeout\\s*\\()|((?i)setInterval\\s*\\()|((?i)onreadystatechange\\s*\\()|((?i)appendChild\\s*\\()|((?i)createTextNode\\s*\\()|((?i)createElement\\s*\\()|((?i)getElementsByTagName\\s*\\()|((?i)getElementsByClassName\\s*\\()|((?i)querySelector\\s*\\()|((?i)querySelectorAll\\s*\\()|((?i)document\\.location)|((?i)document\\.body\\.innerHTML)|((?i)document\\.forms)|((?i)document\\.images)|((?i)document\\.links)|((?i)document\\.URL)|((?i)document\\.domain)|((?i)document\\.referrer)|((?i)history\\.back\\s*\\()"; private static final String XSS_PATTERN = "((?i)<script.*?>)|((?i)alert\\s*\\()|((?i)prompt\\s*\\()|((?i)document\\.cookie)|((?i)location\\.href)|((?i)window\\.location)|((?i)onerror\\s*\\()|((?i)eval\\s*\\()|((?i)window\\.open\\s*\\()|((?i)innerHTML)|((?i)onclick\\s*\\()|((?i)onmouseover\\s*\\()|((?i)onsubmit\\s*\\()|((?i)onload\\s*\\()|((?i)onfocus\\s*\\()|((?i)onblur\\s*\\()|((?i)onkeyup\\s*\\()|((?i)onkeydown\\s*\\()|((?i)onkeypress\\s*\\()|((?i)onmouseout\\s*\\()|((?i)src=)|((?i)href=)|((?i)style=)|((?i)background=)|((?i)expression\\s*\\()|((?i)XMLHttpRequest\\s*\\()|((?i)ActiveXObject\\s*\\()|((?i)iframe)|((?i)document\\.write\\s*\\()|((?i)document\\.writeln\\s*\\()|((?i)setTimeout\\s*\\()|((?i)setInterval\\s*\\()|((?i)onreadystatechange\\s*\\()|((?i)appendChild\\s*\\()|((?i)createTextNode\\s*\\()|((?i)createElement\\s*\\()|((?i)getElementsByTagName\\s*\\()|((?i)getElementsByClassName\\s*\\()|((?i)querySelector\\s*\\()|((?i)querySelectorAll\\s*\\()|((?i)document\\.location)|((?i)document\\.body\\.innerHTML)|((?i)document\\.forms)|((?i)document\\.images)|((?i)document\\.links)|((?i)document\\.URL)|((?i)document\\.domain)|((?i)document\\.referrer)|((?i)history\\.back\\s*\\()";
private static final Pattern PATTERN = Pattern.compile(XSS_PATTERN); private static final Pattern PATTERN = Pattern.compile(XSS_PATTERN);

1
im-platform/src/main/java/com/bx/implatform/vo/FriendVO.java

@ -1,6 +1,5 @@
package com.bx.implatform.vo; package com.bx.implatform.vo;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;

1
im-platform/src/main/java/com/bx/implatform/vo/GroupMemberVO.java

@ -1,6 +1,5 @@
package com.bx.implatform.vo; package com.bx.implatform.vo;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;

1
im-platform/src/main/java/com/bx/implatform/vo/GroupVO.java

@ -11,7 +11,6 @@ import javax.validation.constraints.NotEmpty;
@ApiModel("群信息VO") @ApiModel("群信息VO")
public class GroupVO { public class GroupVO {
@ApiModelProperty(value = "群id") @ApiModelProperty(value = "群id")
private Long id; private Long id;

1
im-platform/src/main/java/com/bx/implatform/vo/UserVO.java

@ -1,6 +1,5 @@
package com.bx.implatform.vo; package com.bx.implatform.vo;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;

3
im-server/src/main/java/com/bx/imserver/IMServerApp.java

@ -1,20 +1,17 @@
package com.bx.imserver; package com.bx.imserver;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
@EnableAsync @EnableAsync
@EnableScheduling @EnableScheduling
@ComponentScan(basePackages = {"com.bx"}) @ComponentScan(basePackages = {"com.bx"})
@SpringBootApplication @SpringBootApplication
public class IMServerApp { public class IMServerApp {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(IMServerApp.class, args); SpringApplication.run(IMServerApp.class, args);
} }

17
im-server/src/main/java/com/bx/imserver/constant/ChannelAttrKey.java

@ -1,12 +1,21 @@
package com.bx.imserver.constant; package com.bx.imserver.constant;
public class ChannelAttrKey { public final class ChannelAttrKey {
// 用户ID private ChannelAttrKey() {
}
/**
* 用户ID
*/
public static final String USER_ID = "USER_ID"; public static final String USER_ID = "USER_ID";
// 终端类型 /**
* 终端类型
*/
public static final String TERMINAL_TYPE = "TERMINAL_TYPE"; public static final String TERMINAL_TYPE = "TERMINAL_TYPE";
// 心跳次数 /**
* 心跳次数
*/
public static final String HEARTBEAT_TIMES = "HEARTBEAt_TIMES"; public static final String HEARTBEAT_TIMES = "HEARTBEAt_TIMES";
} }

1
im-server/src/main/java/com/bx/imserver/netty/IMChannelHandler.java

@ -15,7 +15,6 @@ import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
/** /**
* WebSocket 长连接下 文本帧的处理器 * WebSocket 长连接下 文本帧的处理器
* 实现浏览器发送文本回写 * 实现浏览器发送文本回写

2
im-server/src/main/java/com/bx/imserver/netty/IMServerGroup.java

@ -19,7 +19,7 @@ public class IMServerGroup implements CommandLineRunner {
RedisTemplate<String, Object> redisTemplate; RedisTemplate<String, Object> redisTemplate;
private List<IMServer> imServers; private final List<IMServer> imServers;
/*** /***
* 判断服务器是否就绪 * 判断服务器是否就绪

5
im-server/src/main/java/com/bx/imserver/netty/UserChannelCtxMap.java

@ -5,10 +5,9 @@ import io.netty.channel.ChannelHandlerContext;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class UserChannelCtxMap { public class UserChannelCtxMap {
/* /**
* 维护userId和ctx的关联关系格式:Map<userId,map<terminalctx>> * 维护userId和ctx的关联关系格式:Map<userId,map<terminalctx>>
*/ */
private static Map<Long, Map<Integer, ChannelHandlerContext>> channelMap = new ConcurrentHashMap(); private static Map<Long, Map<Integer, ChannelHandlerContext>> channelMap = new ConcurrentHashMap();
@ -20,11 +19,9 @@ public class UserChannelCtxMap {
public static void removeChannelCtx(Long userId, Integer terminal) { public static void removeChannelCtx(Long userId, Integer terminal) {
if (userId != null && terminal != null && channelMap.containsKey(userId)) { if (userId != null && terminal != null && channelMap.containsKey(userId)) {
Map<Integer, ChannelHandlerContext> userChannelMap = channelMap.get(userId); Map<Integer, ChannelHandlerContext> userChannelMap = channelMap.get(userId);
if(userChannelMap.containsKey(terminal)){
userChannelMap.remove(terminal); userChannelMap.remove(terminal);
} }
} }
}
public static ChannelHandlerContext getChannelCtx(Long userId, Integer terminal) { public static ChannelHandlerContext getChannelCtx(Long userId, Integer terminal) {
if (userId != null && terminal != null && channelMap.containsKey(userId)) { if (userId != null && terminal != null && channelMap.containsKey(userId)) {

7
im-server/src/main/java/com/bx/imserver/netty/processor/AbstractMessageProcessor.java

@ -1,13 +1,14 @@
package com.bx.imserver.netty.processor; package com.bx.imserver.netty.processor;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
public abstract class AbstractMessageProcessor<T> { public abstract class AbstractMessageProcessor<T> {
public void process(ChannelHandlerContext ctx,T data){} public void process(ChannelHandlerContext ctx, T data) {
}
public void process(T data){} public void process(T data) {
}
public T transForm(Object o) { public T transForm(Object o) {
return (T) o; return (T) o;

4
im-server/src/main/java/com/bx/imserver/netty/processor/GroupMessageProcessor.java

@ -9,7 +9,7 @@ import com.bx.imcommon.model.IMSendResult;
import com.bx.imcommon.model.IMUserInfo; import com.bx.imcommon.model.IMUserInfo;
import com.bx.imserver.netty.UserChannelCtxMap; import com.bx.imserver.netty.UserChannelCtxMap;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
@ -19,7 +19,7 @@ import java.util.List;
@Slf4j @Slf4j
@Component @Component
@AllArgsConstructor @RequiredArgsConstructor
public class GroupMessageProcessor extends AbstractMessageProcessor<IMRecvInfo> { public class GroupMessageProcessor extends AbstractMessageProcessor<IMRecvInfo> {
private final RedisTemplate<String, Object> redisTemplate; private final RedisTemplate<String, Object> redisTemplate;

7
im-server/src/main/java/com/bx/imserver/netty/processor/HeartbeatProcessor.java

@ -9,7 +9,7 @@ import com.bx.imcommon.model.IMSendInfo;
import com.bx.imserver.constant.ChannelAttrKey; import com.bx.imserver.constant.ChannelAttrKey;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey; import io.netty.util.AttributeKey;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -19,7 +19,7 @@ import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
@Component @Component
@AllArgsConstructor @RequiredArgsConstructor
public class HeartbeatProcessor extends AbstractMessageProcessor<IMHeartbeatInfo> { public class HeartbeatProcessor extends AbstractMessageProcessor<IMHeartbeatInfo> {
private final RedisTemplate<String, Object> redisTemplate; private final RedisTemplate<String, Object> redisTemplate;
@ -49,7 +49,6 @@ public class HeartbeatProcessor extends AbstractMessageProcessor<IMHeartbeatInfo
@Override @Override
public IMHeartbeatInfo transForm(Object o) { public IMHeartbeatInfo transForm(Object o) {
HashMap map = (HashMap) o; HashMap map = (HashMap) o;
IMHeartbeatInfo heartbeatInfo = BeanUtil.fillBeanWithMap(map, new IMHeartbeatInfo(), false); return BeanUtil.fillBeanWithMap(map, new IMHeartbeatInfo(), false);
return heartbeatInfo;
} }
} }

2
im-server/src/main/java/com/bx/imserver/netty/processor/LoginProcessor.java

@ -34,7 +34,7 @@ public class LoginProcessor extends AbstractMessageProcessor<IMLoginInfo> {
private String accessTokenSecret; private String accessTokenSecret;
@Override @Override
synchronized public void process(ChannelHandlerContext ctx, IMLoginInfo loginInfo) { public synchronized void process(ChannelHandlerContext ctx, IMLoginInfo loginInfo) {
if (!JwtUtil.checkSign(loginInfo.getAccessToken(), accessTokenSecret)) { if (!JwtUtil.checkSign(loginInfo.getAccessToken(), accessTokenSecret)) {
ctx.channel().close(); ctx.channel().close();
log.warn("用户token校验不通过,强制下线,token:{}", loginInfo.getAccessToken()); log.warn("用户token校验不通过,强制下线,token:{}", loginInfo.getAccessToken());

4
im-server/src/main/java/com/bx/imserver/netty/processor/PrivateMessageProcessor.java

@ -9,14 +9,14 @@ import com.bx.imcommon.model.IMSendResult;
import com.bx.imcommon.model.IMUserInfo; import com.bx.imcommon.model.IMUserInfo;
import com.bx.imserver.netty.UserChannelCtxMap; import com.bx.imserver.netty.UserChannelCtxMap;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Slf4j @Slf4j
@Component @Component
@AllArgsConstructor @RequiredArgsConstructor
public class PrivateMessageProcessor extends AbstractMessageProcessor<IMRecvInfo> { public class PrivateMessageProcessor extends AbstractMessageProcessor<IMRecvInfo> {
private final RedisTemplate<String, Object> redisTemplate; private final RedisTemplate<String, Object> redisTemplate;

5
im-server/src/main/java/com/bx/imserver/netty/tcp/TcpSocketServer.java

@ -16,7 +16,6 @@ import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* TCP服务器,用于连接非网页的客户端,协议格式 4字节内容的长度+IMSendInfo的JSON序列化 * TCP服务器,用于连接非网页的客户端,协议格式 4字节内容的长度+IMSendInfo的JSON序列化
* *
@ -28,13 +27,11 @@ import java.util.concurrent.TimeUnit;
@ConditionalOnProperty(prefix = "tcpsocket", value = "enable", havingValue = "true", matchIfMissing = true) @ConditionalOnProperty(prefix = "tcpsocket", value = "enable", havingValue = "true", matchIfMissing = true)
public class TcpSocketServer implements IMServer { public class TcpSocketServer implements IMServer {
private volatile boolean ready = false; private volatile boolean ready = false;
@Value("${tcpsocket.port}") @Value("${tcpsocket.port}")
private int port; private int port;
private ServerBootstrap bootstrap;
private EventLoopGroup bossGroup; private EventLoopGroup bossGroup;
private EventLoopGroup workGroup; private EventLoopGroup workGroup;
@ -45,7 +42,7 @@ public class TcpSocketServer implements IMServer {
@Override @Override
public void start() { public void start() {
bootstrap = new ServerBootstrap(); ServerBootstrap bootstrap = new ServerBootstrap();
bossGroup = new NioEventLoopGroup(); bossGroup = new NioEventLoopGroup();
workGroup = new NioEventLoopGroup(); workGroup = new NioEventLoopGroup();
// 设置为主从线程模型 // 设置为主从线程模型

4
im-server/src/main/java/com/bx/imserver/netty/tcp/endecode/MessageProtocolEncoder.java

@ -6,13 +6,15 @@ import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder; import io.netty.handler.codec.MessageToByteEncoder;
import java.nio.charset.StandardCharsets;
public class MessageProtocolEncoder extends MessageToByteEncoder<IMSendInfo> { public class MessageProtocolEncoder extends MessageToByteEncoder<IMSendInfo> {
@Override @Override
protected void encode(ChannelHandlerContext channelHandlerContext, IMSendInfo sendInfo, ByteBuf byteBuf) throws Exception { protected void encode(ChannelHandlerContext channelHandlerContext, IMSendInfo sendInfo, ByteBuf byteBuf) throws Exception {
ObjectMapper objectMapper = new ObjectMapper(); ObjectMapper objectMapper = new ObjectMapper();
String content = objectMapper.writeValueAsString(sendInfo); String content = objectMapper.writeValueAsString(sendInfo);
byte[] bytes = content.getBytes("UTF-8"); byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
// 写入长度 // 写入长度
byteBuf.writeLong(bytes.length); byteBuf.writeLong(bytes.length);
// 写入命令体 // 写入命令体

1
im-server/src/main/java/com/bx/imserver/netty/ws/WebSocketServer.java

@ -20,7 +20,6 @@ import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
* WS服务器,用于连接网页的客户端,协议格式: 直接IMSendInfo的JSON序列化 * WS服务器,用于连接网页的客户端,协议格式: 直接IMSendInfo的JSON序列化
* *

27
im-server/src/main/java/com/bx/imserver/task/AbstractPullMessageTask.java

@ -1,5 +1,6 @@
package com.bx.imserver.task; package com.bx.imserver.task;
import com.bx.imcommon.util.ThreadPoolExecutorFactory;
import com.bx.imserver.netty.IMServerGroup; import com.bx.imserver.netty.IMServerGroup;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -8,33 +9,18 @@ import org.springframework.boot.CommandLineRunner;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j @Slf4j
public abstract class AbstractPullMessageTask implements CommandLineRunner { public abstract class AbstractPullMessageTask implements CommandLineRunner {
private int threadNum = 1; private static final ExecutorService EXECUTOR_SERVICE = ThreadPoolExecutorFactory.getThreadPoolExecutor();
private ExecutorService executorService;
@Autowired @Autowired
private IMServerGroup serverGroup; private IMServerGroup serverGroup;
public AbstractPullMessageTask() {
this.threadNum = 1;
}
public AbstractPullMessageTask(int threadNum) {
this.threadNum = threadNum;
}
@Override @Override
public void run(String... args) { public void run(String... args) {
// 初始化定时器 EXECUTOR_SERVICE.execute(new Runnable() {
executorService = Executors.newFixedThreadPool(threadNum);
for (int i = 0; i < threadNum; i++) {
executorService.execute(new Runnable() {
@SneakyThrows @SneakyThrows
@Override @Override
public void run() { public void run() {
@ -46,18 +32,17 @@ public abstract class AbstractPullMessageTask implements CommandLineRunner {
log.error("任务调度异常", e); log.error("任务调度异常", e);
Thread.sleep(200); Thread.sleep(200);
} }
if (!executorService.isShutdown()) { if (!EXECUTOR_SERVICE.isShutdown()) {
executorService.execute(this); EXECUTOR_SERVICE.execute(this);
} }
} }
}); });
} }
}
@PreDestroy @PreDestroy
public void destroy() { public void destroy() {
log.info("{}线程任务关闭", this.getClass().getSimpleName()); log.info("{}线程任务关闭", this.getClass().getSimpleName());
executorService.shutdown(); EXECUTOR_SERVICE.shutdown();
} }
public abstract void pullMessage(); public abstract void pullMessage();

4
im-server/src/main/java/com/bx/imserver/task/PullGroupMessageTask.java

@ -7,7 +7,7 @@ import com.bx.imcommon.model.IMRecvInfo;
import com.bx.imserver.netty.IMServerGroup; import com.bx.imserver.netty.IMServerGroup;
import com.bx.imserver.netty.processor.AbstractMessageProcessor; import com.bx.imserver.netty.processor.AbstractMessageProcessor;
import com.bx.imserver.netty.processor.ProcessorFactory; import com.bx.imserver.netty.processor.ProcessorFactory;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -16,7 +16,7 @@ import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
@Component @Component
@AllArgsConstructor @RequiredArgsConstructor
public class PullGroupMessageTask extends AbstractPullMessageTask { public class PullGroupMessageTask extends AbstractPullMessageTask {
private final RedisTemplate<String, Object> redisTemplate; private final RedisTemplate<String, Object> redisTemplate;

4
im-server/src/main/java/com/bx/imserver/task/PullPrivateMessageTask.java

@ -7,7 +7,7 @@ import com.bx.imcommon.model.IMRecvInfo;
import com.bx.imserver.netty.IMServerGroup; import com.bx.imserver.netty.IMServerGroup;
import com.bx.imserver.netty.processor.AbstractMessageProcessor; import com.bx.imserver.netty.processor.AbstractMessageProcessor;
import com.bx.imserver.netty.processor.ProcessorFactory; import com.bx.imserver.netty.processor.ProcessorFactory;
import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -16,7 +16,7 @@ import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
@Component @Component
@AllArgsConstructor @RequiredArgsConstructor
public class PullPrivateMessageTask extends AbstractPullMessageTask { public class PullPrivateMessageTask extends AbstractPullMessageTask {
private final RedisTemplate<String,Object> redisTemplate; private final RedisTemplate<String,Object> redisTemplate;

1
im-server/src/main/java/com/bx/imserver/util/SpringContextHolder.java

@ -5,7 +5,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
public class SpringContextHolder implements ApplicationContextAware { public class SpringContextHolder implements ApplicationContextAware {

4
im-ui/src/components/chat/ChatBox.vue

@ -47,7 +47,7 @@
<div title="聊天记录" class="el-icon-chat-dot-round" @click="showHistoryBox()"></div> <div title="聊天记录" class="el-icon-chat-dot-round" @click="showHistoryBox()"></div>
</div> </div>
<div class="send-content-area"> <div class="send-content-area">
<div contenteditable="true" v-show="!sendImageUrl" ref="editBox" class="send-text-area" <div contenteditable="true" v-show="!sendImageUrl" id="inputText" ref="editBox" class="send-text-area"
:disabled="lockMessage" @paste.prevent="onEditorPaste" :disabled="lockMessage" @paste.prevent="onEditorPaste"
@compositionstart="onEditorCompositionStart" @compositionstart="onEditorCompositionStart"
@compositionend="onEditorCompositionEnd" @input="onEditorInput" @compositionend="onEditorCompositionEnd" @input="onEditorInput"
@ -221,7 +221,7 @@
let sendText = "" let sendText = ""
this.$refs.editBox.childNodes.forEach((node) => { this.$refs.editBox.childNodes.forEach((node) => {
if (node.nodeName == "#text") { if (node.nodeName == "#text") {
sendText += node.textContent; sendText = document.getElementById("inputText").innerHTML;
} else if (node.nodeName == "SPAN") { } else if (node.nodeName == "SPAN") {
sendText += node.innerText; sendText += node.innerText;
} else if (node.nodeName == "IMG") { } else if (node.nodeName == "IMG") {

2
pom.xml

@ -28,7 +28,7 @@
<velocity.version>1.7</velocity.version> <velocity.version>1.7</velocity.version>
<ehcache.version>3.3.1</ehcache.version> <ehcache.version>3.3.1</ehcache.version>
<swagger.version>2.7.0</swagger.version> <swagger.version>2.7.0</swagger.version>
<hutool.version>5.3.9</hutool.version> <hutool.version>5.8.16</hutool.version>
<druid.version>1.1.22</druid.version> <druid.version>1.1.22</druid.version>
<alipay.version>3.7.110.ALL</alipay.version> <alipay.version>3.7.110.ALL</alipay.version>
<zxing.version>3.3.3</zxing.version> <zxing.version>3.3.3</zxing.version>

Loading…
Cancel
Save