03 . Go框架之Gin框架从入门到熟悉(Cookie和Session,数据库操作)
Cookie
Cookie是什么
HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出
Cookie就是解决HTTP协议无状态的方案之一,中文是小甜饼的意思
Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求
Cookie由服务器创建,并发送给浏览器,最终由浏览器保存
Cookie的用途
保持用户登录状态
Cookie的缺点
/*
不安全,明文
增加带宽消耗
可以被禁用
Cookie有上限
*/
Cookie的使用
测试服务器发送cookie给客户端,客户端请求时携带cookie
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
// 服务端要给客户端
r.GET("cookie", func(c *gin.Context) {
// 获取客户端是否携带cookie
cookie,err := c.Cookie("key_cookie")
if err != nil {
cookie = "NotSet"
// 给客户端设置cookie
// maxAge int, 单位 s
// path cookie 所在目录
// domain string 域名
// secure 是否只能通过https访问
// httponly bool 是否允许别人通过js获取自己的cookie
c.SetCookie("key_cookie","value_cookie",60,"/","localhost",false,true)
}
fmt.Printf("cookie的值是: %s\n",cookie)
})
r.Run()
}
模拟实现权限验证中间件
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func AuthMiddleWare() gin.HandlerFunc {
return func(c *gin.Context) {
if cookie, err := c.Cookie("abc"); err == nil {
if cookie == "123" {
c.Next()
return
}
}
// 返回错误
c.JSON(http.StatusUnauthorized,gin.H{"error":"err"})
c.Abort()
return
}
}
func main() {
// 1.创建路由
// 默认使用了2个中间件Logger(), Recovery()
r := gin.Default()
r.GET("/login", func(c *gin.Context) {
c.SetCookie("abc","123",60,"/","localhost",false,true)
c.String(200,"Login success!")
})
r.GET("/home",AuthMiddleWare(), func(c *gin.Context) {
c.JSON(200,gin.H{"data":"home"})
})
r.Run()
}
Session
Session是什么
Session可以弥补Cookie的不足, Session必须依赖于Cookie才能使用, 生成一个SessionID放在Cookie里传到客户端就可以.
Session中间件开发
设计一个通用的Session服务, 支持内存存储和redis存储
Session模块设计
/*
本质上k-v系统,通过key进行增删改查.
Session可以存储在内存或者redis(2个版本)
*/
Session接口设计
/*
Set()
Get()
Del()
Save() session存储, redis的实现延迟加载
*/
SessionMgr接口设计
/*
Init() 初始化,加载redis地址
CreateSession() 创建一个新的session
GetSession() 通过SessionID获取对应的Session对象
*/
MemorySession设计
/*
定义MemorySession对象 (字段: SessionID, 存kv的map,读写锁)
构造函数,为了获取对象
Set()
Get()
Del()
Save()
*/
MemorySessionMgr设计
/*
定义MemorySessionMgr对象(字段: 存放所有session的map, 读写锁)
构造函数
Init()
CreateSession()
GetSession()
*/
RedisSession设计
/*
定义RedisSession对象(字段: sessionID,存kv的map, 读写锁, redis连接池, 记录内存中map是否被修改的标记)
构造函数
Set(): 将session存到内存中的map
Get(): 取数据,实现延迟加载
Del()
Save(): 将session存到redis
*/
RedisSessionMgr设计
/*
定义RedisSessionMgr对象(字段: redis地址,redis密码, 连接池,读写锁, 大map)
构造函数
Init()
CreateeSession()
GetSession()
*/
session.go
数据库操作
sql
CREATE TABLE `book` (
`id` int(50) NOT NULL AUTO_INCREMENT,
`title` varchar(50) DEFAULT NULL,
`price` int(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
结构
tree
.
├── book
├── db
│ └── db.go
├── go.mod
├── go.sum
├── main.go
├── model
│ └── book.go
└── templates
├── book_list.html
└── new_book.html
db
db.go
// 查询单条数据示例
package db
import (
"database_test1/model"
"fmt"
_ "github.com/go-sql-driver/mysql" // init()
"github.com/jmoiron/sqlx"
)
// Go连接MySQL示例
var db *sqlx.DB // 是一个连接池对象
func InitDB() (err error) {
// 数据库信息
// 用户名:密码@tcp(ip:端口)/数据库的名字
dsn := "test:ZHOUjian.22@tcp(121.36.43.223:3306)/book?charset=utf8"
// 连接数据库
db, err = sqlx.Connect("mysql", dsn)
if err != nil {
return
}
db.SetMaxOpenConns(10) // 设置数据库连接池的最大连接数
db.SetMaxIdleConns(5) // 设置最大空闲连接数
return
}
func QueryAllBook() (bookList []*model.Book,err error) {
sqlStr := "select id,title,price from book"
err = db.Select(&bookList,sqlStr)
if err != nil {
fmt.Println("查询失败")
return
}
return
}
func InsertBook(title string,price int64) (err error) {
sqlStr := "insert into book(title,price) values(?,?)"
_, err = db.Exec(sqlStr,title,price)
if err != nil {
fmt.Println("插入失败")
return
}
return
}
func DeleteBook(id int64) (err error) {
sqlStr := "delete from book where id =?"
_,err = db.Exec(sqlStr,id)
if err != nil {
fmt.Println("删除失败")
return
}
return
}
model
book.go
package model
type Book struct {
ID string `db:"id"`
Title string `db:"title"`
Price int64 `db:"price"`
}
template
book_list.html
{{ define "book_list.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>书籍列表</title>
</head>
<body>
<div><a href="/book/new">添加新书</a></div>
<table border="1">
<thead>
<tr>
<th>ID</th>
<th>title</th>
<th>price</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{{ range .data}}
<tr>
<td>{{ .ID }}</td>
<td>{{ .Title }}</td>
<td>{{ .Price }}</td>
<td><a href="/book/delete?id={{ .ID }}">删除</a></td>
</tr>
{{ end }}
</tbody>
</table>
</body>
</html>
{{ end }}
new_book.html
{{ define "new_book.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加图书信息</title>
</head>
<body>
<form action="/book/new" method="POST">
<div>
<label>书名:
<input type="text" name="title">
</label>
</div>
<div>
<label>价格:
<input type="number" name="price">
</label>
</div>
<div>
<input type="submit" value="点我">
</div>
</form>
</body>
</html>
{{ end }}
Main.go
package main
import (
"database_test1/db"
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
// 初始化数据库
err := db.InitDB()
if err != nil {
panic(err)
}
r := gin.Default()
r.LoadHTMLGlob("./templates/*")
// 查询所有图书
r.GET("/book/list",bookListHandler)
r.Run()
}
func bookListHandler(c *gin.Context) {
bookList ,err := db.QueryAllBook()
if err != nil {
c.JSON(http.StatusOK,gin.H{
"code":1,
"msg":err,
})
return
}
// 返回数据
c.HTML(http.StatusOK,"book_list.html",gin.H{
"code":200,
"data":bookList,
})
}
03 . Go框架之Gin框架从入门到熟悉(Cookie和Session,数据库操作)的更多相关文章
- 01 . Go框架之Gin框架从入门到熟悉(路由和上传文件)
Gin框架简介 Gin是使用Go/Golang语言实现的HTTP Web框架, 接口简洁, 性能极高,截止1.4.0版本,包含测试代码,仅14K, 其中测试代码9K, 也就是说测试源码仅5k左右, 具 ...
- Go语言基础之20--web编程框架之Gin框架
一.Gin框架介绍 1.1 简介 A. 基于httprouter开发的web框架. http://github.com/julienschmidt/httprouter B. 提供Martini风格的 ...
- 02 . Go框架之Gin框架从入门到熟悉(数据解析和绑定,渲染,重定向,同步异步,中间件)
数据解析和绑定 json数据解析和绑定 package main import ( "github.com/gin-gonic/gin" "net/http" ...
- Web框架之Gin
Gin是一个用Go语言编写的web框架.它是一个类似于martini但拥有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍. 如果你是性能和高效的追求者, 你会爱上Gin. ...
- Gin框架介绍及使用
Gin是一个用Go语言编写的web框架.它是一个类似于martini但拥有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍. 如果你是性能和高效的追求者, 你会爱上Gin. ...
- gin框架中间件
1. Gin框架中间件Gin框架中间件A. Gin框架允许在请求处理过程中,加入用户自己的钩子函数.这个钩子函数就叫中间件B. 因此,可以使用中间件处理一些公共业务逻辑,比如耗时统计,日志打印,登陆校 ...
- Web框架之Gin介绍及使用
Gin是一个用Go语言编写的web框架.它是一个类似于martini但拥有更好性能的API框架, 由于使用了httprouter,速度提高了近40倍. 如果你是性能和高效的追求者, 你会爱上Gin. ...
- Gin框架介绍与使用
Gin // 初识 Gin框架 //下载(可能会下载不全.缺什么get什么即可) //go get -u -v github.com/gin-gonic/gin package main import ...
- 前端程序员学习 Golang gin 框架实战笔记之一开始玩 gin
原文链接 我是一名五六年经验的前端程序员,现在准备学习一下 Golang 的后端框架 gin. 以下是我的学习实战经验,记录下来,供大家参考. https://github.com/gin-gonic ...
随机推荐
- Java Comparable 和 Comparator 接口详解
本文基于 JDK8 分析 Comparable Comparable 接口位于 java.lang 包下,Comparable 接口下有一个 compareTo 方法,称为自然比较方法.一个类只要实现 ...
- 使用deeplabv3+训练自己数据集(迁移学习)
概述 在前边一篇文章,我们讲了如何复现论文代码,使用pascal voc 2012数据集进行训练和验证,具体内容可以参考<deeplab v3+在pascal_voc 2012数据集上进行训练& ...
- Python-判断字符串是否以某个字符串开头或结尾?
案例: 某文件系统目录下有一系列文件: 1.c 2.py 3.java 4.sh 5.cpp ...... 编写一个程序,给其中所有的.sh文件和.py文件加上可执行权限 如何解决这个问题? 1. 先 ...
- 玩转Libmodbus(二) 写代码体验
libmodbus在线文档 https://www.jianshu.com/p/d93c17485c0a 原创篇 参考上一篇转载的博客,我的ubuntu上的最终生成的动态库的路径,下图所示 我的lin ...
- # 095 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 03 封装总结 01 封装知识点总结
095 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...
- 远程触发Jenkins的Pipeline任务
场景 虽然能配置提交代码时触发Jenkins任务,但有时并不需要每次提交代码都触发,而是仅在有需要时才执行. 除了在Jenkins页面上手动执行任务,还可以向Jenkins网站发起HTTP请求,触发指 ...
- node_modules 文件夹需要管理员权限才能删除问题
方法一:以管理员权限运行IDE ,然后在IDE里面删除该文件夹 方法二:以管理员身份运行cmd,使用命令行来删除该文件夹 找到要删除文件夹的位置,使用命令行 rmdir /s/q 文件夹位置 /s 是 ...
- 利用HDFS实现ElasticSearch7.2容灾方案
利用HDFS实现ElasticSearch7.2容灾方案 目录 利用HDFS实现ElasticSearch7.2容灾方案 前言 快照版本兼容 备份集群 HDFS文件系统 软件下载 JDK环境 配置系统 ...
- python xlrd读取Excel文件
1 import xlrd 2 3 #打开excel文件 4 book = xlrd.open_workbook('salary.xls') 5 6 #打印每个工作表的名称 7 for sheet i ...
- 在Linux终端中快速生成、解码二维码
我们要实现两个功能: 解码Linux屏幕上的二维码,将结果输出在终端 在终端中将字符串转为二维码,直接显示二维码在终端中以供扫描 实现方法 生成二维码 qrencode是一个常见的生成二维码的CLI程 ...