فهرست منبع

修改 有可能由于项目重启或关闭后,造成客户端连接未请求关闭请求处理,而造成的一些数据未更改的问题

779513719 5 سال پیش
والد
کامیت
9365b294ef

+ 1 - 2
jim-common/src/main/java/org/jim/common/cache/redis/JedisTemplate.java

@@ -450,8 +450,7 @@ public  class JedisTemplate implements  Serializable{
     * @param value string value 
     * @return 如果 field 是哈希表中的一个新建域,并且值设置成功,返回 1 。如果哈希表中域 field 已经存在且旧值已被新值覆盖,返回 0 。 
     */  
-   public Long
-   hashSet(final String key, final String field, final String value) {
+   public Long hashSet(final String key, final String field, final String value) {
        return new Executor<Long>(jedisPool) {  
  
            @Override  

+ 8 - 1
jim-server/src/main/java/org/jim/server/command/handler/ChatReqHandler.java

@@ -52,7 +52,14 @@ public class ChatReqHandler extends AbstractCmdHandler {
 			}
 		}
 		//聊天的业务处理器  (自己定义)
-		List<ChatCmdProcessor> chatProcessors = this.getProcessorNotEqualName(Sets.newHashSet(ImConst.BASE_ASYNC_CHAT_MESSAGE_PROCESSOR),ChatCmdProcessor.class);
+		List<ChatCmdProcessor> chatProcessors
+				= this.getProcessorNotEqualName(
+						Sets.newHashSet(
+								ImConst.BASE_ASYNC_CHAT_MESSAGE_PROCESSOR
+								,ImConst.IM_AUTO_MESSAGE_PROCESSOR
+						)
+						,ChatCmdProcessor.class
+		);
 		if(CollectionUtils.isNotEmpty(chatProcessors)){
 			chatProcessors.forEach(chatProcessor -> chatProcessor.handler(packet,channelContext));
 		}

+ 4 - 4
jim-server/src/main/java/org/jim/server/command/handler/CloseReqHandler.java

@@ -60,13 +60,13 @@ public class CloseReqHandler extends AbstractCmdHandler
 				User user = client.getUser();
 				if( null != user ){
 					String visitType = user.getVisitType();
+					String[] userIdArray = {user.getId()};
 					if( VisitTypeEnum.SERVICEACCOUNT.getKey().equals(visitType) ){
 						//移除客服容器中的 客服
 						String serviceAccountContainerKey
 								=  user.getExtras().getString("companyId") + ImConst.SEPARATOR
 								+ user.getExtras().getString("departmentId") + ImConst.SEPARATOR
 								+ VisitTypeEnum.SERVICEACCOUNT.getKey() ;
-						String[] userIdArray = {user.getId()};
 						jedisTemplate.hashDel(serviceAccountContainerKey,userIdArray);
 						//判断 客服是否具有查看当前部门下 全部客服通话的权限 如果有移除
 						if( Boolean.valueOf(user.getExtras().getString("hasViewAllServiceAccount")) ){
@@ -87,7 +87,7 @@ public class CloseReqHandler extends AbstractCmdHandler
 						//修改 sw_visitor_department_middle 表中的 online状态; '用户状态 1:已下线 0:在线'
 						VisitorDepartmentMiddle.dao.findById(user.getId()).set("online",1).update();
 					}
-					jedisTemplate.listRemove(CURRENT_SYSTEM_ALL_USER_ID,0,user.getId());
+					jedisTemplate.hashDel(CURRENT_SYSTEM_ALL_USER_ID,userIdArray);
 				}
 			}
 			ImAio.remove(channelContext, "收到关闭请求");
@@ -96,13 +96,13 @@ public class CloseReqHandler extends AbstractCmdHandler
 			User user = ImAio.getUser(userId);
 			//访问类型 (SERVICEACCOUNT 客服 / CUSTOMER 客户 / VISITOR 游客)
 			String visitType = user.getVisitType();
+			String[] userIdArray = {userId};
 			if( VisitTypeEnum.SERVICEACCOUNT.getKey().equals(visitType) ){
 				//移除客服容器中的 客服
 				String serviceAccountContainerKey
 						=  user.getExtras().getString("companyId") + ImConst.SEPARATOR
 						+ user.getExtras().getString("departmentId") + ImConst.SEPARATOR
 						+ VisitTypeEnum.SERVICEACCOUNT.getKey() ;
-				String[] userIdArray = {userId};
 				jedisTemplate.hashDel(serviceAccountContainerKey,userIdArray);
 				//判断 客服是否具有查看当前部门下 全部客服通话的权限
 				if( Boolean.valueOf(user.getExtras().getString("hasViewAllServiceAccount")) ){
@@ -123,7 +123,7 @@ public class CloseReqHandler extends AbstractCmdHandler
 				//修改 sw_visitor_department_middle 表中的 online状态; '用户状态 1:已下线 0:在线'
 				VisitorDepartmentMiddle.dao.findById(user.getId()).set("online",1).update();
 			}
-			jedisTemplate.listRemove(CURRENT_SYSTEM_ALL_USER_ID,0,userId);
+			jedisTemplate.hashDel(CURRENT_SYSTEM_ALL_USER_ID,userIdArray);
 			ImAio.remove(userId, "收到关闭请求!");
 		}
 		return ImKit.ConvertRespPacket(new RespBody(Command.COMMAND_CLOSE_REQ, ImStatus.C10021), channelContext);

+ 8 - 1
server-chat/server-chat.iml

@@ -40,7 +40,6 @@
     <orderEntry type="library" name="Maven: javax.cache:cache-api:1.0.0" level="project" />
     <orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.1.7.RELEASE" level="project" />
     <orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.2" level="project" />
-    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.7.9" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.7.9" level="project" />
     <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.7.9.2" level="project" />
@@ -96,5 +95,13 @@
     </orderEntry>
     <orderEntry type="library" name="Maven: mysql:mysql-connector-java:8.0.17" level="project" />
     <orderEntry type="library" name="Maven: com.google.protobuf:protobuf-java:3.6.1" level="project" />
+    <orderEntry type="library" name="Maven: log4j:log4j:1.2.16" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.7" level="project" />
+    <orderEntry type="library" name="Maven: com.googlecode.log4jdbc:log4jdbc:1.2" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:slf4j-log4j12:1.7.25" level="project" />
+    <orderEntry type="library" name="Maven: org.quartz-scheduler:quartz:2.3.0" level="project" />
+    <orderEntry type="library" name="Maven: com.mchange:c3p0:0.9.5.2" level="project" />
+    <orderEntry type="library" name="Maven: com.mchange:mchange-commons-java:0.2.11" level="project" />
+    <orderEntry type="library" name="Maven: com.zaxxer:HikariCP-java6:2.3.13" level="project" />
   </component>
 </module>

+ 114 - 23
server-chat/src/main/java/com/cn/ServerChatStart.java

@@ -8,17 +8,25 @@ import com.cn.service.IMChatLoginServiceProcessor;
 import nl.basjes.shaded.org.springframework.util.CollectionUtils;
 import org.jim.common.ImAio;
 import org.jim.common.ImConfig;
+import org.jim.common.ImConst;
 import org.jim.common.ImPacket;
 import org.jim.common.cache.redis.JedisTemplate;
 import org.jim.common.config.PropertyImConfigBuilder;
 import org.jim.common.packets.CloseReqBody;
 import org.jim.common.packets.Command;
+import org.jim.common.packets.User;
+import org.jim.common.utils.JsonKit;
 import org.jim.server.ImServerStarter;
 import org.jim.server.command.CommandManager;
 import org.jim.server.command.handler.CloseReqHandler;
 import org.jim.server.command.handler.HandshakeReqHandler;
 import org.jim.server.command.handler.JoinGroupReqHandler;
 import org.jim.server.command.handler.LoginReqHandler;
+import org.jim.server.enums.*;
+import org.jim.server.model.ChatGroup;
+import org.jim.server.model.Conversation;
+import org.jim.server.model.GroupConversationMiddle;
+import org.jim.server.model.VisitorDepartmentMiddle;
 import org.quartz.*;
 import org.quartz.impl.StdSchedulerFactory;
 import org.slf4j.Logger;
@@ -27,7 +35,9 @@ import org.tio.core.Aio;
 import org.tio.core.ChannelContext;
 import org.tio.utils.lock.SetWithLock;
 
+import java.sql.Timestamp;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
@@ -44,6 +54,8 @@ public class ServerChatStart {
 
     private static final String CURRENT_SYSTEM_ALL_USER_ID = "CURRENT_SYSTEM_ALL_USER_ID";
 
+    private static final String GROUP_PROPERTY = " group_id,name,avatar,service_account_role_department_middle_id,consumer_id,group_type,company_id,department_id ";
+
     static {
         try {
             jedisTemplate = JedisTemplate.me();
@@ -79,11 +91,10 @@ public class ServerChatStart {
         //添加登录业务处理器;
         loginReqHandler.addProcessor(new IMChatLoginServiceProcessor());
 
-
         /*****************end *******************************************************************************************/
         imServerStarter.start();
         //initQuartz();
-        initRedisData();
+        initData();
 
     }
 
@@ -94,35 +105,115 @@ public class ServerChatStart {
      * @author Darren
      * @date 2020/2/14 12:02
      */
-    private static void initRedisData(){
+    private static void initData(){
         //修改由于程序重启或关闭 而没有 走正常的 关闭请求处理器 的 user
-        List<String> userIds = jedisTemplate.listGetAll(CURRENT_SYSTEM_ALL_USER_ID);
-        if(!CollectionUtils.isEmpty(userIds)){
-            for (String userId : userIds) {
-                SetWithLock<ChannelContext> channelContexts = ImAio.getChannelContextsByUserId(userId);
-                if( null != channelContexts && channelContexts.size() > 0 ){
-                    //获取读锁
-                    ReadLock readLock = channelContexts.getLock().readLock();
-                    //加锁
-                    readLock.lock();
-                    try {
-                        Set<ChannelContext> channels = channelContexts.getObj();
-                        for (ChannelContext channelContext : channels) {
-                            ImPacket imPacket = new ImPacket(new CloseReqBody(userId).toByte());
-                            CloseReqHandler closeReqHandler = CommandManager.getCommand(Command.COMMAND_CLOSE_REQ, CloseReqHandler.class);
-                            closeReqHandler.handler(imPacket,channelContext);
+        Map<String,String> users = jedisTemplate.hashGetAll(CURRENT_SYSTEM_ALL_USER_ID);
+        if(!CollectionUtils.isEmpty(users)){
+            for(Map.Entry<String,String> entry : users.entrySet()){
+                User user = JsonKit.toBean(entry.getValue(), User.class);
+                //访问类型 (SERVICEACCOUNT 客服 / CUSTOMER 客户 / VISITOR 游客)
+                String visitType = user.getVisitType();
+                String[] userIdArray = {user.getId()};
+                if( VisitTypeEnum.SERVICEACCOUNT.getKey().equals(visitType) ){
+                    //移除客服容器中的 客服
+                    String serviceAccountContainerKey
+                            =  user.getExtras().getString("companyId") + ImConst.SEPARATOR
+                            + user.getExtras().getString("departmentId") + ImConst.SEPARATOR
+                            + VisitTypeEnum.SERVICEACCOUNT.getKey() ;
+                    jedisTemplate.hashDel(serviceAccountContainerKey,userIdArray);
+                    //判断 客服是否具有查看当前部门下 全部客服通话的权限
+                    if( Boolean.valueOf(user.getExtras().getString("hasViewAllServiceAccount")) ){
+                        String adminContainerKey = user.getExtras().getString("companyId")
+                                + ImConst.SEPARATOR + user.getExtras().getString("departmentId")
+                                + ImConst.SEPARATOR +  ImConst.ADMIN ;
+                        jedisTemplate.listRemove(adminContainerKey,0,user.getId());
+                    }
+                    List<ChatGroup> chatGroups = ChatGroup.dao.find(createSelectGroupSqlByServiceAccountRoleDepartmentId(user));
+                    if( org.apache.commons.collections4.CollectionUtils.isNotEmpty(chatGroups) ){
+                        for (ChatGroup chatGroup : chatGroups) {
+                            //客服是否是离线状态 1: 是 0: 否
+                            chatGroup.set("service_account_type", ServiceAccountOfflineTypeEnum.OFF_LINE.getKey()).update();
+                        }
+                    }
+                }
+                if( !VisitTypeEnum.SERVICEACCOUNT.getKey().equals(visitType) ){
+                    List<ChatGroup> chatGroups = ChatGroup.dao.find(createSelectGroupSqlByConsumerId(user));
+                    if( !CollectionUtils.isEmpty(chatGroups) ){
+                        for (ChatGroup chatGroup : chatGroups) {
+                            //更改 group_state: 1 (群组离线状态 1: 离线 0: 在线)
+                            //更改 consumer_type: 1 (客户/游客 离线状态 1:离线 0:在线)
+                            chatGroup
+                                    .set("group_state", GroupStateEnum.OFF_LINE.getKey())
+                                    .set("consumer_type", ConsumerTypeEnum.OFF_LINE.getKey())
+                                    .update();
+                            if(MessageStateEnum.NO.getKey() == chatGroup.getInt("message_state")){
+                                //群组状态 为 非留言状态
+                                //修改 sw_conversation 表中的  end_time 和 conversation_lenth
+                                StringBuilder sql = new StringBuilder();
+                                sql.append(" select * from sw_group_conversation_middle where group_id = " + chatGroup.getStr("group_id"))
+                                        .append(" order by create_time desc limit 1");
+                                GroupConversationMiddle groupConversation = GroupConversationMiddle.dao.findFirst(sql.toString());
+                                if( null != groupConversation ){
+                                    Conversation conversation = Conversation.dao.findById(groupConversation.getLong("conversation_id"));
+                                    Timestamp endTime = conversation.getTimestamp("end_time");
+                                    Integer conversationLenth = conversation.getInt("conversation_lenth");
+                                    if( null == endTime && null == conversationLenth ){
+                                        //需要更改会话结束时间 和 对话时长
+                                        long currentTimeMillis = System.currentTimeMillis();
+                                        //当前时间的格林威治时间 毫秒数
+                                        Timestamp currentTime = new Timestamp(currentTimeMillis);
+                                        Timestamp createTime = conversation.getTimestamp("create_time");
+                                        //会话创建时间的格林威治时间 毫秒数
+                                        long createTimeMillis = createTime.getTime();
+                                        if(currentTimeMillis > createTimeMillis){
+                                            conversation.set("end_time",currentTime);
+                                            conversation.set("conversation_lenth",Integer.valueOf( String.valueOf( (currentTimeMillis - createTimeMillis)/1000 )));
+                                        }
+                                    }
+                                }
+                            }
                         }
-                    } catch (Exception e) {
-                        logger.error(e.toString(),e);
-                    }finally {
-                        //解锁
-                        readLock.unlock();
                     }
                 }
+                if( VisitTypeEnum.VISITOR.getKey().equals(visitType) ){
+                    //修改 sw_visitor_department_middle 表中的 online状态; '用户状态 1:已下线 0:在线'
+                    VisitorDepartmentMiddle.dao.findById(user.getId()).set("online",1).update();
+                }
+                jedisTemplate.hashDel(CURRENT_SYSTEM_ALL_USER_ID,userIdArray);
             }
         }
     }
 
+    private static String createSelectGroupSqlByConsumerId(User user){
+        StringBuilder sql = new StringBuilder();
+        sql
+                .append(" select ")
+                .append(GROUP_PROPERTY)
+                .append(" from sw_group where 1 = 1 ")
+                .append(" and company_id = " + user.getExtras().getString("companyId"))
+                .append(" and department_id = " + user.getExtras().getString("departmentId"))
+                .append(
+                        " and consumer_id = "
+                                + user.getId()
+                );
+        return sql.toString();
+    }
+
+    private static String createSelectGroupSqlByServiceAccountRoleDepartmentId(User user){
+        StringBuilder sql = new StringBuilder();
+        sql
+                .append(" select ")
+                .append(GROUP_PROPERTY)
+                .append(" from sw_group where 1 = 1 ")
+                .append(" and company_id = " + user.getExtras().getString("companyId"))
+                .append(" and department_id = " + user.getExtras().getString("departmentId"))
+                .append(
+                        " and service_account_role_department_middle_id = "
+                                + user.getId()
+                );
+        return sql.toString();
+    }
+
     /**
      * 集成 quartz 定时任务启动
      * @param

+ 0 - 1
server-chat/src/main/java/com/cn/listener/IMChatGroupListener.java

@@ -80,7 +80,6 @@ public class IMChatGroupListener extends ImGroupListener {
                         }
                     }
                 }
-
             }
         }
 

+ 13 - 5
server-chat/src/main/java/com/cn/service/IMChatLoginServiceProcessor.java

@@ -1,6 +1,7 @@
 package com.cn.service;
 
 import com.alibaba.fastjson.JSONObject;
+import org.jim.common.utils.JsonKit;
 import org.jim.server.model.*;
 import nl.basjes.shaded.org.springframework.util.CollectionUtils;
 import org.jim.server.enums.*;
@@ -66,14 +67,21 @@ public class IMChatLoginServiceProcessor implements LoginCmdProcessor {
                 loginRespBody =  new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10022,user);
             }else{
                 loginRespBody = new LoginRespBody(Command.COMMAND_LOGIN_RESP,ImStatus.C10007,user);
-                List<String> userIds = jedisTemplate.listGetAll(CURRENT_SYSTEM_ALL_USER_ID);
-                if(!CollectionUtils.isEmpty(userIds)){
-                    if( !userIds.contains(user.getId()) ){
+                String userJson = JsonKit.toJSONString(user);
+                Map<String,String> users = jedisTemplate.hashGetAll(CURRENT_SYSTEM_ALL_USER_ID);
+                if(!CollectionUtils.isEmpty(users)){
+                    boolean flag = true;
+                    for(Map.Entry<String,String> entry : users.entrySet()){
+                        if(entry.getKey() == user.getId() ){
+                            flag = false;
+                        }
+                    }
+                    if(flag){
                         //存储所有登录的用户 的 userId
-                        jedisTemplate.listPushTail(CURRENT_SYSTEM_ALL_USER_ID,user.getId());
+                        jedisTemplate.hashSet(CURRENT_SYSTEM_ALL_USER_ID, user.getId(), userJson);
                     }
                 }else{
-                    jedisTemplate.listPushTail(CURRENT_SYSTEM_ALL_USER_ID,user.getId());
+                    jedisTemplate.hashSet(CURRENT_SYSTEM_ALL_USER_ID, user.getId(), userJson);
                 }
             }
         }