Gin+Gorm+sessions 搭建 golang web项目
Gin是用Go(Golang)编写的HTTP web框架。它具有类似Martini的API,但性能比Martini快40倍
Gorm,Golang 出色的ORM库
sessions,具有多后端支持的用于会话管理的Gin中间件
使用 Gin + Gorm + sessions 搭建 golang web 项目,步骤如下
目录
1、创建项目
1.1、新建项目
1.2、安装依赖
2、搭建项目
2.1、项目分层
2.2、完善各层代码
2.3、数据库建表
3、添加 html 和静态文件
4、添加 session
5、添加过滤器
6、登录验证实现
7、项目扩展
8、事物测试
9、项目代码
1、创建项目
1.1、新建项目
项目名为 go-web
在指定文件夹下,新建项目文件夹 go-web
进入项目文件夹,打开cmd窗口,在项目(go-web)文件夹路径下,执行初始化命令 go mod init go-web
go mod init go-web
1.2、安装依赖
进入项目(go-web)文件夹,打开 cmd 窗口,在项目(go-web)文件夹路径下安装GIn、Gorm、sessions、mysql 依赖安装包
go get -u github.com/gin-gonic/gin
go get -u github.com/gin-contrib/sessions
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
2、搭建项目
2.1、项目分层
在项目根目录下,新建 main.go
依次新建controller、service、entity、dao文件夹
2.2、完善各层代码
这里可以使用编辑器 goland 或 vs code 打开项目,笔者使用 goland
在 entity 目录下 User.go
package entitytype User struct {//属性开头字母大写Id intName stringAge int
}
在 dao 目录下 UserDao.go
package daoimport ("go-web/entity""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger""log"
)var db *gorm.DBfunc init() {//数据库账号root 密码123456 地址192.168.5.38dsn := "root:123456@tcp(192.168.5.38:3306)/go-web?charset=utf8&parseTime=True&loc=Local"db1, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: logger.Default.LogMode(logger.Info)})if err != nil {log.Fatal("", err)} else {db = db1}}
func AddUser(user entity.User) {db.AutoMigrate(&entity.User{})db.Table("user").Save(&user)
}
在service 目录下新建 UserService.go
package serviceimport ("go-web/dao""go-web/entity"
)func UserAdd(name string, age int) {user := entity.User{Name: name,Age: age,}dao.AddUser(user)
}
在controller 目录下新建 UserController.go
package controllerimport ("github.com/gin-gonic/gin""go-web/service""strconv"
)func UserAdd(c *gin.Context) {name := c.Query("name")age := c.Query("age")agei, _ := strconv.Atoi(age)service.UserAdd(name, agei)c.JSON(200, "添加成功")
}
main.go 内容
package mainimport ("github.com/gin-gonic/gin""go-web/controller"
)func main() {e := gin.Default()e.GET("/user/add", controller.UserAdd)//修改端口号为80e.Run("0.0.0.0:80")
}
2.3、数据库建表
新建数据库 go-web,然后执行下面建表 sql,笔者数据库是 mysql5.7
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`age` int(11) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
建表完成后,运行 main.go,启动项目,浏览器访问
http://localhost/user/add?name=%E5%BC%A0%E6%97%A0%E5%BF%8C&age=27
效果如下
3、添加 html 和静态文件
在项目根目录下新建 templates 和 static 目录,用来存放 html 页面和静态文件
在 main.go 中添加目录配置
package mainimport ("github.com/gin-gonic/gin""go-web/controller"
)func main() {e := gin.Default()//html页面位置e.LoadHTMLGlob("templates/*")//静态文件位置e.Static("/static", "./static")e.GET("/user/add", controller.UserAdd)//修改端口号为80e.Run("0.0.0.0:80")
}
在 templates 目录下新建 index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link href="/static/index.css" rel="stylesheet">
</head>
<body><p>时逢三五便团圆,</p><p>满把晴光护玉栏。</p><p>天上一轮才捧出,</p><p>人间万姓仰头看。</p>
</body>
</html>
在 static 目录下新建 index.css
p {color: red;text-align: center;font-size: 30px;
}
在controller 目录下新建 IndexController
package controllerimport "github.com/gin-gonic/gin"func Index(c *gin.Context) {c.HTML(200, "index.html", nil)
}
在 main.go 中添加路由到 index.html 页面
package mainimport ("github.com/gin-gonic/gin""go-web/controller"
)func main() {e := gin.Default()//html页面位置e.LoadHTMLGlob("templates/*")//静态文件位置e.Static("/static", "./static")e.GET("/index", controller.Index)e.GET("/user/add", controller.UserAdd)//修改端口号为80e.Run("0.0.0.0:80")
}
运行效果
浏览器请求:http://localhost/index
4、添加 session
先在controller目录下新建 TestController.go
package controllerimport ("github.com/gin-contrib/sessions""github.com/gin-gonic/gin"
)// SessionAdd 添加name到session
func SessionAdd(c *gin.Context) {session := sessions.Default(c)if session.Get("name") == nil {session.Set("name", "ShakeSpeare")//每次操作完session后必须调用Save方法,否则不生效session.Save()}c.JSON(200, "添加完成")
}// SessionGet 从session中获取name
func SessionGet(c *gin.Context) {session := sessions.Default(c)name := session.Get("name")c.JSON(200, name)
}
然后在 main.go 中添加 session 中间件和 TestController 中的方法路由
package mainimport ("github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/cookie""github.com/gin-gonic/gin""go-web/controller"
)func main() {e := gin.Default()//设置sessionstore := cookie.NewStore([]byte("secret"))//session注入中间件e.Use(sessions.Sessions("mysession", store))//html页面位置e.LoadHTMLGlob("templates/*")//静态文件位置e.Static("/static", "./static")e.GET("/index", controller.Index)e.GET("/user/add", controller.UserAdd)//测试session相关e.GET("/session/add", controller.SessionAdd)e.GET("/session/get", controller.SessionGet)//修改端口号为80e.Run("0.0.0.0:80")
}
依次请求 TestController 中获取和添加的方法测试
先请求 http://localhost/session/get 获取
然后请求 http://localhost/session/add 添加
再获取
看效果,session 中间件添加成功
现在的 session 是保存在 cookie 中(store := cookie.NewStore([]byte("secret")))
如果想将 session 保存在内存中,需要添加依赖 github.com/quasoft/memstore,并修改 main.go中的 session 存储
go get github.com/quasoft/memstore
store := memstore.NewStore([]byte("secret"))
此外session还有其他保存方案,具体实现可以看官网文档:sessions package - github.com/gin-contrib/sessions - Go Packages
5、添加过滤器
过滤器,可以使用 Gin 中添加自定义中间件的方式实现
在根目录下新建 filter 文件夹
在 filter 目录下新建 Filter.go
package filterimport ("fmt""github.com/gin-gonic/gin"
)func DoFilter(c *gin.Context) {fmt.Println("过滤")fmt.Println(c.Request.URL)c.Next()
}
先在controller目录下新建 BookController.go
package controllerimport "github.com/gin-gonic/gin"func GetBook(c *gin.Context) {c.JSON(200, "红楼梦")
}
在 main.go 中添加需要过滤的路由
package mainimport ("github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/cookie""github.com/gin-gonic/gin""go-web/controller""go-web/filter"
)func main() {e := gin.Default()//设置sessionstore := cookie.NewStore([]byte("secret"))//session注入中间件e.Use(sessions.Sessions("mysession", store))//html页面位置e.LoadHTMLGlob("templates/*")//静态文件位置e.Static("/static", "./static")e.GET("/index", controller.Index)e.GET("/user/add", controller.UserAdd)//测试session相关e.GET("/session/add", controller.SessionAdd)e.GET("/session/get", controller.SessionGet)//添加filter过滤路由bookApi := e.Group("/book")bookApi.Use(filter.DoFilter)bookApi.GET("/get", controller.GetBook)//修改端口号为80e.Run("0.0.0.0:80")
}
重启项目,浏览器请求 http://localhost/book/get 测试 filter
过滤器配置完成
6、登录验证实现
在 controller 目录下新建 LoginController.go
里面有登录,登出的方法
package controllerimport ("fmt""github.com/gin-contrib/sessions""github.com/gin-gonic/gin"
)func Login(c *gin.Context) {c.HTML(200, "login.html", nil)
}func DoLogin(c *gin.Context) {username := c.PostForm("username")password := c.PostForm("password")fmt.Println(username)fmt.Println(password)session := sessions.Default(c)session.Set("user", "userinfo")session.Save()c.JSON(200, "登录成功")
}func DoLogout(c *gin.Context) {session := sessions.Default(c)if session.Get("user") != nil {session.Delete("user")session.Save()}c.JSON(200, "登出成功")
}
在 controller 目录下新建 ShopController.go
里面的方法返回登录后才能显示的页面
package controllerimport "github.com/gin-gonic/gin"func ShopList(c *gin.Context) {shop := "商品"c.HTML(200, "shop.html", shop)
}
在 templates 目录下新建 login.html 和 shop.html
login.html 内容
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="dologin" method="post"><input type="text" name="username"><input type="text" name="password"><input type="submit" value="登录">
</form></body>
</html>
shop.html 内容
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
{{.}}
</body>
</html>
在 filter 目录下新建 LoginFilter.go
package filterimport ("fmt""github.com/gin-contrib/sessions""github.com/gin-gonic/gin"
)func DoLoginFilter(c *gin.Context) {fmt.Println("登录过滤")fmt.Println(c.Request.URL)session := sessions.Default(c)if session.Get("user") == nil {c.Redirect(302, "/login")}c.Next()
}
在 main.go 中添加新的路由和登录过滤器中间件
package mainimport ("github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/cookie""github.com/gin-gonic/gin""go-web/controller""go-web/filter"
)func main() {e := gin.Default()//设置sessionstore := cookie.NewStore([]byte("secret"))//session注入中间件e.Use(sessions.Sessions("mysession", store))//html页面位置e.LoadHTMLGlob("templates/*")//静态文件位置e.Static("/static", "./static")e.GET("/index", controller.Index)e.GET("/user/add", controller.UserAdd)//测试session相关e.GET("/session/add", controller.SessionAdd)e.GET("/session/get", controller.SessionGet)//添加filter过滤路由bookApi := e.Group("/book")bookApi.Use(filter.DoFilter)bookApi.GET("/get", controller.GetBook)e.GET("/login", controller.Login)e.POST("/dologin", controller.DoLogin)e.GET("/logout", controller.DoLogout)//会对下面路由进行过滤e.Use(filter.DoLoginFilter)e.GET("/shop", controller.ShopList)//修改端口号为80e.Run("0.0.0.0:80")
}
运行效果
至此,使用 Gin + Gorm + sessions 搭建 golang web 项目完成
7、项目扩展
现在项目的数据库配置信息是写死在dao层代码中的,这样配置起来很不方便,下面我们为项目添加配置文件,将数据库连接信息放在配置文件中
先为项目安装读取配置文件的包
go get github.com/spf13/viper
然后在项目根目录下新建 env 目录和 application.properties 配置文件
application.properties 内容如下
db.username=root
db.password=123456
db.url=192.168.5.38:3306
db.name=go-web
username 和 password 是数据库账号和密码
url 是数据库服务器地址和端口
name 数据库名称
这里读者可以自由发挥
在 env 目录下新建 env.go
package envtype Environment interface {GetProperty(key string) string
}
env.go 里面是获取配置文件的接口方法,这里借鉴 springboot 的思想
在 env 目录下新建 application_env.go
package envimport "github.com/spf13/viper"func init() {viper.SetConfigFile("./application.properties")viper.ReadInConfig()
}type ApplicationEnvironment struct {
}func (ae ApplicationEnvironment) GetProperty(key string) string {value := viper.Get(key)if value != nil {return value.(string)}return ""
}
application_env.go 实现了 Environment 的获取配置文件的方法 GetProperty,同时在 init 中读取配置文件
在 env 目录下新建 data_source.go
package envimport ("gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger""log"
)var DB *gorm.DBfunc init() {var environment Environmentenvironment = ApplicationEnvironment{}dsn := environment.GetProperty("db.username") + ":" +environment.GetProperty("db.password") + "@tcp(" +environment.GetProperty("db.url") + ")/" +environment.GetProperty("db.name") + "?charset=utf8&parseTime=True&loc=Local"db1, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: logger.Default.LogMode(logger.Info)})if err != nil {log.Fatal("", err)} else {DB = db1}
}
里面创建了 gorm.DB 对象,其他使用 gorm.DB 对象的地方直接使用 env.DB 即可
修改 dao 层下的 UserDao.go 代码
package daoimport ("go-web/entity""go-web/env"
)func AddUser(user entity.User) {env.DB.AutoMigrate(&entity.User{})env.DB.Table("user").Save(&user)
}
重新启动项目测试添加用户
浏览器请求:http://localhost/user/add?name=%E5%91%A8%E8%8A%B7%E8%8B%A5&age=22
效果如下图
添加成功,说明项目改造配置文件成功
8、事物测试
项目扩展,添加配置文件后,修改 gorm.DB 创建方式,测试事物
在 UserDao.go 中添加更新用户的方法
package daoimport ("go-web/entity""go-web/env""gorm.io/gorm"
)func AddUser(user entity.User) {env.DB.AutoMigrate(&entity.User{})env.DB.Table("user").Save(&user)
}func UpdateUser(DB *gorm.DB, user entity.User) error {return DB.Table("user").Model(&entity.User{}).Where("id = ?", user.Id).Update("name", user.Name).Update("age", user.Age).Error
}
在 UserService.go 中添加更新用户的方法,同时更新2个user的数据
package serviceimport ("fmt""go-web/dao""go-web/entity""go-web/env"
)func UserAdd(name string, age int) {user := entity.User{Name: name,Age: age,}dao.AddUser(user)
}func UpdateTwoUser(users []entity.User) error {user1 := users[0]user2 := users[1]//开启事物tx := env.DB.Begin()defer func() {if r := recover(); r != nil {fmt.Println(r)//回滚事物tx.Rollback()}}()if err := dao.UpdateUser(tx, user1); err != nil {//回滚事物tx.Rollback()return err}if err := dao.UpdateUser(tx, user2); err != nil {//回滚事物tx.Rollback()return err}//提交事物return tx.Commit().Error
}
在 UserController.go 中添加更新用户的方法
package controllerimport ("github.com/gin-gonic/gin""go-web/entity""go-web/service""strconv"
)func UserAdd(c *gin.Context) {name := c.Query("name")age := c.Query("age")agei, _ := strconv.Atoi(age)service.UserAdd(name, agei)c.JSON(200, "添加成功")
}func TwoUserAdd(c *gin.Context) {var user1 = entity.User{Id: 6,Name: "韦一笑",Age: 42,}var user2 = entity.User{Id: 8,Name: "杨逍12345678901234567890",Age: 12,}var users []entity.Userusers = append(users, user1)users = append(users, user2)er := service.UpdateTwoUser(users)if er != nil {c.JSON(200, "修改失败")} else {c.JSON(200, "修改成功")}
}
在 main.go 中添加更新方法路由
package mainimport ("github.com/gin-contrib/sessions""github.com/gin-contrib/sessions/cookie""github.com/gin-gonic/gin""go-web/controller""go-web/filter"
)func main() {e := gin.Default()//设置sessionstore := cookie.NewStore([]byte("secret"))//session注入中间件e.Use(sessions.Sessions("mysession", store))//html页面位置e.LoadHTMLGlob("templates/*")//静态文件位置e.Static("/static", "./static")e.GET("/index", controller.Index)e.GET("/user/add", controller.UserAdd)//测试session相关e.GET("/session/add", controller.SessionAdd)e.GET("/session/get", controller.SessionGet)//添加filter过滤路由bookApi := e.Group("/book")bookApi.Use(filter.DoFilter)bookApi.GET("/get", controller.GetBook)e.GET("/login", controller.Login)e.POST("/dologin", controller.DoLogin)e.GET("/logout", controller.DoLogout)e.GET("/two/user/add", controller.TwoUserAdd)//会对下面路由进行过滤e.Use(filter.DoLoginFilter)e.GET("/shop", controller.ShopList)//修改端口号为80e.Run("0.0.0.0:80")
}
将 user表 name字段长度修改为10
user表更新前数据
浏览器请求:http://localhost/two/user/add 测试
修改失败,事物回滚
修改 UserController.go 中修改方法 user2 name字段长度
package controllerimport ("github.com/gin-gonic/gin""go-web/entity""go-web/service""strconv"
)func UserAdd(c *gin.Context) {name := c.Query("name")age := c.Query("age")agei, _ := strconv.Atoi(age)service.UserAdd(name, agei)c.JSON(200, "添加成功")
}func TwoUserAdd(c *gin.Context) {var user1 = entity.User{Id: 6,Name: "韦一笑",Age: 42,}var user2 = entity.User{Id: 8,Name: "杨逍",Age: 12,}var users []entity.Userusers = append(users, user1)users = append(users, user2)er := service.UpdateTwoUser(users)if er != nil {c.JSON(200, "修改失败")} else {c.JSON(200, "修改成功")}
}
重启项目,重新请求测试
修改成功,事物提交
9、项目代码
码云:https://gitee.com/wsjzzcbq/go-web
至此完
Gin+Gorm+sessions 搭建 golang web项目相关推荐
- MyEclipse搭建java Web项目开发环境
MyEclipse搭建java Web项目开发环境 首先,在开始搭建MyEclipse的开发环境之前,还有三步工具的安装需要完成,只要在安装配置成功之后才可以进入下面的java Web项目开发环境的搭 ...
- java web开发myeclipse_【java项目实战】一步步教你使用MyEclipse搭建java Web项目开发环境(一)...
首先,在开始搭建MyEclipse的开发环境之前,还有三步工具的安装需要完成,只要在安装配置成功之后才可以进入下面的java Web项目开发环境的搭建. 1.安装工具 第一步,下载并安装JDK,到官网 ...
- 【Spring Boot】使用Spring Boot来搭建Java web项目以及开发过程
[Spring Boot]使用Spring Boot来搭建Java web项目以及开发过程 一.Spring Boot简介 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来 ...
- idea用maven搭建的web项目没有src目录只有pom解决方案(最暴力,最简单版本)
用maven搭建的web项目出现的bug解决方法 解决方法: 建议先去看第二种解决方法 一.创建maven 项目 上一步完成以后就可以一直下一步了,中间可以设置一下 maven项目存储位置和名称,本次 ...
- beego框架 golang web项目-个人博客系统
beego框架 golang web项目-个人博客系统 beego个人博客系统功能介绍 首页 分页展示博客 博客详情 评论 文章专栏 分类导航 资源分享 时光轴点点滴滴 关于本站 后台管理 登录 系统 ...
- 腾讯云轻量应用服务器 CentOS7.6 +Tomcat/apache 搭建个人web项目,并允许外网通过80或8080端口访问【超详细】
目录 1. 腾讯云购买学生轻量应用服务器 2. 为服务器用户设置密码允许远程登录 3. 本地下载Xshell和Xftp远程管理更方便 4. 域名认证和域名解析 5. 服务器安装JDK和Tomcat 6 ...
- idea搭建 maven web项目
idea搭建 maven web项目 1.Create new Project 2.选择Maven,勾选Create from archetype 在archetype中选择:org.apache.m ...
- java web 显示项目下的图片_[适合初中级Java程序员修炼手册从0搭建整个Web项目](一)...
前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206种一棵树最好的时间是十年前,其次是现在 six-finger-web 一个Web后端 ...
- apache为什么更适合处理动态请求_[适合初中级Java程序员修炼手册从0搭建整个Web项目](一)...
前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206种一棵树最好的时间是十年前,其次是现在 six-finger-web 一个Web后端 ...
最新文章
- Nginx源码分析:惊群处理与负载均衡
- html类型转换函数,如何在JavaScript中转换数据类型?
- PyTorch基础(12)-- torch.nn.BatchNorm2d()方法
- android 支付宝沙箱测试环境,Android支付宝沙箱环境使用教程
- 转载--va_list
- 对一个“世纪数学难题”的重新思考
- 1185 城市名排序
- .net runtime占用cpu_Go服务在容器内CPU使用率异常问题排查手记
- MAC编译OpenJDK8:iostream file not found(独家解决办法)
- 解密Twitch:一家游戏直播网站缘何价值10亿刀?
- Windows、Linux下安装Redis图文教程
- win7系统移动磁盘合并卷
- 网站使用QQ互联接入第三方登录,实现qq快捷登录网站的功能
- 圣诞邀请助力活动H5系统开发
- EXCEL如何隔三行设置背景色
- qt tableWidget 去掉网格线
- 计算机图形学 学习笔记(一):概述,直线扫描转换算法:DDA,中点画线算法,Bresenham算法
- 如何下载 TI 公司的官方例程以及为用户写好的标准头/源文件
- 关于facebook分享不能显示图片链接问题
- 到底什么是大数据?新手学习大数据的路径是什么?