項目地址 https://github.com/JabinGP/demo-chatroom,對你有幫助的話請多多star
go+iris+jwt+mysql+gorm+viper,iris項目實戰簡易聊天室,登陸、註冊、私聊、羣聊。前端
git clone https://github.com/JabinGP/demo-chatroom.git cd demo-chatroom // 複製config.toml.example 爲 config.toml 並填寫數據庫信息,或者可選修改端口號 go run demo-chatroom.go
默認爲8888端口,啓動後訪問http://localhost:8888
便可,或者訪問演示地址http://mike.jabingp.cn:8888
mysql
用了react,可是沒用ui框架,不少的小細節上表現並很差,湊合着看吧,重點放在後端。react
聊天框設置了窗口自動滾動到底端,可是api是react提供的,發如今許多瀏覽器上並不兼容,使用chrome瀏覽器能夠解決這個問題。git
註冊後手動返回選擇登錄,消息框裏面的紅色名稱爲公共發言,灰色名稱爲私聊發言、能夠在紅色的框裏面指定接收者的名稱,若是不指定的話,默認是公共發言,指定後只有對應的用戶能看到信息。github
藍色框內顯示本身的用戶名,點擊即直接退出登陸。golang
api格式基於restful設計,登陸功能使用jwt完成,許多接口須要登陸狀態,請求的時候須要攜帶JWT,具體請看golang iris的jwt實踐,另外便於測試,JWT簽發有效時間只設置了20分鐘,過時須要從新登陸。web
功能 | 請求方式 | 地址 |
---|---|---|
獲取登陸token | POST | http://localhost:8888/v1/login |
查找用戶 | GET | http://localhost:8888/v1/user |
註冊 | POST | http://localhost:8888/v1/user |
用戶本身修改信息 | PUT | http://localhost:8888/v1/user |
用戶發送信息 | POST | http://localhost:8888/v1/message |
用戶獲取信息 | GET | http://localhost:8888/v1/message |
用戶獲取token信息 | GET | http://localhost:8888/v1/token/info |
詳細請求參數能夠在demo-chatroom的postman-api文檔裏查看。sql
或者查看源碼,請求參數在model/reqo
裏面查看,響應參數能夠在model/reso
裏查看chrome
聊天功能AJAX不是最好的選擇,WebSocket比較好,可是被要求使用了AJAX因此沒有選擇後者。數據庫
項目的前端比較簡陋,由於只是做爲demo使用。
英語不是很好,代碼註釋用英語只是由於懶得切換輸入法。
第一次用go開發web項目,也是第一次用react寫前端,因爲前端沒怎麼注重項目結構(xjbx),就不放源碼了,把項目編譯後放在了assets文件夾下,可讀性不好,可是能夠和後端一塊兒啓動,不須要單獨啓動前端,比較方便查看效果。若是還有時間會考慮用原生寫一個極簡版的供你們參考原理。
第一次用ORM操做數據庫,感受好難用,我仍是寧願手寫sql,好多想要的效果翻半天文檔都找不到解決方案,後期有機會考慮用sqlx重構。
最近對Go比較有興趣,又接到任務編寫一個簡易聊天室,發現目前iris的項目實踐比較少,只有一些HelloWorld級別的示例,因而決定用Go來作,而後開源出來供大互相參考借鑑,固然項目結構如何設計徹底基於我有限的開發經驗,對於不合理的地方,請給出你寶貴的意見。
這個項目有以下要求
登錄功能此次選用JWT
來實現,JWT
和Session
各自的優劣就再也不贅述。
基於AJAX是全部先後端分離項目的必備,所以這個功能不過多討論,這裏重點在於無刷新,難點在哪?
用戶的操做邏輯是,在聊天室裏面發送數據,而後數據就被髮出去,聊天界面要顯示出本身發送的數據,以及要實時更新別人發出來的數據。
前端和後端之間是經過AJAX來交流的,前端發送數據和後端發送數據能夠表現爲
這裏有什麼問題?問就在前端永遠只能主動發起請求,然後端永遠只能接受請求。這意味着最新的消息永遠沒法實時地從後端主動發送給前端,最新的消息只能先存放在後端,而後等待前端發起請求,後端才能返回數據。
因爲後端是沒有能力主動推送消息給前端的,所以用戶獲取最新數據的解決方法是前端設置一個定時器每隔一段比較短的時間就請求一次後臺接口(輪詢)
,這樣就能不斷更新數據。
前端已經肯定使用AJAX定時輪詢後臺接口來獲取最新數據,爲了數據實時性,輪詢間隔會小於1s
,這樣又會帶來另個問題,後端在如此頻繁的請求下,必定不能每次都將全部數據都傳輸出去,一是數據大小致使的網路傳輸效率、流量成本問題,二是數據大小致使的前端判斷新數據的效率問題,那麼後端每次必須都返回前端尚未接收過的數據,而問題在於--後端怎麼知道前端已經接收了哪些信息?
這個就要利用到消息的自增主鍵
,只須要前端每次請求的時候都攜帶上前端已經接收的最後的消息的主鍵
,因爲主鍵是不重複且自增的,咱們能夠很輕鬆的找出比該主鍵大的數據,也就是前端還沒接收到的數據。
語言
框架
數據存儲
技術
因爲使用了Gorm數據庫ORM框架,如下表都是自動生成的,自帶了
xxxxxx_at
字段
基於如上的需求,設計了users
和messages
兩個表
關鍵字段
數據庫表結構
Field | Type | Null | Key | Default | Extra |
---|---|---|---|---|---|
id | int(10) unsigned | NO | PRI | NULL | auto_increment |
created_at | timestamp | YES | NULL | ||
updated_at | timestamp | YES | NULL | ||
deleted_at | timestamp | YES | MUL | NULL | |
username | varchar(255) | YES | NULL | ||
passwd | varchar(255) | YES | NULL | ||
gender | bigint(20) | YES | NULL | ||
age | bigint(20) | YES | NULL | ||
interest | varchar(255) | YES | NULL |
關鍵字段
數據庫表結構
Field | Type | Null | Key | Default | Extra |
---|---|---|---|---|---|
id | int(10) unsigned | NO | PRI | NULL | auto_increment |
created_at | timestamp | YES | NULL | ||
updated_at | timestamp | YES | NULL | ||
deleted_at | timestamp | YES | MUL | NULL | |
sender_id | int(10) unsigned | YES | NULL | ||
receiver_id | int(10) unsigned | YES | NULL | ||
content | varchar(255) | YES | NULL | ||
send_time | timestamp | YES | NULL |
如下結構出於我的經驗,有不當之處請給出寶貴意見
model 定義一系列結構體
很好理解,就是數據庫對應的實體,但不要求與數據庫字段一一對應
不一樣接口請求的時候,能夠攜帶的參數以及響應的數據也不一樣,因此爲每個接口設計一個對應的請求實體和響應實體
如下爲我的理解
主要職責是,接受請求的請求參數,轉換爲reqo,進行簡單的請求參數驗證(我我的的定義與數據庫無關的驗證,如非空、非零),調用Service層的函數獲取pojo結果,並將pojo結果轉換封裝爲reso返回。
主要職責是,對Dao層的接口進一步封裝,提供通用的接口給Controller調用,返回數據能夠是pojo,在Service內須要進行數據的驗證,如(新增用戶,校驗用戶名是否重複)。
這裏基本上一個方法直接對應一條sql語句,不作任何的驗證,認爲接收到的數據是可靠的(已經通過了Controller和Service兩層的參數驗證了),返回數據能夠是pojo。
項目地址 https://github.com/JabinGP/demo-chatroom,對你有幫助的話請多多star