go+iris+jwt+mysql+xorm+viper ห้องสนทนาเรียบง่ายที่ใช้งานได้จริงสำหรับโปรเจ็กต์ iris พร้อมการเข้าสู่ระบบ การลงทะเบียน แชทส่วนตัว และแชทกลุ่ม
ขั้นแรก โปรดดูคำแนะนำส่วนหน้าด้านล่างเอกสารนี้เพื่อทราบวิธีการใช้งาน (เนื่องจากพลังงานที่จำกัด UI จึงไม่เป็นมิตรกับผู้ใช้เป็นพิเศษ)
เข้าถึงที่อยู่สาธิต หากสถานะของไอคอนขนาดเล็กด้านบนเป็นปกติ คุณสามารถเข้าถึงได้ อาจเข้าสู่สถานะไม่เคลื่อนไหวและต้องรอสักครู่
ปัจจุบันโปรเจ็กต์เขียนเฉพาะการดัดแปลงที่เกี่ยวข้องกับ mySQL เท่านั้น แต่การใช้ xorm ก็สามารถสนับสนุนฐานข้อมูลอื่นได้ไม่ยาก แต่ก็ไม่จำเป็น ฮ่าๆ หากคุณขี้เกียจเกินไปที่จะรันด้วยตัวเองก็ลองดู ที่ URL สาธิต หากคุณสนใจ ตอนนี้ไม่มีใครมี mysql
เดิมทีฉันต้องการรองรับ sqlite ดังนั้นจึงไม่จำเป็นต้องกำหนดค่าพารามิเตอร์ฐานข้อมูล แต่เมื่อพิจารณาว่าการคอมไพล์ sqlite ภายใต้ windows จำเป็นต้องกำหนดค่าสภาพแวดล้อม 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
ฉันใช้การตอบสนอง แต่ฉันไม่ได้ใช้กรอบ UI รายละเอียดเล็กๆ น้อยๆ หลายอย่างทำงานได้ไม่ดีนัก อินเทอร์เฟซถูกสร้างขึ้นตามขนาดของโทรศัพท์มือถือ หากคุณเปิดคอมพิวเตอร์ คุณสามารถเปิด f12 ได้ . มาทำกันดีกว่า.
กล่องแชทจะตั้งค่าหน้าต่างให้เลื่อนไปที่ด้านล่างโดยอัตโนมัติ แต่ API นั้นจัดทำโดย React และพบว่าเข้ากันไม่ได้ในเบราว์เซอร์จำนวนมาก ปัญหานี้สามารถแก้ไขได้โดยใช้เบราว์เซอร์ Chrome
หลังจากลงทะเบียนแล้ว ให้กลับมาเลือกเข้าสู่ระบบด้วยตนเอง ชื่อสีแดงในกล่องข้อความใช้สำหรับการพูดในที่สาธารณะ และชื่อสีเทาสำหรับการแชทส่วนตัว คุณสามารถระบุชื่อผู้รับในกล่องสีแดงได้ ค่าเริ่มต้นคือ คำพูดสาธารณะ หลังจากระบุแล้ว เฉพาะผู้ใช้ที่เกี่ยวข้องเท่านั้นที่สามารถดูข้อมูลได้
ชื่อผู้ใช้ของคุณจะแสดงอยู่ในกล่องสีน้ำเงิน คลิกเพื่อออกจากระบบโดยตรง
รูปแบบ API ขึ้นอยู่กับการออกแบบที่เงียบสงบ และฟังก์ชันการเข้าสู่ระบบจะเสร็จสมบูรณ์โดยใช้ jwt อินเทอร์เฟซจำนวนมากจำเป็นต้องมีสถานะการเข้าสู่ระบบ และต้องมีการดำเนินการ JWT เมื่อทำการร้องขอ สำหรับรายละเอียด โปรดดูแนวทางปฏิบัติของ jwt ของ golang iris สะดวกสำหรับการทดสอบ ระยะเวลาการออก JWT กำหนดไว้เพียง 20 นาที โดยจะต้องเข้าสู่ระบบอีกครั้ง
รูปแบบคำขอ API เหมือนกับอินเทอร์เฟซทั่วไป Get ใช้ Params และ Post, Put, Delete ฯลฯ ใช้ Json ใน Body เพื่อส่งผ่านพารามิเตอร์
รูปแบบการส่งคืนค่อนข้างขัดแย้ง ฉันค้นคว้ามาระยะหนึ่งแล้ว บางคนสนับสนุนให้ใช้รหัสสถานะ http แบบเต็ม 200 รายการและเพิ่มโค้ดลงในเนื้อหาส่งคืนเพื่อระบุข้อผิดพลาด เช่นนี้
// 注册错误时
// 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
}
ที่จริงแล้ว ทั้งสองวิธีข้างต้นมีข้อดีและข้อเสียในตัวเอง:
จากสถานการณ์ข้างต้น ฉันจะรวมทั้งสองเข้าด้วยกัน:
เมื่อสำเร็จ ให้ส่งคืนรหัสสถานะ 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 |
พารามิเตอร์คำขอโดยละเอียดสามารถดูได้ในเอกสารบุรุษไปรษณีย์ API ของห้องสาธิต
หรือดูซอร์สโค้ด พารามิเตอร์คำขอสามารถดูได้ใน model/reqo
และพารามิเตอร์การตอบสนองสามารถดูได้ใน model/reso
AJAX ไม่ใช่ตัวเลือกที่ดีที่สุดสำหรับฟังก์ชันแชท WebSocket ดีกว่า แต่ฉันถูกขอให้ใช้ AJAX ดังนั้นฉันจึงไม่ได้เลือกอันหลัง
ส่วนหน้าของโปรเจ็กต์ค่อนข้างเรียบง่ายเนื่องจากใช้เป็นตัวอย่างเท่านั้น
ภาษาอังกฤษของฉันไม่ค่อยดีนัก และความคิดเห็นของโค้ดก็เป็นภาษาอังกฤษเพียงเพราะฉันขี้เกียจเกินกว่าจะเปลี่ยนวิธีการป้อนข้อมูล
นี่เป็นครั้งแรกที่ฉันใช้ go เพื่อพัฒนาโครงการเว็บ และเป็นครั้งแรกที่ฉันใช้ react เพื่อเขียนส่วนหน้า เนื่องจากส่วนหน้าไม่ได้ให้ความสำคัญกับโครงสร้างของโครงการ (xjbx) มากนัก ฉันจะไม่ทำเช่นนั้น ใส่ซอร์สโค้ด ฉันคอมไพล์โปรเจ็กต์และวางไว้ในโฟลเดอร์ทรัพย์สินเพื่อให้อ่านง่าย ผล. หากฉันยังมีเวลา ฉันจะพิจารณาเขียนเวอร์ชันมินิมอลในภาษาเนทีฟเพื่อให้ทุกคนใช้อ้างอิง
นี่เป็นครั้งแรกที่ฉันใช้ ORM ในการใช้งานฐานข้อมูล ฉันรู้สึกอยากจะเขียน SQL ด้วยมือมากกว่า มีเอฟเฟกต์ที่ต้องการมากมายและฉันไม่สามารถหาวิธีแก้ไขได้หลังจากอ่านเอกสารมาเป็นเวลานาน ฉันจะพิจารณาใช้ SQLX เพื่อสร้างใหม่ในภายหลัง
เมื่อเร็วๆ นี้ ฉันเริ่มสนใจ Go มากขึ้น และได้รับงานให้เขียนห้องสนทนาแบบง่ายๆ ฉันพบว่าปัจจุบันมีแนวทางปฏิบัติของโปรเจ็กต์ใน Iris เพียงเล็กน้อย มีเพียงตัวอย่างระดับ HelloWorld บางส่วนเท่านั้น ฉันจึงตัดสินใจใช้ Go เพื่อทำสิ่งนี้ แล้วเปิดแหล่งที่มาเพื่อใช้อ้างอิงร่วมกัน แน่นอนว่าการออกแบบโครงสร้างโครงการนั้นขึ้นอยู่กับประสบการณ์การพัฒนาที่จำกัดของฉันอย่างสมบูรณ์
โครงการนี้มีข้อกำหนดดังต่อไปนี้
ฟังก์ชันการเข้าสู่ระบบถูกใช้งานโดยใช้ JWT
ในครั้งนี้ ข้อดีและข้อเสียของ JWT
และ Session
จะไม่ถูกกล่าวถึงโดยละเอียด
การทำงานแบบ AJAX เป็นสิ่งจำเป็นสำหรับโปรเจ็กต์การแยกส่วนหน้าและส่วนหลังทั้งหมด ดังนั้นฟังก์ชันนี้จะไม่มีการพูดคุยกันมากเกินไป ประเด็นที่นี่คือไม่มีการรีเฟรช
ตรรกะการทำงานของผู้ใช้คือการส่งข้อมูลในห้องสนทนา จากนั้นข้อมูลจะถูกส่งออกไป อินเทอร์เฟซการแชทควรแสดงข้อมูลที่ส่งด้วยตัวเองและอัปเดตข้อมูลที่ส่งโดยผู้อื่นแบบเรียลไทม์
ส่วนหน้าและส่วนหลังสื่อสารผ่าน AJAX ข้อมูลที่ส่งส่วนหน้าและข้อมูลการส่งส่วนหลังสามารถแสดงเป็น
มีปัญหาอะไรที่นี่? ปัญหาคือส่วนหน้าสามารถเริ่มต้นคำขอได้เท่านั้น และส่วนหลังสามารถยอมรับได้เฉพาะคำขอเท่านั้น ซึ่งหมายความว่าไม่สามารถส่งข้อความล่าสุดจากแบ็กเอนด์ไปยังฟรอนต์เอนด์แบบเรียลไทม์ได้ ข้อความล่าสุดสามารถจัดเก็บไว้ในแบ็กเอนด์ก่อนได้ จากนั้นรอให้ฟรอนต์เอนด์เริ่มคำขอก่อนที่แบ็กเอนด์จะสามารถส่งคืนข้อมูลได้
เนื่องจากแบ็กเอนด์ไม่มีความสามารถในการพุชข้อความไปที่ฟรอนต์เอนด์ วิธีแก้ปัญหาสำหรับผู้ใช้ในการรับข้อมูลล่าสุดคือการให้ฟรอนต์เอนด์ตั้งเวลา每隔一段比较短的时间就请求一次后台接口(轮询)
ดังนั้น สามารถอัพเดตข้อมูลได้อย่างต่อเนื่อง
ส่วนหน้าได้ตัดสินใจใช้ AJAX เพื่อสำรวจอินเทอร์เฟซเบื้องหลังเป็นประจำเพื่อรับข้อมูลล่าสุด เพื่อประโยชน์ของข้อมูลแบบเรียลไทม์ ช่วงเวลาการโพลจะ小于1s
สิ่งนี้จะนำมาซึ่งปัญหาอื่นตามมา ภายใต้คำขอบ่อยครั้ง แบ็กเอนด์จะต้องไม่ส่งข้อมูลทั้งหมดทุกครั้ง หนึ่งคือประสิทธิภาพการส่งข้อมูลเครือข่ายและต้นทุนการรับส่งข้อมูลที่เกิดจากขนาดข้อมูล อีกอย่างคือปัญหาประสิทธิภาพที่เกิดขึ้น การตัดสินข้อมูลใหม่ของส่วนหน้าหมายความว่าส่วนหลังจะต้องส่งคืนข้อมูลที่ส่วนหน้าไม่ได้รับทุกครั้ง ปัญหาคือ - ส่วนหลังจะรู้ได้อย่างไรว่าข้อมูลใดที่ส่วนหน้าได้รับ
สิ่งนี้จำเป็นต้องใช้自增主键
ของข้อความ ส่วนหน้าจะต้องดำเนินการ最后的消息的主键
ที่ได้รับจากส่วนหน้าทุกครั้งที่ทำการร้องขอ เนื่องจากคีย์หลักไม่ใช่ การทำซ้ำและเพิ่มอัตโนมัติทำให้เราสามารถหาอัตราส่วนได้อย่างง่ายดาย ข้อมูลที่มีคีย์หลักขนาดใหญ่คือข้อมูลที่ส่วนหน้ายังไม่ได้รับ
ภาษา
กรอบ
การจัดเก็บข้อมูล
เทคโนโลยี
เนื่องจากการใช้เฟรมเวิร์ก ORM ฐานข้อมูล Xorm ตารางต่อไปนี้จะถูกสร้างขึ้นโดยอัตโนมัติและมาพร้อมกับฟิลด์
xxxxxx_at
ตามข้อกำหนดข้างต้น มีการออกแบบตารางสองตาราง users
และ messages
ฟิลด์สำคัญ
โครงสร้างตารางฐานข้อมูล
สนาม | พิมพ์ | โมฆะ | สำคัญ | ค่าเริ่มต้น | พิเศษ |
---|---|---|---|---|---|
บัตรประจำตัวประชาชน | ใหญ่(20) | เลขที่ | ปรีดี | โมฆะ | อัตโนมัติ_เพิ่ม |
ชื่อผู้ใช้ | วาร์ชาร์(255) | ใช่ | โมฆะ | ||
รหัสผ่าน | วาร์ชาร์(255) | ใช่ | โมฆะ | ||
เพศ | ใหญ่(20) | ใช่ | โมฆะ | ||
อายุ | ใหญ่(20) | ใช่ | โมฆะ | ||
ความสนใจ | วาร์ชาร์(255) | ใช่ | โมฆะ | ||
สร้างขึ้น_at | วันที่และเวลา | ใช่ | โมฆะ | ||
อัปเดต_ที่ | วันที่และเวลา | ใช่ | โมฆะ | ||
ลบแล้ว_at | วันที่และเวลา | ใช่ | โมฆะ |
ฟิลด์สำคัญ
โครงสร้างตารางฐานข้อมูล
สนาม | พิมพ์ | โมฆะ | สำคัญ | ค่าเริ่มต้น | พิเศษ |
---|---|---|---|---|---|
บัตรประจำตัวประชาชน | ใหญ่(20) | เลขที่ | ปรีดี | โมฆะ | อัตโนมัติ_เพิ่ม |
sender_id | ใหญ่(20) | ใช่ | โมฆะ | ||
ผู้รับ_id | ใหญ่(20) | ใช่ | โมฆะ | ||
เนื้อหา | วาร์ชาร์(255) | ใช่ | โมฆะ | ||
ส่ง_เวลา | ใหญ่(20) | ใช่ | โมฆะ | ||
สร้างขึ้น_at | วันที่และเวลา | ใช่ | โมฆะ | ||
อัปเดต_ที่ | วันที่และเวลา | ใช่ | โมฆะ | ||
ลบแล้ว_at | วันที่และเวลา | ใช่ | โมฆะ |
โครงสร้างต่อไปนี้อิงจากประสบการณ์ส่วนตัว หากมีสิ่งใดที่ไม่เหมาะสม โปรดให้ข้อเสนอแนะอันมีค่าของคุณแก่เรา
โปโจ
ง่ายต่อการเข้าใจ เป็นเอนทิตีที่สอดคล้องกับฐานข้อมูล แต่ไม่จำเป็นต้องโต้ตอบแบบตัวต่อตัวกับฟิลด์ฐานข้อมูล
reqo (วัตถุร้องขอ), reso (วัตถุตอบสนอง)
เมื่อทำการร้องขอผ่านอินเทอร์เฟซที่แตกต่างกัน พารามิเตอร์ที่สามารถรับได้และข้อมูลการตอบสนองจะแตกต่างกันเช่นกัน ดังนั้นเอนทิตีคำขอที่เกี่ยวข้องและเอนทิตีการตอบสนองจึงได้รับการออกแบบสำหรับแต่ละอินเทอร์เฟซ
ต่อไปนี้เป็นความเข้าใจส่วนตัวของผม
คอนโทรลเลอร์
ความรับผิดชอบหลักคือการยอมรับพารามิเตอร์คำขอของคำขอ แปลงเป็น reqo ทำการตรวจสอบพารามิเตอร์คำขออย่างง่าย (คำจำกัดความส่วนตัวของฉันคือการตรวจสอบที่ไม่เกี่ยวข้องกับฐานข้อมูล เช่น ไม่เป็นค่าว่าง ไม่เป็นศูนย์) การโทร ฟังก์ชันของเลเยอร์บริการเพื่อรับผลลัพธ์ pojo และการแปลงผลลัพธ์ pojo จะถูกห่อหุ้มและส่งคืนในรูปแบบ reso
บริการ
ความรับผิดชอบหลักคือการห่อหุ้มอินเทอร์เฟซของเลเยอร์ Dao เพิ่มเติม และจัดให้มีอินเทอร์เฟซทั่วไปเพื่อให้ผู้ควบคุมสามารถเรียกได้ ข้อมูลที่ส่งคืนจะต้องดำเนินการตรวจสอบข้อมูลในบริการ เช่น (เพิ่มผู้ใช้ใหม่ ตรวจสอบว่า ชื่อผู้ใช้ซ้ำ)
ดาว
โดยพื้นฐานแล้ว วิธีการที่นี่จะสอดคล้องกับคำสั่ง SQL โดยตรงโดยไม่มีการตรวจสอบใด ๆ ข้อมูลที่ได้รับถือว่าเชื่อถือได้ (ได้รับการตรวจสอบโดยพารามิเตอร์ของเลเยอร์ตัวควบคุมและการบริการ) และข้อมูลที่ส่งคืนอาจเป็น POJO