問答平臺實習專案
摘要:
從八月底到昨天,整整三個月,邊看視訊學技術棧邊寫程式碼,每天晚上擠時間完成了這個專案,還是想為明年實習做一個專案上的準備。最初是想做一個深度學習方面的專案,當時對這方面基礎知識的儲備還不夠,如今也還在看視訊和文件學習,因此選擇了web專案。其實對於以後工作的方向到底是演算法還是研發現在也說...
從八月底到昨天,整整三個月,邊看視訊學技術棧邊寫程式碼,每天晚上擠時間完成了這個專案,還是想為明年實習做一個專案上的準備。最初是想做一個深度學習方面的專案,當時對這方面基礎知識的儲備還不夠,如今也還在看視訊和文件學習,因此選擇了web專案。其實對於以後工作的方向到底是演算法還是研發現在也說不清楚,等明年初根據自己的學習情況再做進一步的打算。
接下來學校的課越來越集中,各種考試也陸續而至,深度學習也還在繼續學習,因此留給專案上的準備時間也捉襟見肘,但每天還是會堅持寫演算法題,相信明年會越來越好。
這個專案是以現在的知乎、牛客網這類問答平臺為原型,基於springboot的SSM框架的Java web應用專案。資料庫使用了redis和mysql,同時加入了非同步訊息等進階功能,同時使用python爬蟲進行資料填充。
quick-start
- 1.專案基本配置
- 2.基本框架開發
- 3.AOP和IOC/">IOC
- 4.資料庫配置和首頁的建立
- 5.使用者註冊登入以及使用
- 6.新增發表問題功能,並防止xss注入以及敏感詞過濾
- 7.新增評論和站內信功能
- 8.新增點贊和點踩功能,使用Redis實現
- 9.新增非同步訊息功能
- 10.新增關注功能,開發關注頁面和粉絲頁面
- 11.Timeline與新鮮事,推拉模式下的Feed流
- 12.使用python爬蟲爬取知乎話題資料,充實網站資訊
- 13.使用solr搭建全文搜尋引擎,開發知乎的全文搜尋功能
- 14.單元測試與壓力測試,專案打包及部署等收尾工作
- 15.產品功能擴充套件以及技術深度擴充套件
專案基礎配置
建立git倉庫,本地配置idea並測試pull和push。
建立springboot工程,匯入web,velocity和aop的包。
生成maven專案,pom.xml包含上述依賴。
基本框架開發
建立基本的controller,service和model層。
controller中使用註解配置,requestmapping,responsebody基本可以解決請求轉發以及響應內容的渲染。responsebody自動選擇viewresolver進行解析。
使用pathvariable和requestparam傳遞引數。
使用velocity編寫頁面模板,注意其中的語法使用。常用
{}
使用http規範下的httpservletrequest和httpservletresponse來封裝請求和相響應,使用封裝好的session和cookie物件。
使用重定向的redirectview和統一異常處理器exceptionhandler。
AOP和IOC
IOC解決物件例項化以及依賴傳遞問題,解耦。
AOP解決縱向切面問題,主要實現日誌和許可權控制功能。
aspect實現切面,並且使用logger來記錄日誌,用該切面的切面方法來監聽controller。
資料庫配置和首頁的建立
使用mysql建立資料庫和表。
加入mybatis和mysql的maven倉庫,注意,由於現在版本的springboot不再支援velocity進而導致我使用較早版本的springboot,所以這裡提供一可以正常執行的版本設定。
springboot使用1.4.0
mybatis-spring-boot-starter使用1.2.1
mysql-connector-java使用8.0.12
接下來寫controller,dao和service。注意mybatis的註解語法以及xml的配置要求,xml要求放在resource中並且與dao介面在相同的包路徑下。
application.properties增加spring配置資料庫連結地址
兩個小工具:
ViewObject:方便傳遞任何資料到
VelocityDateTool:velocity自帶工具類
寫好靜態檔案html css和js。並且注意需要配置
spring.velocity.suffix=.html 保證跳轉請求轉發到html上
spring.velocity.toolbox-config-location=toolbox.xml
至此主頁基本完成。
使用者註冊登入以及使用token
完成使用者註冊和登入的controller,service和dao層程式碼。
新建資料表login_ticket用來儲存ticket欄位。該欄位在使用者登入成功時被生成並存入資料庫,並被設定為cookie,下次使用者登入時會帶上這個ticket,ticket是隨機的uuid,有過期時間以及有效狀態。
使用攔截器interceptor來攔截所有使用者請求,判斷請求中是否有有有效的ticket,如果有的話則將使用者資訊寫入Threadlocal。所有執行緒的threadlocal都被存在一個叫做hostholder的例項中,根據該例項就可以在全域性任意位置獲取使用者的資訊。
該ticket的功能類似session,也是通過cookie寫回瀏覽器,瀏覽器請求時再通過cookie傳遞,區別是該欄位是存在資料庫中的,並且可以用於移動端。
通過使用者訪問許可權攔截器來攔截使用者的越界訪問,比如使用者沒有管理員許可權就不能訪問管理員頁面。
配置了使用者的webconfiguration來設定啟動時的配置,這裡可以將上述的兩個攔截器加到啟動項裡。
配置了json工具類以及md5工具類,並且使用Java自帶的鹽生成api將使用者密碼加密為密文。保證密碼安全。
資料安全性的保障手段:https使用公鑰加密私鑰解密,比如支付寶的密碼加密,單點登入驗證,驗證碼機制等。
新增發表問題功能,並防止xss注入以及敏感詞過濾
新增Question相關的model,dao,service和controller。
釋出問題時檢查標題和內容,防止xss注入,並且過濾敏感詞。
防止xss注入直接使用HTMLutils的方法即可實現。
過濾敏感詞首先需要建立一個字典樹,並且讀取一份儲存敏感詞的文字檔案,然後初始化字典樹。最後將過濾器作為一個服務,讓需要過濾敏感詞的服務進行呼叫即可。
新增評論和站內信功能
首先建立表comment和message分別代表評論和站內信。
依次開發model,dao,service和controller。
評論的邏輯是每一個問題下面都有評論,顯示評論數量,具體內容,評論人等資訊。
訊息的邏輯是,兩個使用者之間傳送一條訊息,有一個唯一的會話id,這個會話裡可以有多條這兩個使用者的互動資訊。通過一個使用者id獲取該使用者的會話列表,再根據會話id再獲取具體的會話內的多條訊息。
邏輯清楚之後,再加上一些附加功能,比如顯示未讀訊息數量,根據時間順序排列會話和訊息。
本節內容基本就是業務邏輯的開發,沒有新增什麼技術點,主要是前後端互動的邏輯比較複雜,前端的開發量也比較大。
新增點贊和點踩功能,使用Redis實現
首先了解一下redis的基礎知識,資料結構,jedis使用等。
編寫list,string,hashmap,set,sortset的測試用例,熟悉jedis api。
開發點踩和點贊功能,在此之前根據業務封裝好jedis的增刪改查操作,放在util包中。
根據需求確定key欄位,格式是 like:實體型別:實體id 和 dislike:實體型別:實體id 這樣可以將喜歡一條新聞的人存在一個集合,不喜歡的存在另一個集合。通過統計數量可以獲得點贊和點踩數。
一般點贊點踩操作是先修改redis的值並獲取返回值,然後再非同步修改mysql資料庫的likecount數值。這樣既可以保證點贊操作快速完成,也可保證資料一致性。
新增非同步訊息框架
在之前的功能中有一些不需要實時執行的操作或者任務,我們可以把它們改造成非同步訊息來進行傳送。
具體操作就是使用redis來實現非同步訊息佇列。程式碼中我們使用事件event來包裝一個事件,事件需要記錄事件實體的各種資訊。
我們在async包裡開發非同步工具類,事件生產者,事件消費者,並且開發一個eventhandler介面,讓各種事件的實現類來實現這個介面。
事件生產者一般作為一個服務,由業務程式碼進行呼叫產生一個事件。而事件消費者我們在程式碼裡使用了單執行緒迴圈獲取佇列裡的事件,並且尋找對應的handler進行處理。
如此一來,整個非同步事件的框架就開發完成了。後面新加入的登入,點贊等事件都可以這麼實現。
新增關注功能,開發關注頁面和粉絲頁面
新增關注功能,使用redis實現每一個關注物件的粉絲列表以及每一個使用者的關注物件列表。通過該列表的crud操作可以對應獲取粉絲列表和關注列表,並且實現關注和取關功能。
由於關注成功和新增粉絲成功時同一個事務裡的兩個操作,可以使用redis的事務multi來包裝事務並進行提交。
除此之外,關注成功或者被關注還可以通過事件機制來生成傳送郵件的事件,由非同步的佇列處理器來完成事件響應,同樣是根據redis來實現。
對於粉絲列表,除了顯示粉絲的基本資訊之外,還要顯示當前使用者是否關注了這個粉絲,以便前端顯示。
對於關注列表來說,如果被關注物件是使用者的話,除了顯示使用者的基本資訊之外,還要顯示當前使用者是被這個使用者關注,以便前端顯示。
Timeline與新鮮事,推拉模式下的Feed流
微博的新鮮事功能介紹:關注好友的動態,比如關注好友的點贊,發表的問題,關注了某個問題等資訊,都是feed流的一部分。
在知乎中的feed流主要體現於:關注使用者的評論行為,關注使用者的關注問題行為。
feed流主要分為兩種,推模式和拉模式,推模式主要是把新鮮事推送給關注該使用者的粉絲,本例使用redis來儲存某個使用者接受的新鮮事id列表。這個資訊流又稱為timeline,根據使用者的唯一key來儲存。
拉模式主要是使用者直接找尋自己所有關注的人,並且到資料庫去查詢這些關注物件的新鮮事,直接返回。
推模式主要適合粉絲較少的小使用者,因為他們的粉絲量少,使用推模式產生的冗餘副本也比較少,並且可以減少使用者訪問的壓力。
拉模式主要適合大v,因為很多殭屍粉根本不需要推送資訊,用推模式發給這些殭屍粉就是浪費資源,所以讓使用者通過拉模式請求,只需要一個數據副本即可。同時如果是熱點資訊,這些資訊也可以放在快取,讓使用者首先拉取這些資訊,提高查詢效率。
使用feedhandler非同步處理上述的兩個事件,當事件發生時,根據事件實體進行重新包裝,構造一個新鮮事,因為所有新鮮事的格式是一樣的。需要包括:日期,新鮮事型別,發起者,新鮮事內容,然後把該資料存入資料庫,以便使用者使用pull模式拉出。
為了適配推送模式,此時也要把新鮮事放到該使用者所有粉絲的timeline裡,這樣的話就同時實現了推和拉的操作了。
使用python爬蟲爬取知乎和v2ex資料,充實網站資訊
安裝python3.x並且配置環境變數。同時安裝pycharm,安裝pip。
安裝好以後,先熟悉python的語法,寫一些例子,比如資料型別,操作符,方法呼叫,以及面嚮物件的技術。
因為資料是要匯入資料庫的,所以這裡安裝SQL/">MySQLdb的一個庫,並且寫一下連線資料庫的程式碼,寫一下簡單的crud進行測試。
使用requests庫作為解析http請求的工具,使用beautifulsoup作為解析html程式碼的工具,請求之後直接使用css選擇器匹配。即可獲得內容。
當然現在我們有更方便的工具pyspider,可以方便解析請求並且可以設定代理,偽裝身份等,直接傳入url並且寫好多級的解析函式,程式便會迭代執行,直到把所有頁面的內容解析出來。這裡我們直接啟動pyspider的web應用並且寫好python程式碼,就可以執行爬蟲了。
知乎:先找到問題,再把問題下所有的回答進行爬取,最後把問題和評論一起處理。
使用solr搭建全文搜尋引擎,開發知乎的全文搜尋功能
solr是一個成熟的全文搜尋引擎工具,底層是Lucene實現,主要是java語言寫的。
下載solr6.2。完成solr環境搭建,簡單測試多副本部署和單機部署。
solr預設英文分詞,需要加入中文分詞工具IK-Analyzer。
solr中一個core代表一個全文搜尋集,我們可以在server資料夾中找到我們建立的core。然後根據需要修改conf裡的配置檔案,首先修改managed-schema來設定分詞規則,我們在此加入中文分詞型別,並且配置其索引分詞和查詢分詞,此處需要引入IK-Analyzer的jar包,jar包可以通過maven專案打包而獲得。
索引分詞指的是建立索引使用的分詞,比如你好北京,可以分為你 你好 北京 北 等情況。而查詢分詞是根據需求進行查詢時的分詞,可以分為你好 北京。
為了通過資料庫向solr匯入資料,我們需要配置資料匯入處理器,這是需要修改solrconfig檔案來配置資料匯入處理器,並且在solr-data-config中配置本地資料庫地址,這樣就可以在solr的web頁面中進行資料庫匯入了。匯入之後自動建立索引,我們就可以使用solr來對資料庫進行全文搜尋了。比如mysql資料庫進行普通搜尋,把資料匯入solr進行全文搜尋。
開發搜尋相關功能,開發service並且接入solr的api,從而連線本機的solr服務並且執行查詢和索引操作。只需要指定關鍵字,以及我們要搜尋的欄目(本例中主要title和content,所以傳入這兩個欄位,並且在搜尋結果中加亮關鍵字。開發相關controller以及頁面。並且在新增問題以後執行非同步事件,將新增的問題資料加入solr的資料庫中,以便後面進行搜尋。
產品功能擴充套件以及技術深度擴充套件
產品功能擴充套件
1. 使用者註冊,郵箱啟用流程 2. 首頁滾動到底部自動載入更多 3. 管理員後臺管理 4. 運營推薦問題置頂 5. timeline推拉結合 6. 個性化首頁,timeline更多事件
技術深度擴充套件
1. 搜尋結果排序打分 2. 爬蟲覆蓋使用者,評論,內容去html標籤 3. 個性化推薦