Spring Boot專案實踐之問答社群

2021-09-13 16:25:45 字數 3048 閱讀 9683

專案源**已託管在

github,歡迎 star、fork。

qa是乙個基於 b/s 架構而設計開發的社群**。

主要為使用者提供以下服務:

spring boot + mybatis + mysql + redis + freemarker

為了保證使用者資訊保安,系統對使用者密碼採用「salt + md5」方式進行加密。使用者註冊/登入成功後,系統會生成乙個 ticket ,將 ticket 與使用者 id 相關聯,並將此資訊插入到資料庫表 login_ticket 中,同時將 ticket 響應給客戶端。

使用者每次請求頁面的時候,都需要先經過 passportinterceptor ***,***判斷此 ticket 是否真實有效,若是,根據 ticket 對應的使用者 id ,查出相應使用者資訊,並新增至頁面上下文中。

若沒有對 html 標籤進行處理,當使用者發布的內容含有如時,**頁面每次載入此內容時都會彈出訊息框。
對於敏感詞過濾,按照常規的思維,也是最簡單的方式,就是:對於每個敏感詞,都在文字中查詢該敏感詞是否出現,出現則進行替換。這種方式,每個敏感詞都要在一段文字中進行遍歷查詢,複雜度非常高。

本專案採用「字首樹」方式實現敏感詞過濾,空間換時間,效率較高。字首樹結點結構如下:

class trienode 

// 根據key獲取子結點

trienode getsubnode(character key)

}

後台從敏感詞檔案 sensitivewords.txt 順序讀取每一行建立字首樹。進行過濾時,遍歷需要過濾的文字,用星號替換發現的敏感詞。假設文字長度為 len,字首樹的最大高度為 h,那麼此演算法的最壞時間複雜度為 o(len*h)。

演算法比較假如敏感詞平均長度為10,數量為100000,文字長度為 len。

常規方式,複雜度o(100000

(len + 10));字首樹演算法複雜度o(10 len)。

贊踩功能採用「redis」作為資料儲存。why redis?

比較一下 redis 和 mysql:

redis 適合放一些頻繁使用、比較熱的資料。因為資料放在了記憶體中,讀寫效能卓越。

redis 型別

資料結構

應用場景

list

雙向列表

最新列表、關注列表

set無序集合

贊踩、**、已讀、共同好友

sortedset

優先佇列

排行榜hash

雜湊表不定長屬性數

kv單一數值

驗證碼、pv、快取

除了使用者內容贊踩,在本專案中,redis 還應用於以下場景:

本小節討論使用者內容贊踩服務。

使用者對某一實體點讚,會將"like:entity_type:entity_id"作為 key ,使用者 id 作為 value ,存入 like 集合中。同時移除 unlike 集合中該 key 對應的使用者 id。點踩服務反之。

最後將點讚數響應給頁面。

本專案涉及到多種非同步事件的處理。如:

使用者關注了另乙個實體

這些動作並不是單一的,它們會觸發一些後續的操作:

事件觸發者並不關心這些後續的任務,系統處理完某個動作後就可以將結果返回給觸發者,而後續的任務交給系統進行非同步處理即可。

因此,設計乙個非同步事件處理框架尤為重要。

本專案的非同步框架如下圖所示:

業務觸發乙個非同步事件,eventproducer 將該事件(eventmodel)序列化並存入佇列(redis list)中,eventconsumer 開啟執行緒迴圈從佇列中取出事件,識別該事件的型別,找出該型別對應的一系列 eventhandler,交由這些 handler 去處理。

eventmodel的設計如下:

class eventmodel
乙個使用者,系統儲存兩個集合:

①儲存使用者關注的實體;②儲存關注使用者的人。

即 a 是 b 的粉絲,b 是 a 的關注物件。[參考資料 ]

使用者關注了乙個問題,需要發生兩個動作:

這兩個動作必須同時發生,因此,這裡用到了 redis 事務保證原子性和資料的一致性。

另外,對於關注功能,如前面所說,會觸發非同步事件,將訊息通知被關注的實體 / 實體 owner。

當使用者更新動態時,該使用者所有粉絲都可以在一定時間內收到新的動態(也稱為新鮮事、feed),可以由 「推拉模式」 實現。

模式定義

優缺點推

事件觸發後廣播給所有粉絲。

對於粉絲數過多的事件,後台壓力較大,浪費儲存空間;

流程清晰,開發難度低,關注新使用者需要同步更新 feed 流。

拉登入開啟頁面時,根據關注的實體動態生成 timeline 內容。

讀取壓力大,儲存占用小,快取最新讀取的 feed,根據時間分割槽拉取。

推拉降低儲存空間,又滿足大部分使用者的讀取需求。

具體來說,推模式就是:事件觸發後產生 feed,觸發事件的使用者下所有粉絲的 timeline(redis list 實現)中都存入該 feed 的 id。而拉模式,就是當前使用者去拉取自己關注的人的 feed。

更多推拉模式相關,可以參考 微博 feed 系統推拉模式。

由於系統初始資料較少,為了豐富**內容,本專案採用 pyspider 實現對 v2ex **的資料爬取,儲存到後台資料庫,並展示在前端頁面上。

安裝 pyspider:

pip install pyspider
啟動 pyspider:

pyspider
本專案在全文搜尋服務上採用 solr 框架,中文分詞採用 solr 自帶的中文分詞外掛程式 solr_cnanalyzer 。

springboot專案實踐 整合swagger

1.在pom檔案中做如下配置 io.springfoxgroupid springfox swagger2artifactid 2.9.2version dependency io.springfoxgroupid springfox swagger uiartifactid 2.9.2versio...

Spring Boot最佳實踐

org.springframework.boot spring boot starter data redis 如果你想使用mongodb,你有 org.springframework.boot spring boot starter data mongodb 依賴於這些starter,依靠這些經過...

優秀實踐之專案管理

軟體專案管理方法與專案需求流程緊密相關。專案經理應當根據需要實現的需求,規劃專案時間表 資源以及做出承諾。另一種策略是將開發周期納入 時間盒 即團隊估算出他們在固定迭代時間內能夠完成的工作範圍。敏捷開發專案採用的就是這種方式。範圍可以在計畫時間範圍內協商。這樣一來,範圍蔓延就成了 範圍選擇 產品負責...