目录
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的原因,感觉挺麻烦的,有什么好的方法欢迎指教~~~~