Переглянути джерело

改为redis保存未读消息的list

nnkwrik 6 роки тому
батько
коміт
b134d4512c

+ 8 - 5
im-service/src/main/java/io/github/nnkwrik/imservice/controller/ChatController.java

@@ -54,7 +54,7 @@ public class ChatController {
     @GetMapping("/chat/index")
     public Response<List<ChatIndex>> getChatIndex(@JWT JWTUser user,
                                                   @RequestParam(value = "offsetTime", required = false)
-                                                  @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") Date offsetTime,
+                                                  @DateTimeFormat(pattern = StdDateFormat.DATE_FORMAT_STR_ISO8601) Date offsetTime,
                                                   @RequestParam(value = "size", defaultValue = "10") int size) {
         if (user == null) {
             return Response.ok(0);
@@ -72,11 +72,14 @@ public class ChatController {
     @GetMapping("/chat/form/{chatId}")
     public Response<ChatForm> getChatForm(@PathVariable("chatId") int chatId,
                                           @JWT(required = true) JWTUser user,
-                                          @RequestParam(value = "page", defaultValue = "1") int page,
-                                          @RequestParam(value = "size", defaultValue = "10") int size,
-                                          @RequestParam(value = "offset", defaultValue = "0") int offset) {
+                                          @RequestParam(value = "offsetTime", required = false)
+                                          @DateTimeFormat(pattern = StdDateFormat.DATE_FORMAT_STR_ISO8601) Date offsetTime,
+                                          @RequestParam(value = "size", defaultValue = "10") int size) {
+        if (offsetTime == null) {
+            offsetTime = new Date();
+        }
         //offset,在聊天框的时候收到的消息个数
-        ChatForm vo = formService.showForm(chatId, user.getOpenId(), page, size, offset);
+        ChatForm vo = formService.showForm(chatId, user.getOpenId(), size, offsetTime);
         log.info("用户openId={}获取与用户openId={}的聊天记录,展示 {} 条记录", user.getOpenId(), vo.getOtherSide().getOpenId(), vo.getHistoryList().size());
 
         return Response.ok(vo);

+ 21 - 3
im-service/src/main/java/io/github/nnkwrik/imservice/dao/HistoryMapper.java

@@ -2,6 +2,7 @@ package io.github.nnkwrik.imservice.dao;
 
 import io.github.nnkwrik.imservice.model.po.History;
 import io.github.nnkwrik.imservice.model.po.HistoryExample;
+import org.apache.ibatis.annotations.Insert;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
@@ -20,10 +21,27 @@ public interface HistoryMapper {
      *
      * @param history
      */
-    @Select("insert into history (chat_id, u1_to_u2, message_type, message_body, send_time)\n" +
+    @Insert("insert into history (chat_id, u1_to_u2, message_type, message_body, send_time)\n" +
             "values (#{chatId}, #{u1ToU2}, #{messageType}, #{messageBody}, #{sendTime})")
     void addHistory(History history);
 
+    /**
+     * 添加多条聊天记录
+     * @param historyList
+     */
+    @Insert({
+            "<script>",
+            "INSERT INTO history",
+            "(chat_id, u1_to_u2, message_type, message_body, send_time)",
+            "VALUES" +
+                    "<foreach item='item' collection='historyList' open='' separator=',' close=''>" +
+                    "(" +
+                    "#{item.chatId}, #{item.u1ToU2}, #{item.messageType}, #{item.messageBody}, #{item.sendTime}" +
+                    ")" +
+                    "</foreach>",
+            "</script>"})
+    void addHistoryList(@Param("historyList") List<History> historyList);
+
     /**
      * 获取自己和所有人的最后一条"已读的"聊天记录,取offsetTime之前的,按时间倒序
      *
@@ -84,8 +102,8 @@ public interface HistoryMapper {
      */
     @Select("select u1_to_u2, message_type, message_body, send_time\n" +
             "from history\n" +
-            "where chat_id = #{chat_id} order by send_time desc")
-    List<History> getChatHistory(@Param("chat_id") int chat_id);
+            "where chat_id = #{chat_id} and send_time &lt;= #{offset_time,jdbcType=TIMESTAMP} order by send_time desc")
+    List<History> getChatHistory(@Param("chat_id") int chatId,@Param("offset_time") Date offsetTime);
 
 
 }

+ 6 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/model/vo/ChatForm.java

@@ -1,10 +1,13 @@
 package io.github.nnkwrik.imservice.model.vo;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.util.StdDateFormat;
 import io.github.nnkwrik.common.dto.SimpleGoods;
 import io.github.nnkwrik.common.dto.SimpleUser;
 import io.github.nnkwrik.imservice.model.po.History;
 import lombok.Data;
 
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -17,4 +20,7 @@ public class ChatForm {
     private SimpleGoods goods;
     private Boolean isU1;
     private List<History> historyList;
+
+    @JsonFormat(pattern = StdDateFormat.DATE_FORMAT_STR_ISO8601)
+    private Date offsetTime;
 }

+ 7 - 0
im-service/src/main/java/io/github/nnkwrik/imservice/model/vo/ChatIndex.java

@@ -1,10 +1,14 @@
 package io.github.nnkwrik.imservice.model.vo;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.util.StdDateFormat;
 import io.github.nnkwrik.common.dto.SimpleGoods;
 import io.github.nnkwrik.common.dto.SimpleUser;
 import io.github.nnkwrik.imservice.model.po.History;
 import lombok.Data;
 
+import java.util.Date;
+
 /**
  * @author nnkwrik
  * @date 18/12/07 15:56
@@ -15,4 +19,7 @@ public class ChatIndex {
     private SimpleUser otherSide;
     private SimpleGoods goods;
     private History lastChat;
+
+    @JsonFormat(pattern = StdDateFormat.DATE_FORMAT_STR_ISO8601)
+    private Date offsetTime;
 }

+ 6 - 3
im-service/src/main/java/io/github/nnkwrik/imservice/service/FormService.java

@@ -3,13 +3,16 @@ package io.github.nnkwrik.imservice.service;
 import io.github.nnkwrik.imservice.model.vo.ChatForm;
 import io.github.nnkwrik.imservice.model.vo.WsMessage;
 
+import java.util.Date;
+import java.util.List;
+
 /**
  * @author nnkwrik
  * @date 18/12/07 22:36
  */
 public interface FormService {
-    
-    ChatForm showForm(int chatId, String userId, int page, int size, int offset);
 
-    void addMessageToSQL(WsMessage message);
+    ChatForm showForm(int chatId, String userId, int size, Date offsetTime);
+
+//    void addMessageListToSQL(List<WsMessage> messageList);
 }

+ 44 - 35
im-service/src/main/java/io/github/nnkwrik/imservice/service/impl/FormServiceImpl.java

@@ -8,7 +8,6 @@ import io.github.nnkwrik.imservice.dao.ChatMapper;
 import io.github.nnkwrik.imservice.dao.HistoryMapper;
 import io.github.nnkwrik.imservice.model.po.Chat;
 import io.github.nnkwrik.imservice.model.po.History;
-import io.github.nnkwrik.imservice.model.po.LastChat;
 import io.github.nnkwrik.imservice.model.vo.ChatForm;
 import io.github.nnkwrik.imservice.model.vo.WsMessage;
 import io.github.nnkwrik.imservice.redis.RedisClient;
@@ -17,9 +16,11 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
+import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @author nnkwrik
@@ -47,11 +48,8 @@ public class FormServiceImpl implements FormService {
 
 
     @Override
-    public ChatForm showForm(int chatId, String userId, int page, int size, int offset) {
-        LastChat lastChat = null;
-        if (page == 1) {
-            lastChat = flushUnread(chatId, userId);
-        }
+    public ChatForm showForm(int chatId, String userId, int size, Date offsetTime) {
+
 
         ChatForm vo = new ChatForm();
 
@@ -66,46 +64,52 @@ public class FormServiceImpl implements FormService {
         }
         vo.setGoods(goodsClientHandler.getSimpleGoods(chat.getGoodsId()));
 
-        int pageOffset = (page - 1) * size + offset;
-        PageHelper.offsetPage(pageOffset, size);
-        List<History> chatHistory = historyMapper.getChatHistory(chatId);
+        PageHelper.offsetPage(0, size);
+        List<History> chatHistory = historyMapper.getChatHistory(chatId, offsetTime);
         chatHistory = Lists.reverse(chatHistory);
 
-        if (lastChat != null) {
-            History lastHistory = new History();
-            BeanUtils.copyProperties(lastChat.getLastMsg(), lastHistory);
-            if (lastChat.getLastMsg().getSenderId().compareTo(lastChat.getLastMsg().getReceiverId()) < 0) {
-                lastHistory.setU1ToU2(true);
-            }
-            chatHistory.add(lastHistory);
-        }
+        List<History> unreadList = flushUnread(chatId, userId); //自己发送,但对方还未读的消息
 
+        if (unreadList != null && unreadList.size() > 0) {
+            chatHistory.addAll(unreadList);
+            chatHistory = chatHistory.stream()
+                    .sorted((a, b) -> a.getSendTime().compareTo(b.getSendTime()))
+                    .limit(size)
+                    .collect(Collectors.toList());
+        }
         vo.setHistoryList(chatHistory);
+        vo.setOffsetTime(chatHistory.get(0).getSendTime());
 
         return vo;
     }
 
-    private LastChat flushUnread(int chatId, String userId) {
-        LastChat lastChat = redisClient.get(chatId + "");
-        if (lastChat != null && lastChat.getLastMsg().getReceiverId().equals(userId)) {
+    private List<History> flushUnread(int chatId, String userId) {
+        List<WsMessage> unreadMsgList = redisClient.get(chatId + "");
+        List<History> unreadHistory = WsListToHisList(unreadMsgList);
+        if (unreadHistory != null && unreadHistory.size() > 0 && unreadMsgList.get(0).getReceiverId().equals(userId)) {
             log.info("把chatId={}设为已读消息", chatId);
-            addMessageToSQL(lastChat.getLastMsg());
+            //添加聊天记录
+            historyMapper.addHistoryList(unreadHistory);
             redisClient.del(chatId + "");
-            return null;
-        }
+        }//否则不是receiver访问form,所以仍是未读状态,不刷入sql
 
-        return lastChat;    //不是receiver访问form,所以仍是未读状态,不刷入sql
+        return unreadHistory;
     }
 
-//    public void flushWsMsgList(String userId, int chatId,List<WsMessage> wsMsgList){
+//    @Override
+//    @Transactional
+//    public void addMessageListToSQL(List<WsMessage> messageList) {
 //
+//
+//        //添加聊天记录
+//        historyMapper.addHistoryList(historyList);
 //    }
 
-    @Override
-    @Transactional
-    public void addMessageToSQL(WsMessage message) {
+    private List<History> WsListToHisList(List<WsMessage> wsMessageList) {
+        if (wsMessageList == null || wsMessageList.size() < 1) return null;
         String u1 = null;
         String u2 = null;
+        WsMessage message = wsMessageList.get(0);
         if (message.getSenderId().compareTo(message.getReceiverId()) > 0) {
             u1 = message.getReceiverId();
             u2 = message.getSenderId();
@@ -113,14 +117,19 @@ public class FormServiceImpl implements FormService {
             u1 = message.getSenderId();
             u2 = message.getReceiverId();
         }
+        boolean u1ToU2 = u1.equals(message.getSenderId()) ? true : false;
+
+        List<History> historyList = new ArrayList<>();
+        wsMessageList.stream().forEach(msg -> {
+            History history = new History();
+            BeanUtils.copyProperties(msg, history);
+            history.setU1ToU2(u1ToU2);
+            historyList.add(history);
+
+        });
 
+        return historyList;
 
-        //添加聊天记录
-        History history = new History();
-        BeanUtils.copyProperties(message, history);
-        boolean u1ToU2 = u1.equals(message.getSendTime()) ? true : false;
-        history.setU1ToU2(u1ToU2);
-        historyMapper.addHistory(history);
     }
 
 

+ 36 - 23
im-service/src/main/java/io/github/nnkwrik/imservice/service/impl/IndexServiceImpl.java

@@ -9,14 +9,15 @@ import io.github.nnkwrik.imservice.dao.ChatMapper;
 import io.github.nnkwrik.imservice.dao.HistoryMapper;
 import io.github.nnkwrik.imservice.model.po.History;
 import io.github.nnkwrik.imservice.model.po.HistoryExample;
-import io.github.nnkwrik.imservice.model.po.LastChat;
 import io.github.nnkwrik.imservice.model.vo.ChatIndex;
+import io.github.nnkwrik.imservice.model.vo.WsMessage;
 import io.github.nnkwrik.imservice.redis.RedisClient;
 import io.github.nnkwrik.imservice.service.IndexService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
 
 import java.util.*;
 import java.util.stream.Collectors;
@@ -53,17 +54,18 @@ public class IndexServiceImpl implements IndexService {
         Map<Integer, String> chatUserMap = new HashMap<>();           //k=chatId,v=需要去用户服务查的id
 
         List<Integer> chatIds = chatMapper.getChatIdsByUser(currentUser);
-        List<LastChat> unreadMessage = redisClient.multiGet(
+        List<List<WsMessage>> unreadMessage = redisClient.multiGet(
                 chatIds.stream()
                         .map(id -> id + "")
                         .collect(Collectors.toList()));
 
         //从redis(未读)和sql(已读)中各尝试取10个
-        List<LastChat> unread = getDisplayUnread(unreadMessage, size, offsetTime);
-        dealUnread(currentUser, unread, resultVoList, chatGoodsMap, chatUserMap);
+        Map<Integer, Integer> unreadCount = new HashMap<>();
+        List<WsMessage> unread = getDisplayUnread(unreadMessage, unreadCount, size, offsetTime);
+        dealUnread(currentUser, unread, unreadCount, resultVoList, chatGoodsMap, chatUserMap);
 
         List<Integer> unreadChatIds = unread.stream()
-                .map(chat -> chat.getLastMsg().getChatId())
+                .map(chat -> chat.getChatId())
                 .collect(Collectors.toList());
         PageHelper.offsetPage(0, size);
         List<HistoryExample> read = historyMapper.getLastReadChat(unreadChatIds, currentUser, offsetTime);
@@ -73,7 +75,7 @@ public class IndexServiceImpl implements IndexService {
         resultVoList = sortAndLimitMsg(size, resultVoList, chatGoodsMap, chatUserMap);
 
 
-        //添加用户和商品信息
+        //添加用户和商品信息,offsetTime
         resultVoList = setGoodsAndUser4Chat(resultVoList, chatGoodsMap, chatUserMap);
 
 
@@ -84,12 +86,12 @@ public class IndexServiceImpl implements IndexService {
     public int getUnreadCount(String userId) {
         //去查userId参与的chat的id
         List chatIdList = chatMapper.getChatIdsByUser(userId);
-        List<LastChat> lastChatList = redisClient.multiGet(chatIdList);
+        List<List<WsMessage>> lastChatList = redisClient.multiGet(chatIdList);
 
         //过滤自己发送的
         int unreadCount = lastChatList.stream()
-                .filter(chat -> !chat.getLastMsg().getSenderId().equals(userId))
-                .mapToInt(LastChat::getUnreadCount)
+                .filter(chat -> !chat.get(0).getSenderId().equals(userId))
+                .mapToInt(List::size)
                 .sum();
 
         return unreadCount;
@@ -97,40 +99,49 @@ public class IndexServiceImpl implements IndexService {
     }
 
 
-    private List<LastChat> getDisplayUnread(List<LastChat> unreadMessage, int size, Date offsetTime) {
-        List<LastChat> displayUnread = unreadMessage.stream()
-                .filter(msg -> msg != null && offsetTime.compareTo(msg.getLastMsg().getSendTime()) > 0)
-                .sorted((a, b) -> b.getLastMsg().getSendTime().compareTo(a.getLastMsg().getSendTime()))
+    private List<WsMessage> getDisplayUnread(List<List<WsMessage>> unreadMessage,
+                                             Map<Integer, Integer> unreadCount,
+                                             int size, Date offsetTime) {
+        if (ObjectUtils.isEmpty(unreadMessage)) return new ArrayList<>();
+        List<WsMessage> displayUnread = unreadMessage.stream()
+                .map(msgList -> {
+                    unreadCount.put(msgList.get(0).getChatId(), msgList.size());
+                    return msgList.get(msgList.size() - 1);
+                })
+                .filter(msg -> msg != null && offsetTime.compareTo(msg.getSendTime()) > 0)
+                .sorted((a, b) -> b.getSendTime().compareTo(a.getSendTime()))
                 .limit(size)
                 .collect(Collectors.toList());
 
         return displayUnread;
+
     }
 
     private void dealUnread(String currentUserId,
-                            List<LastChat> unread,
+                            List<WsMessage> unread,
+                            Map<Integer, Integer> unreadCount,
                             List<ChatIndex> resultVoList,
                             Map<Integer, Integer> chatGoodsMap,
                             Map<Integer, String> chatUserMap) {
 
         unread.stream().forEach(po -> {
             //稍后去其他服务查询
-            chatGoodsMap.put(po.getLastMsg().getChatId(), po.getLastMsg().getGoodsId());
+            chatGoodsMap.put(po.getChatId(), po.getGoodsId());
 
 
             //设置未读数,是自己发送的则不显示未读消息数
             ChatIndex vo = new ChatIndex();
-            if (po.getLastMsg().getSenderId().equals(currentUserId)) {
-                chatUserMap.put(po.getLastMsg().getChatId(), po.getLastMsg().getReceiverId());
+            if (po.getSenderId().equals(currentUserId)) {
+                chatUserMap.put(po.getChatId(), po.getReceiverId());
                 vo.setUnreadCount(0);
             } else {
-                vo.setUnreadCount(po.getUnreadCount());
-                chatUserMap.put(po.getLastMsg().getChatId(), po.getLastMsg().getSenderId());
+                vo.setUnreadCount(unreadCount.get(po.getChatId()));
+                chatUserMap.put(po.getChatId(), po.getSenderId());
             }
 
             //设置最后一条信息
             History lastChat = new History();
-            BeanUtils.copyProperties(po.getLastMsg(), lastChat);
+            BeanUtils.copyProperties(po, lastChat);
             vo.setLastChat(lastChat);
 
             resultVoList.add(vo);
@@ -167,9 +178,9 @@ public class IndexServiceImpl implements IndexService {
     }
 
     private List<ChatIndex> sortAndLimitMsg(int size,
-                                List<ChatIndex> voList,
-                                Map<Integer, Integer> chatGoodsMap,
-                                Map<Integer, String> chatUserMap) {
+                                            List<ChatIndex> voList,
+                                            Map<Integer, Integer> chatGoodsMap,
+                                            Map<Integer, String> chatUserMap) {
         List<ChatIndex> limited = voList.stream()
                 .sorted((a, b) -> b.getLastChat().getSendTime().compareTo(a.getLastChat().getSendTime()))
                 .limit(size)
@@ -225,6 +236,8 @@ public class IndexServiceImpl implements IndexService {
             }
             vo.setGoods(simpleGoods);
 
+            vo.setOffsetTime(vo.getLastChat().getSendTime());
+
         });
 
         return voList;

+ 7 - 11
im-service/src/main/java/io/github/nnkwrik/imservice/service/impl/WebSocketServiceImpl.java

@@ -5,7 +5,6 @@ import io.github.nnkwrik.common.exception.GlobalException;
 import io.github.nnkwrik.common.util.JsonUtil;
 import io.github.nnkwrik.imservice.constant.MessageType;
 import io.github.nnkwrik.imservice.dao.ChatMapper;
-import io.github.nnkwrik.imservice.model.po.LastChat;
 import io.github.nnkwrik.imservice.model.vo.WsMessage;
 import io.github.nnkwrik.imservice.redis.RedisClient;
 import io.github.nnkwrik.imservice.service.FormService;
@@ -17,7 +16,9 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
+import java.util.ArrayList;
 import java.util.Date;
+import java.util.List;
 
 /**
  * @author nnkwrik
@@ -79,17 +80,12 @@ public class WebSocketServiceImpl implements WebSocketService {
     }
 
     private void updateRedis(WsMessage message) {
-        LastChat lastChat = redisClient.get(message.getChatId() + "");
-        if (lastChat != null) {
-            formService.addMessageToSQL(lastChat.getLastMsg());
-            lastChat.setUnreadCount(lastChat.getUnreadCount() + 1);
-            lastChat.setLastMsg(message);
-        } else {
-            lastChat = new LastChat();
-            lastChat.setUnreadCount(1);
-            lastChat.setLastMsg(message);
+        List<WsMessage> unreadList = redisClient.get(message.getChatId() + "");
+        if (unreadList != null) {
+            unreadList = new ArrayList<>();
         }
-        redisClient.set(message.getChatId() + "", lastChat);
+        unreadList.add(message);
+        redisClient.set(message.getChatId() + "", unreadList);
     }