go+iris+jwt+mysql+xorm+viper、ログイン、登録、プライベート チャット、グループ チャットを含む、iris プロジェクトのシンプルなチャット ルーム。
まず、このドキュメントの下にあるフロントエンドの概要を参照して、その操作方法を確認してください (エネルギーが限られているため、UI は特にユーザーフレンドリーではありません)。
デモ アドレスにアクセスします。上の小さなアイコンの状態が正常であれば、アクセスできるようになり、数秒待つ必要があります。
このプロジェクトは現在、mysql 関連の適応のみを記述していますが、xorm を使用すると、他のデータベースをサポートすることは難しくありませんが、必要ではありません。ははは、自分で実行するのが面倒な場合は、ちょっと見てみてください。興味があれば、デモ URL を参照してください。
もともとsqliteをサポートしてデータベースパラメータを設定する必要がないようにしたいと思っていましたが、Windowsでsqliteをコンパイルするにはgcc環境を設定する必要があることを考慮すると、それはさらに面倒ですが、高速起動効果はなく、完全ではありません, そのため、他のデータベースは当面サポートされていません (いつか時間があるときに追加してください)。
したがって、プロジェクトでは次のパラメータを設定するだけで済みます。
git clone https://github.com/JabinGP/demo-chatroom.git
cd demo-chatroom
// 复制config.toml.example 为 config.toml 并填写数据库信息,或者可选修改端口号
go run main.go
デフォルトはポート 8888 です。起動後、 http://localhost:8888
にアクセスします。
React を使用しましたが、UI フレームワークは使用しませんでした。インターフェイスは携帯電話のサイズに合わせて作成されています。f12 を開くとより快適に見えます。焦点は後者にあります。
チャット ボックスはウィンドウを自動的に下にスクロールするように設定しますが、API は React によって提供されており、多くのブラウザーと互換性がないことがわかっています。この問題は Chrome ブラウザーを使用することで解決できます。
登録後、手動で戻ってログインを選択します。メッセージ ボックス内の赤い名前はパブリック スピーチ用であり、灰色の名前はプライベート チャット用です。指定しない場合は、デフォルトの名前を指定できます。公開発言を指定すると、該当するユーザーのみが情報を閲覧できるようになります。
青いボックスにユーザー名が表示されます。クリックすると、直接ログアウトします。
API形式はRestful設計に基づいており、ログイン機能はjwtを使用して完了します。多くのインターフェースはログインステータスを必要とし、リクエスト時にJWTを運ぶ必要があります。また、詳細はgolang irisのjwt実践を参照してください。 JWT の発行有効期限は 20 分に設定されているため、再度ログインする必要があります。
APIのリクエスト形式は一般的なインターフェースと同じで、GetはParamsを使用し、Post、Put、DeleteなどはBodyにJsonを使用してパラメータを渡します。
戻り値の形式は非常に物議を醸しており、私はしばらく研究してきました。次のような完全な http ステータス コードを使用し、戻り値のコンテンツにコードを追加することを推奨しています。
// 注册错误时
// http status 200
{
"code" : 40001 ,
"msg" : "注册用户名非法"
}
// 注册成功时
// http status 200
{
"code" : 200 ,
"msg" : "成功" ,
"data" : {
"username" : " JabinGP " ,
"id" : 3
}
}
エラーを示すために完全な http ステータス コードを使用することを推奨する人もいます。
// 注册错误时
// http status 400
{
"msg" : "注册用户名非法"
}
// 注册成功时
// http status 200
{
"username" : " JabinGP " ,
"id" : 3
}
実際、上記のアプローチには両方ともそれぞれ長所と短所があります。
上記の状況に基づいて、次の 2 つを組み合わせます。
成功すると、http ステータス コード 200 が返されます。
// 注册成功时
// http status 200
{
"username" : " JabinGP " ,
"id" : 3
}
障害が発生した場合、エラーを表す一般的に使用されるステータス コード 400 (リクエスト エラー)、500 (サーバー内部エラー)、404 (見つからない)、401 (認証失敗) を選択し、エラーを大まかに分類して、カスタマイズを返します。詳細なエラー原因を表すデータ内のコード、メッセージ、および詳細:
// 注册失败
// http status 400
{
"code" : 6 ,
"msg" : "数据检验失败" ,
"detail" : "用户名已存在"
}
// 登录失效
// http status 401
{
"code" : 8 ,
"msg" : "未认证登录" ,
"detail" : " Token is expired "
}
この組み合わせの後、成功コールバックは成功し、res.data.data を繰り返し記述する必要はありません。エラー コールバックはエラーのみを処理します。エラーは http ステータス コードによって判断でき、さらにコード化できます。エラーを処理するための詳細。
API リストは次のとおりです。localhost を mike.jabingp.cn に置き換えるか、デモ バックエンドに直接リクエストすることもできます。
関数 | リクエスト方法 | 住所 |
---|---|---|
ログイントークンを取得する | 役職 | http://localhost:8888/v1/login |
ユーザーを探す | 得る | http://localhost:8888/v1/user |
登録する | 役職 | http://localhost:8888/v1/user |
ユーザー自身が情報を変更する | 置く | http://localhost:8888/v1/user |
ユーザーがメッセージを送信 | 役職 | http://localhost:8888/v1/message |
ユーザーが情報を取得する | 得る | http://localhost:8888/v1/message |
ユーザーがトークン情報を取得する | 得る | http://localhost:8888/v1/token/info |
詳細なリクエストパラメータは、demo-chatroom の postman-api ドキュメントで確認できます。
または、ソースコードを表示します。リクエストパラメータはmodel/reqo
で表示でき、レスポンスパラメータはmodel/reso
チャット機能は AJAX が最適ではありませんが、WebSocket の方が優れていますが、AJAX を使用するように求められたため、後者は選択しませんでした。
プロジェクトのフロントエンドはデモとしてのみ使用されるため、比較的シンプルです。
私の英語はあまり得意ではなく、入力方法を切り替えるのが面倒なだけでコードのコメントは英語になっています。
go を使用して Web プロジェクトを開発するのはこれが初めてであり、react を使用してフロントエンドを作成するのも初めてです。フロントエンドはプロジェクトの構造 (xjbx) にあまり注意を払わないので、説明しません。ソースコードをコンパイルして、読みやすいようにアセットフォルダーに置きます。非常に貧弱ですが、フロントエンドを個別に起動する必要がなく、より便利です。効果。まだ時間があれば、みんなの参考のためにネイティブでミニマリスト バージョンを書くことを検討します。
初めて ORM を使ってデータベースを操作したとき、非常に使いづらく、SQL を手動で書きたいと思いました。必要な効果がたくさんあり、長い間ドキュメントを調べても解決策が見つかりませんでした。後で再構築に sqlx を使用することを検討するかもしれません。
最近、Go に興味を持ち始め、簡単なチャット ルームを作成するというタスクを受け取りました。iris にはプロジェクトの実践例がほとんどなく、HelloWorld レベルのサンプルしかないことがわかったので、Go を使用して実行することにしました。もちろん、プロジェクトの構造をどのように設計するかは、私の限られた開発経験に基づいています。無理な点については貴重なご意見をお願いします。
このプロジェクトには次の要件があります
今回はSession
JWT
使用してログイン機能を実装します。JWT とJWT
のメリットとデメリットについては詳しく説明しません。
AJAX ベースはすべてのフロントエンドとバックエンドの分離プロジェクトに必須であるため、この機能についてはあまり説明しません。ここでの焦点は更新ではありません。
ユーザーの操作ロジックは、チャット ルームでデータを送信し、そのデータが送信されることです。チャット インターフェイスは、自分が送信したデータを表示し、他のユーザーが送信したデータをリアルタイムで更新する必要があります。
フロントエンドとバックエンドは AJAX を介して通信します。フロントエンドの送信データとバックエンドの送信データは次のように表現できます。
ここで何が問題になっているのでしょうか?問題は、フロントエンドはリクエストをアクティブに開始することしかできず、バックエンドはリクエストを受け入れることしかできないことです。これは、最新のメッセージをバックエンドからフロントエンドにリアルタイムでアクティブに送信することはできないことを意味します。最新のメッセージは、まずバックエンドに保存され、その後、バックエンドがデータを返す前にフロントエンドがリクエストを開始するのを待つ必要があります。
バックエンドには積極的にメッセージをフロントエンドにプッシュする機能がないため、ユーザーが最新のデータを取得するための解決策は、フロントエンドがタイマーを設定し每隔一段比较短的时间就请求一次后台接口(轮询)
ことです。データは継続的に更新できます。
フロントエンドは、AJAX を使用してバックグラウンド インターフェイスを定期的にポーリングし、リアルタイム データを取得することにしました。ポーリング間隔は小于1s
このような頻繁なリクエストでは、バックエンドが毎回すべてのデータを送信する必要がなく、もう 1 つはデータ サイズによって生じる効率の問題です。フロントエンドが新しいデータを判断するということは、バックエンドが毎回受信していないデータを返さなければならないことを意味します。問題は、バックエンドがフロントエンドが受信した情報をどのようにして知るのかということです。
これには、メッセージの自增主键
の使用が必要です。主キーはリクエストを行うたびに、フロントエンドが受信した最后的消息的主键
を保持する必要があります。繰り返しと自動増加により、大きな主キーを持つデータは、フロントエンドがまだ受信していないデータです。
言語
フレーム
データストレージ
テクノロジー
Xorm データベース ORM フレームワークの使用により、次のテーブルが自動的に生成され、
xxxxxx_at
フィールドが付属します。
上記の要件に基づいて、 users
とmessages
2 つのテーブルが設計されました。
主要なフィールド
データベーステーブルの構造
分野 | タイプ | ヌル | 鍵 | デフォルト | 余分な |
---|---|---|---|---|---|
ID | bigint(20) | いいえ | PRI | NULL | auto_increment |
ユーザー名 | varchar(255) | はい | NULL | ||
パスワード | varchar(255) | はい | NULL | ||
性別 | bigint(20) | はい | NULL | ||
年 | bigint(20) | はい | NULL | ||
興味 | varchar(255) | はい | NULL | ||
作成日 | 日時 | はい | NULL | ||
更新済み | 日時 | はい | NULL | ||
削除済み_at | 日時 | はい | NULL |
主要なフィールド
データベーステーブルの構造
分野 | タイプ | ヌル | 鍵 | デフォルト | 余分な |
---|---|---|---|---|---|
ID | bigint(20) | いいえ | PRI | NULL | auto_increment |
送信者ID | bigint(20) | はい | NULL | ||
受信者ID | bigint(20) | はい | NULL | ||
コンテンツ | varchar(255) | はい | NULL | ||
送信時間 | bigint(20) | はい | NULL | ||
作成日 | 日時 | はい | NULL | ||
更新済み | 日時 | はい | NULL | ||
削除済み_at | 日時 | はい | NULL |
以下の構成は個人的な経験に基づいています。不適切な点がございましたら、貴重なご意見をお聞かせください。
ポジョ
わかりやすく言えば、データベースに対応するエンティティですが、データベースのフィールドと 1 対 1 対応する必要はありません。
reqo (リクエスト オブジェクト)、reso (レスポンス オブジェクト)
異なるインターフェース経由でリクエストを行う場合、伝送できるパラメータや応答データも異なるため、インターフェースごとに対応するリクエストエンティティと応答エンティティが設計されます。
以下は私の個人的な理解です
コントローラ
主な役割は、リクエストのリクエスト パラメータを受け入れ、reqo に変換し、単純なリクエスト パラメータの検証 (私の個人的な定義は、null 以外、ゼロ以外など、データベースとは関係のない検証です) を実行し、呼び出しを実行することです。 pojo 結果を取得するサービス層の関数。pojo 結果の変換はカプセル化され、reso で返されます。
サービス
主な役割は、Dao レイヤーのインターフェイスをさらにカプセル化し、コントローラーが呼び出すための共通インターフェイスを提供することです。(新しいユーザーの追加、ポジョの検証など) データ検証をサービス内で実行する必要があります。ユーザー名が繰り返されます)。
ダオ
基本的に、ここでのメソッドは検証なしで SQL ステートメントに直接対応し、受信したデータは信頼できると見なされ (コントローラー層とサービス層のパラメーターによって検証されている)、返されるデータは POJO である可能性があります。