写此系统的初衷实为加强对所学部分东西的理解与掌握,简洁的同时达到目的,本文代码/项目的形成正是一个学习和加强实践的过程。
基于macaron+viper+gorm框架(关于macaron、gorm可移步:https://blog.csdn.net/HYZX_9987/article/details/100022849
https://blog.csdn.net/HYZX_9987/article/details/99681632)
目录
项目结构
配置文件部分
1、配置文件内容及其存放路径
2、配置文件的解析与内容的注入
结构体
注入配置
提示:启动项目时也可以刻意不写配置文件,viper读取配置时会加载路径,如果没有文件会提示在xx路径下找不到config.yaml
这时你再把文件放到xx路径也行。
路由控制器部分
1、初始化马卡龙组件
-
m := macaron.Classic()
-
m.Use(macaron.Renderer())
-
m.Use(macaron.Recovery())
-
//test
-
m.Get(
"/",
func(ctx *macaron.Context) macaron.ReturnStruct {
-
return macaron.ReturnStruct{Msg:
"Hello world!", Data:
"Your macaron."}
-
})
2、分组路由使用
本系统不需要太复杂的逻辑,暂定实体为客户、订单、订单项,因此分三组路由,前缀以/api开始
3、各模块路由控制器(以Customer部分为例)
路由定义:
-
/*
-
马卡龙数据绑定:go get github.com/go-macaron/binding,移入pkg包
-
*/
-
func CusRoute(m *macaron.Macaron) {
-
//http://localhost:8081/api/cus
-
m.Get(
"/cus", ListCustomer)
-
//http://localhost:8081/api/cus/1
-
m.Get(
"/cus/:ID", GetCustomer)
-
m.Post(
"/cus", binding.Bind(model.Customer{}), CreateCustomer)
-
m.Delete(
"/cus/:ID", DeleteCustomer)
-
m.Put(
"/cus", binding.Bind(model.Customer{}), UpdateCustomer)
-
}
对应处理器:
-
func CusRoute(m *macaron.Macaron) {
-
-
//http://localhost:8081/api/cus
-
m.Get(
"/cus", ListCustomer)
-
//http://localhost:8081/api/cus/1
-
m.Get(
"/cus/:ID", GetCustomer)
-
m.Post(
"/cus", binding.Bind(model.Customer{}), CreateCustomer)
-
m.Delete(
"/cus/:ID", DeleteCustomer)
-
m.Put(
"/cus", binding.Bind(model.Customer{}), UpdateCustomer)
-
}
-
-
func ListCustomer(ctx *macaron.Context) macaron.ReturnStruct {
-
var err error
-
cusList, err := service.ListCustomerInternal()
-
if err !=
nil {
-
errMsg :=
"list customer err:" + err.Error()
-
ctx.Resp.Header().Set(
"error-info", errMsg)
-
log.Fatal(errMsg)
-
return macaron.ReturnStruct{Msg: errMsg}
-
}
-
return macaron.ReturnStruct{Data: cusList, Code: http.StatusOK}
-
}
-
-
func GetCustomer(ctx *macaron.Context) macaron.ReturnStruct {
-
cus, err := service.GetCustomerByIDInternal(ctx.Params(
"ID"))
-
if err !=
nil {
-
errMsg :=
"get customer err:" + err.Error()
-
ctx.Resp.Header().Set(
"error-info", errMsg)
-
log.Fatal(errMsg)
-
return macaron.ReturnStruct{Msg: errMsg}
-
}
-
return macaron.ReturnStruct{Data: cus, Code: http.StatusOK}
-
}
-
-
func CreateCustomer(customer model.Customer, ctx *macaron.Context) macaron.ReturnStruct {
-
err := service.CreateCustomerInternal(customer)
-
if err !=
nil {
-
errMsg :=
"create customer err:" + err.Error()
-
ctx.Resp.Header().Set(
"error-info", errMsg)
-
log.Fatal(errMsg)
-
return macaron.ReturnStruct{Msg: errMsg}
-
}
-
return macaron.ReturnStruct{Code: http.StatusOK}
-
}
-
-
func DeleteCustomer(ctx *macaron.Context) macaron.ReturnStruct {
-
err := service.DeleteCustomerByIDInternal(ctx.Params(
"ID"))
-
if err !=
nil {
-
errMsg :=
"del customer err:" + err.Error()
-
ctx.Resp.Header().Set(
"error-info", errMsg)
-
log.Fatal(errMsg)
-
return macaron.ReturnStruct{Msg: errMsg}
-
}
-
return macaron.ReturnStruct{Code: http.StatusOK}
-
}
-
-
func UpdateCustomer(customer model.Customer, ctx *macaron.Context) macaron.ReturnStruct {
-
err := service.UpdateCustomerInternal(customer)
-
if err !=
nil {
-
errMsg :=
"update customer err:" + err.Error()
-
ctx.Resp.Header().Set(
"error-info", errMsg)
-
log.Fatal(errMsg)
-
return macaron.ReturnStruct{Msg: errMsg}
-
}
-
return macaron.ReturnStruct{Code: http.StatusOK}
-
}
Service层(非必须,web层可直接与持久层交互):
-
func ListCustomerInternal() (cusList []model.Customer, err error) {
-
cusList, err = dao.ListCustomerByDB()
-
return cusList, err
-
}
-
-
func GetCustomerByIDInternal(ID string) (cus model.Customer, err error) {
-
cus, err = dao.GetCustomerByIDByDB(ID)
-
return cus, err
-
}
-
-
func DeleteCustomerByIDInternal(ID string) (err error) {
-
err = dao.DeleteCustomerByIDByDB(ID)
-
return err
-
}
-
-
func CreateCustomerInternal(cus model.Customer) (err error) {
-
err = dao.CreateCustomerByDB(cus)
-
return err
-
}
-
-
func UpdateCustomerInternal(cus model.Customer) (err error) {
-
err = dao.UpdateCustomerByDB(cus)
-
return err
-
}
对象关系映射部分
1、gorm开启连接、初始化配置
2、表初始化
3、各模块db操作(持久层)
-
func ListCustomerByDB() (list []model.Customer, err error) {
-
db := config.Connection()
-
err = db.Find(&list).Error
-
return list, err
-
}
-
-
func GetCustomerByIDByDB(ID string) (cus model.Customer, err error) {
-
db := config.Connection()
-
err = db.Where(
"id = ?", ID).Find(&cus).Error
-
return cus, err
-
}
-
-
func DeleteCustomerByIDByDB(ID string) (err error) {
-
db := config.Connection()
-
err = db.Where(
"id = ?", ID).Delete(&model.Customer{}).Error
-
return err
-
}
-
-
func CreateCustomerByDB(cus model.Customer) (err error) {
-
db := config.Connection()
-
err = db.Save(&cus).Error
-
return err
-
}
-
-
func UpdateCustomerByDB(cus model.Customer) (err error) {
-
db := config.Connection()
-
err = db.Update(&cus).Error
-
return err
-
}
一切就绪后,启动项目:
调接口看效果:
控制台日志:
访问控制
实际项目中往往都加了登录控制以及token校验之类的东西,我们在这模拟一下:
-
m.Group(
"/api",
func() {
-
m.Group(
"",
func() {
-
controller.CusRoute(m)
-
})
-
-
m.Group(
"",
func() {
-
controller.OrderRoute(m)
-
})
-
-
m.Group(
"",
func() {
-
controller.ItemRoute(m)
-
})
-
},CheckToken)
让所有进来的请求都得执行CheckToken函数,函数如下:
-
-
func CheckToken(ctx *macaron.Context) {
-
if auth := ctx.Req.Header.Get(
"auth"); auth ==
"123" {
-
log.Println(
"token success.")
-
return
-
}
-
ctx.JSON(http.StatusUnauthorized, macaron.ReturnStruct{Code: http.StatusUnauthorized, Msg:
"invalid Token."})
-
}
此时如果继续按刚才的请求访问,那么会被校验住:
如果加了token的验证,那么将一路顺风: