Web聊天室消息[已讀未讀]的實現


聊天室快速訪問
繼上次完成聊天室的歷史記錄功能后,我又想着實現聊天記錄的已讀未讀功能。(輕噴。。)

開始之前

首先我看了抖音和釘釘這兩款應用的消息已讀未讀功能的呈現效果。首先是抖音,在聊天界面,給好友發送完消息后,消息界面的最右下角有一個“已發送”標記,這時候是屬於對方未讀,如果對方上線並別點開了和你的聊天界面,你和他的聊天界面上,那個“已發送”就變成了“已讀”,所以抖音並不會每一條消息上面都顯示“已讀”或者“未讀”。而釘釘,由於其專注於辦公,這個已讀未讀功能就“變態”多了,每一條發出去的消息都會顯示對方是已讀還是未讀。

學誰?

當然了,我只能通過抖音或者釘釘在功能上呈現出來的效果來結合自己掌握的知識來推斷他們大概的實現過程,真正的實現可比想的復雜多了,所以我也是照葫蘆畫瓢,做一個能用的精簡版已讀未讀功能。既然是照葫蘆畫瓢,那就學釘釘吧,做一個“變態版”,每一條消息都顯示“已讀”或者“未讀”。

思考

A和B聊天,如果A發送一條消息給B,怎么知道B已讀呢?當然是B收到消息后,發送一個“已讀回執”,A接收到已讀回執后,更新自己的UI,把“未讀”改為“已讀”。

啊!挺簡單啊。。。

可,,可是,如果B不在線,或者B在線,但是沒有打開和A的聊天界面,那B不也是未讀A的消息嗎?如果B不在線,A發完消息后下線了,這時B上線了,查看消息后,發送已讀回執給A,可是A已經下線了啊,怎么保持已讀狀態?此外,消息的已讀和未讀狀態要保持的話,是該給消息添加一個屬性,標識已讀未讀嗎?如果添加屬性,意味着我以前的代碼也得改?比如一些操作數據庫的代碼和邏輯。

啊!

我怎么做

首先,並不需要給消息添加一個已讀未讀標識,只記錄一個B最近已讀A消息的時間即可。這樣怎么就行呢?

1.設計“已讀回執”結構

已讀回執很簡單,就是兩個id和一個時間戳,id分別是讀消息的A用戶id、發消息的B用戶id,時間戳是A最近一次讀取B的消息的時間。這個已讀回執是存到Redis中去的,最終會通過定時任務在凌晨三點持久化到數據庫。例如id為3的用戶發送已讀回執給id為5的用戶,則Redis中保存一個Value(key:'3-4-readTime', ×××)

2.“已讀回執”怎么用

給一個場景A和B兩個用戶,進行對話。我們來分情況討論一下吧:

  • A上線,A點擊好友列表中的好友B,這個動作即會觸發發送一個已讀回執給B(即使沒有未讀消息),同時存在Redis中。
    • B在線,B收到回執會把和A的聊天中的A未讀的消息更改為已讀
    • B不在線,B不能即時收到這個回執。等到B下次上線的時候,首先會去Redis中獲取每個好友給自己的回執緩存(如果緩存沒有則取數據庫中獲取,同時更新到緩存),這里能獲取到好友A的回執,將回執里面的時間和要渲染到界面上的B發的每條消息的時間去比較,如果回執中的時間大於消息時間,則該消息標記為“已讀”,否則標記為“未讀”。
  • A上線,點擊列表中的好友B,執行完上面的過程,A發消息給B,A的界面顯示這條消息,並顯示此消息未讀
    • B在線:
      • B這時開着的是和A的聊天界面。B收到A的消息,立刻顯示了出來,隨即發送一條已讀回執給A,同時更新Redis。如果A在線,則收到這條回執,把界面上的所有未讀消息更改為“已讀”。如果A不在線了,下次上線也可以通過緩存的回執或者持久化到數據庫中的回執來渲染界面,顯示“已讀”。
      • B這時開着的不是和A的聊天界面,則不發送回執給A,A界面繼續顯示“未讀”。當B打開和A的聊天界面,才發送回執,同時更新Redis。
    • B不在線:A界面這條消息繼續顯示“未讀”。只有在下次B上線的時候,B點開和A的聊天界面,才會給A發送已讀回執。A在線則獲取實時的回執,如果不在線則下次上線的時候獲取回執渲染界面。

Redis宕機了怎么辦

和歷史記錄的實現一樣,對於我這個單服務器系統,那就只能直接保存到數據庫了。另外Redis持久化策略可以在下次啟動的時候恢復數據。

遇到的坑

這個思路是沒什么復雜的,但是實施起來就有很多小細節了。在一個坑上面花了很多時間。就是js獲取的時間戳,在java中轉成Timestamp的時候出錯,導致我在調試的時候一旦發送已讀回執,接收已讀回執的那個客戶端就會斷連。最后發現是Timestemp這個東東,不能用強轉字符串來得到,大意了,需要通過Timestamp.valueOf(×××)來把一個字符串轉為時間戳,而且這個傳入的字符串需要以yyyy-MM-dd HH:mm:ss的格式來的。當時寫太快了,就用(Timestamp)強制轉換。。。

截圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM