【golang】iris項目示例,基於AJAX的簡易聊天室

demo-chatroom

項目地址 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:8888mysql

前端

用了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來作,而後開源出來供大互相參考借鑑,固然項目結構如何設計徹底基於我有限的開發經驗,對於不合理的地方,請給出你寶貴的意見。

項目要點

這個項目有以下要求

  1. 基於AJAX
  2. 前端頁面須要無刷新(自動更新數據)
  3. 登陸功能
  4. 註冊功能(要求用戶有用戶名、密碼、性別、年齡、興趣愛好)

實現思路

登錄功能

登錄功能此次選用JWT來實現,JWTSession各自的優劣就再也不贅述。

基於AJAX,且無刷新

基於AJAX是全部先後端分離項目的必備,所以這個功能不過多討論,這裏重點在於無刷新,難點在哪?

用戶操做需求

用戶的操做邏輯是,在聊天室裏面發送數據,而後數據就被髮出去,聊天界面要顯示出本身發送的數據,以及要實時更新別人發出來的數據。

前端的操做邏輯

前端和後端之間是經過AJAX來交流的,前端發送數據和後端發送數據能夠表現爲

  • 發送數據:前端將須要發送的數據以JSON格式攜帶在請求裏,請求對於結構
  • 獲取數據:前端請求後臺獲取消息的接口,獲取最新消息

這裏有什麼問題?問就在前端永遠只能主動發起請求,然後端永遠只能接受請求。這意味着最新的消息永遠沒法實時地從後端主動發送給前端,最新的消息只能先存放在後端,而後等待前端發起請求,後端才能返回數據。

因爲後端是沒有能力主動推送消息給前端的,所以用戶獲取最新數據的解決方法是前端設置一個定時器每隔一段比較短的時間就請求一次後臺接口(輪詢),這樣就能不斷更新數據。

後端的操做邏輯

前端已經肯定使用AJAX定時輪詢後臺接口來獲取最新數據,爲了數據實時性,輪詢間隔會小於1s,這樣又會帶來另個問題,後端在如此頻繁的請求下,必定不能每次都將全部數據都傳輸出去,一是數據大小致使的網路傳輸效率、流量成本問題,二是數據大小致使的前端判斷新數據的效率問題,那麼後端每次必須都返回前端尚未接收過的數據,而問題在於--後端怎麼知道前端已經接收了哪些信息?

這個就要利用到消息的自增主鍵,只須要前端每次請求的時候都攜帶上前端已經接收的最後的消息的主鍵,因爲主鍵是不重複且自增的,咱們能夠很輕鬆的找出比該主鍵大的數據,也就是前端還沒接收到的數據。

項目技術棧

  • 語言

    • Golang
    • HTML
    • CSS
    • JavaScript
  • 框架

    • Iris 後端框架
    • React 前端框架
    • Gorm 數據庫ORM框架
    • Viper 多類型配置文件讀取支持
  • 數據存儲

    • Mysql 經典數據庫
  • 技術

    • JWT 簽發登錄令牌
    • AJAX 異步請求後端數據

數據庫設計結構

因爲使用了Gorm數據庫ORM框架,如下表都是自動生成的,自帶了 xxxxxx_at字段

基於如上的需求,設計了usersmessages兩個表

users

關鍵字段

  • id
  • username
  • passwd
  • gender
  • age
  • interest

數據庫表結構

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

messages

關鍵字段

  • id
  • sender_id -> 對應消息發送者
  • receiver_id -> 對應消息接受者
  • content
  • send_time

數據庫表結構

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

項目結構

如下結構出於我的經驗,有不當之處請給出寶貴意見
  • route 路由層,負責將"xxxxxx"請求映射到對應的函數
  • middleware 中間件層,能夠在執行函數先後進行攔截並處理,如登錄攔截
  • controller 控制層,存放與"xxxxxx"請求對應的函數,根據請求,調用業務層,並將數據進行格式封裝返回
  • service 業務層,調用持久層完成業務邏輯
  • dao 持久層,能夠理解爲sql執行到函數執行的封裝,因爲使用了ORM,本項目沒有dao層目錄
  • database 提供數據庫鏈接
  • model 定義一系列結構體

    • pojo 業務邏輯實體,如User,Message
    • reqo 請求數據實體,對應controller中的每一個方法
    • reso 響應數據實體,對應controller中的每一個方法
  • config 讀取配置,並提供單實例的配置文件實體供外訪問
  • tool 工具層
  • assets 靜態資源目錄,存放靜態資源(前端文件)

pojo、reqo、reso都是什麼

  • pojo

    很好理解,就是數據庫對應的實體,但不要求與數據庫字段一一對應

  • reqo(request object)、reso(response object)

    不一樣接口請求的時候,能夠攜帶的參數以及響應的數據也不一樣,因此爲每個接口設計一個對應的請求實體和響應實體

controller、service、dao到底有什麼區別

如下爲我的理解
  • Controller

    主要職責是,接受請求的請求參數,轉換爲reqo,進行簡單的請求參數驗證(我我的的定義與數據庫無關的驗證,如非空、非零),調用Service層的函數獲取pojo結果,並將pojo結果轉換封裝爲reso返回。

  • Service

    主要職責是,對Dao層的接口進一步封裝,提供通用的接口給Controller調用,返回數據能夠是pojo,在Service內須要進行數據的驗證,如(新增用戶,校驗用戶名是否重複)。

  • Dao

    這裏基本上一個方法直接對應一條sql語句,不作任何的驗證,認爲接收到的數據是可靠的(已經通過了Controller和Service兩層的參數驗證了),返回數據能夠是pojo。

項目地址 https://github.com/JabinGP/demo-chatroom,對你有幫助的話請多多star
相關文章
相關標籤/搜索