目錄
2、管理員控制器定義:admin_controller.go
3、管理員數據提供模塊定義:admin_service.go
一、項目結構
二、數據庫
1、管理員表:admin
CREATE TABLE `admin` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`admin_name` varchar(32) DEFAULT NULL,
`create_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
`status` int(11) NOT NULL DEFAULT '0',
`avatar` varchar(255) DEFAULT NULL,
`pwd` varchar(255) DEFAULT NULL,
`city_name` varchar(12) DEFAULT NULL,
`city_id` int(11) DEFAULT NULL,
`admin_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_admin_city_id` (`city_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of admin
-- ----------------------------
INSERT INTO `admin` VALUES ('1', 'davie', '2020-05-03 17:05:27', '1', '', '123', '湖北武漢', '1', null);
INSERT INTO `admin` VALUES ('2', 'lili', '2020-05-21 17:05:36', '2', '2', '123', '湖北隨州', '2', null);
說明:id爲自增主鍵
三、服務器配置
1、配置端口等信息:config.json
{
"app_name": "CmsProject",
"port": "9000",
"static_path": "/manage/static",
"mode": "dev"
}
2、讀取配置文件並加載服務器配置:config.go
type AppConfig struct {
AppName string `json:"app_name"`
Port string `json:"port"`
StaticPath string `json:"static_path"`
Mode string `json:"mode"`
}
var ServConfig AppConfig
//初始化服務器配置
func InitConfig()*AppConfig {
file,err := os.Open("config.json")
if err != nil {
panic(err.Error())
}
decoder := json.NewDecoder(file)
conf := AppConfig{}
err = decoder.Decode(&conf)
if err != nil {
panic(err.Error())
}
return &conf
}
3、創建及配置數據庫引擎:engine.go
import (
_ "github.com/go-sql-driver/mysql" //不能忘記導入
"github.com/go-xorm/xorm"
"irisDemo/CmsProject/model"
)
/**
* 實例化數據庫引擎方法:mysql的數據引擎
*/
func NewMysqlEngine() *xorm.Engine {
//數據庫引擎
engine, err := xorm.NewEngine("mysql", "root:123456@/iris?charset=utf8")
//根據實體創建表
//err = engine.CreateTables(new(model.Admin))
//同步數據庫結構:主要負責對數據結構實體同步更新到數據庫表
/**
* 自動檢測和創建表,這個檢測是根據表的名字
* 自動檢測和新增表中的字段,這個檢測是根據字段名,同時對錶中多餘的字段給出警告信息
* 自動檢測,創建和刪除索引和唯一索引,這個檢測是根據索引的一個或多個字段名,而不根據索引名稱。因此這裏需要注意,如果在一個有大量數據的表中引入新的索引,數據庫可能需要一定的時間來建立索引。
* 自動轉換varchar字段類型到text字段類型,自動警告其它字段類型在模型和數據庫之間不一致的情況。
* 自動警告字段的默認值,是否爲空信息在模型和數據庫之間不匹配的情況
*/
//Sync2是Sync的基礎上優化的方法
err = engine.Sync2(
new(model.Admin),
)
if err != nil {
panic(err.Error())
}
//設置顯示sql語句
engine.ShowSQL(true)
engine.SetMaxOpenConns(10)
return engine
}
四、後端
1、管理員結構體定義:admin.go
//定義管理員結構體
type Admin struct {
//如果field名稱爲Id,而且類型爲int64,並沒有定義tag,則會被xorm視爲主鍵,並且擁有自增屬性
AdminId int64 `xorm:"pk autoincr 'id'" json:"id"` // 主鍵 自增
AdminName string `xorm:"varchar(32)" json:"admin_name"`
CreateTime time.Time `xorm:"DateTime" json:"create_time"`
Status int64 `xorm:"default 0" json:"status"`
Avatar string `xorm:"varchar(255)" json:"avatar"`
Pwd string `xorm:"varchar(255)" json:"pwd"` //管理員密碼
CityName string `xorm:"varchar(12)" json:"city_name"` //管理員所在城市名稱
CityId int64 `xorm:"index" json:"city_id"`
//City *City `xorm:"- <- ->"` //所對應的城市結構體(基礎表結構體)
}
2、管理員控制器定義:admin_controller.go
我們使用mvc包模式來進行功能開發,在進行了結構體定義以後,我們接着定義控制器。控制器負責來完成我們請求的邏輯流程控制,是我們功能開發的核心樞紐。在AdminController定義中,包含iris.Context上下文處理對象,用於數據功能處理的管理員模塊功能實現AdminService,還有用於session管理的對象。定義PostLogin方法來處理用戶登陸請求。
/**
* 管理員控制器
*/
type AdminController struct {
//iris框架自動爲每個請求都綁定上下文對象:可作爲接受參數
Ctx iris.Context
//admin功能實體:引入Service接口
Service service.AdminService
//session對象:存儲session信息
Session *sessions.Session
}
const (
ADMIN = "admin" //管理員登錄成功後存儲的session信息的key
)
//將發送請求的字段映射爲指定字段
type AdminLogin struct {
UserName string `json:"user_name"`
Password string `json:"password"`
}
/**
* 管理員登錄功能:json請求格式
* 接口:/admin/login
*/
func (ac *AdminController) PostLogin(context iris.Context) mvc.Result {
var adminLogin AdminLogin
ac.Ctx.ReadJSON(&adminLogin) //自動將請求的json字符串映射爲AdminLogin結構體
//數據參數檢驗
if adminLogin.UserName == "" || adminLogin.Password == "" {
return mvc.Response{
Object: map[string]interface{}{
"status": "0",
"success": "登錄失敗",
"message": "用戶名或密碼爲空,請重新填寫後嘗試登錄",
},
}
}
//根據用戶名、密碼到數據庫中查詢對應的管理信息
admin, exist := ac.Service.GetByAdminNameAndPassword(adminLogin.UserName, adminLogin.Password)
//管理員不存在
if !exist {
return mvc.Response{
Object: map[string]interface{}{
"status": "1",
"success": "登錄失敗",
"message": "用戶名或者密碼錯誤,請重新登錄",
},
}
}
//管理員存在 設置session
userByte, _ := json.Marshal(admin)
ac.Session.Set(ADMIN, userByte)
return mvc.Response{
Object: map[string]interface{}{
"status": "1",
"success": "登錄成功",
"message": "管理員登錄成功",
},
}
}
3、管理員數據提供模塊定義:admin_service.go
//定義AdminService接口
type AdminService interface {
//通過管理員用戶名+密碼 獲取管理員實體 如果查詢到,返回管理員實體,並返回true
//否則 返回 nil ,false
GetByAdminNameAndPassword(username, password string) (models.Admin, bool)
}
//在我們實際的開發過程中,我們往往將數據提供服務模塊設計成接口,這樣設計的目的是接口定義和具體
//的功能編程實現了分離,有助於我們在不同的實現方案之間進行切換,成本非常小
func NewAdminService(db *xorm.Engine) AdminService {
return &adminSevice{
engine: db,
}
}
/**
* 管理員的服務實現結構體
*/
type adminSevice struct {
engine *xorm.Engine
}
/**
* 通過用戶名和密碼查詢管理員
*/
func (ac *adminSevice) GetByAdminNameAndPassword(username, password string) (models.Admin, bool) {
var admin models.Admin
ac.engine.Where("admin_name = ? and pwd = ? ", username, password).Get(&admin)
fmt.Println(admin,"............",admin.AdminId != 0)
return admin, admin.AdminId != 0
}
4、控制器綁定,路由處理 main.go
管理員結構體,控制器和功能邏輯實現了以後,我們需要在程序入口處做控制器綁定,指定我們定義的管理員控制器進行路由處理,具體的綁定操作如下:
func main() {
app := newApp()
//應用App設置
configation(app)
//路由設置
mvcHandle(app)
config := config.InitConfig()
addr := "localhost:" + config.Port
app.Run(
iris.Addr(addr), //在端口8080進行監聽
iris.WithoutServerError(iris.ErrServerClosed), //無服務錯誤提示
iris.WithOptimizations, //對json數據序列化更快的配置
)
}
//構建App
func newApp() *iris.Application {
app := iris.New()
//設置日誌級別 開發階段爲debug
app.Logger().SetLevel("debug")
//註冊靜態資源
app.HandleDir("/static", "./static")
app.HandleDir("/manage/static", "./static")
app.HandleDir("/img", "./static/img")
//註冊視圖文件
app.RegisterView(iris.HTML("./static", ".html"))
app.Get("/", func(context context.Context) {
context.View("index.html")
})
return app
}
/**
* 項目設置
*/
func configation(app *iris.Application) {
//配置 字符編碼
app.Configure(iris.WithConfiguration(iris.Configuration{
Charset: "UTF-8",
}))
//錯誤配置
//未發現錯誤
app.OnErrorCode(iris.StatusNotFound, func(context context.Context) {
context.JSON(iris.Map{
"errmsg": iris.StatusNotFound,
"msg": " not found ",
"data": iris.Map{},
})
})
app.OnErrorCode(iris.StatusInternalServerError, func(context context.Context) {
context.JSON(iris.Map{
"errmsg": iris.StatusInternalServerError,
"msg": " interal error ",
"data": iris.Map{},
})
})
}
//MVC 架構模式處理
func mvcHandle(app *iris.Application) {
//啓用session
sessManager := sessions.New(sessions.Config{
Cookie: "sessioncookie",
Expires: 24 * time.Hour,
})
engine := datasource.NewMysqlEngine()
//管理員模塊功能
adminService := service.NewAdminService(engine)
admin := mvc.New(app.Party("/admin"))//設置路由組
admin.Register(
adminService,
sessManager.Start,
)
//通過mvc的Handle方法進行控制器的指定
admin.Handle(new(controller.AdminController))
}
五、瀏覽器Post請求測試(使用postman)
1、請求設置及結果
2、處理過程分析
從main函數的執行開始分析
(1)通過iris構建App:返回*iris.Application
- app := iris.New()
- 設置日誌級別:app.Logger().SetLevel("debug")
- 註冊靜態資源和視圖文件:app.HandleDir、app.RegisterView
- 設置默認請求:app.Get("/", func(context context.Context) {…………})
(2)項目設置
- 配置 字符編碼
- 配置錯誤……
(3)MVC 架構模式處理/路由設置
- 啓用session:sessions.New
- 加載數據庫引擎的設置 :engine := datasource.NewMysqlEngine()
- 管理員模塊功能 :adminService := service.NewAdminService(engine)
- 設置路由組:app.Party
- 通過mvc的Handle方法進行控制器的指定
(4)初始化服務器配置
- 調用config.InitConfig()->實際讀取了config.json中的配置信息
(5)設置iris的Addr並運行
- app.Run
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·
說明:本案例使用的是go mod,導入的包不能再有本地的導入,導入本地的再有本地的導入直接失效,即使你用了replace,程序也會無視,而直接去代理服務器傻乎乎的下載你顯示制定的本地包。。。。。。。。。。
我這目前無解了,只能用最最麻煩的笨方法了,也就是:A引用了本地B,B又引用了本地C,C又引用了本地D,要想A不出錯,那麼A引入了B以後,必須還要在A的mod.go的replace中必須重複聲明C D不然就出錯,也就是在A中引入了B,那麼GO會無視B的mod.go中的replace內容必須要在A中重新再聲明一次,如果都是本地的引用A->B->C->D->E這種笨方法可想而知A中得加了多少重複的東西,但也沒辦法,不然就報錯,真是都瘋了!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·
go mod怎麼導入本地其他自定義模塊可參考我的另一篇博客:https://blog.csdn.net/qq_38151401/article/details/105780251
這就是我的每個模塊中都有go.mod的原因,感覺挺麻煩的,有什麼好的方法歡迎指教~~~~