go web框架实现与使用
Server定义、路由树、context上下文、AOP方案(Middleware)、静态资源服务与文件处理、页面渲染template、Session、优雅退出。测试代码:web/test/graceful_shutdown_test.go 注意:该代码必须放在main函数下运行,test文件下无法监听到退出信号。支持路由:静态路由、参数路由(/a/:id)、正则匹配、动态路由(通配符 /a/*),
文章目录
- web框架是做什么的
- 为什么封装web框架,不直接使用net/http?
- web框架核心
web框架是做什么的
处理http请求,为用户提供便捷api,提供插件机制扩展框架能力,提供默认功能如上传下载
为什么封装web框架,不直接使用net/http?(web框架核心)
高级路由功能,封装上下文以提供便捷api,封装server提供生命周期,提供插件机制扩展框架能力
关键词:Server定义、路由树、context上下文、AOP方案(Middleware)、静态资源服务与文件处理、页面渲染template、Session、优雅退出
核心能力
路由注册
支持用户选择路由handler,已实现treeRoute
支持路由:静态路由、参数路由(/a/:id)、正则匹配、动态路由(通配符 /a/*),路由命中优先级按照前面的顺序
接口设计
node
type Node struct {
path string // 用户查找路径节点
handleFunc handler.HandleFunc
children []*Node
nodeType int
pattern string // route注册匹配规则
Match func(path string, c *context.Context) bool
}
演示
测试代码:web/test/server_route_test.go
context上下文
type Context struct {
W http.ResponseWriter
R *http.Request
RespStatusCode int
RespData []byte
PathParams map[string]string // 参数路径中的参数
MatchRoute string
templateEngine template.TemplateEngine
UserValues map[string]any // session缓存;使用ctx.UserValues缓存使用过的session, 减少访问redis的次数
}
-
将RespStatusCode、RespData维护起来的原因:
直接ctx.W.Write()后的内容是无法再次修改的;使用RespData维护,可以在server-middleware中修改返回值 -
使用sync.Pool复用context
Session
type Session interface { // Session中可以存放热点数据,缓解请求redis的压力
Get(c *context.Context, key string) (interface{}, error)
Set(c *context.Context, key string, val interface{}) error
ID() string
}
// Store 管理session
type Store interface {
Generate(c *context.Context, id string) (Session, error)
Get(c *context.Context, id string) (Session, error)
Remove(c *context.Context, id string) error
Refresh(c *context.Context, id string) error
}
// Propagator 将session关联http.cookie中
type Propagator interface {
Inject(id string, w http.ResponseWriter) error
Extract(r *http.Request) (string, error)
Delete(w http.ResponseWriter) error
}
Manager 胶水作用,方便用户操作
type Manager struct {
session.Store
session.Propagator
}
AOP方案
使用责任链模式
type Middleware func(next Filter) Filter
type Filter func(c *context.Context)
优雅退出
- 拒绝新请求
- 等待已接收请求处理完成
- 关闭所有服务
- 释放资源
- 超时强制退出
接口设计
func WaitForShutdown(hooks ...Hook) {}
使用channel监听关闭信号,监听到关闭信号后,依次执行hook
type Hook func(c context.Context) error
func BuildServerHook(servers ...server.Server) Hook
演示
测试代码:web/test/graceful_shutdown_test.go 注意:该代码必须放在main函数下运行,test文件下无法监听到退出信号
扩展支持
静态资源访问
使用lru缓存,支持扩展文件类型 ,已防御文件访问路径漏洞
接口设计
type StaticResourceHandler struct {
dir string
pathPrefix string
extMap map[string]string // 支持用户扩展支持的extMap
c *lru.Cache
maxFileSize int
}
演示
测试代码:web/test/static_resource_test.go
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
上传下载服务
演示
页面渲染template
使用场景:404时,返回404页面;
使用方式:在server中注入templateEngine; 在route handler中通过ctx.templateEngine中获取自定义使用
type TemplateEngine interface {
Render(ctx context.Context, tplName string, data interface{}) ([]byte, error)
}
测试代码:web/test/template_test.go
observer 数据监控
以插件方式(AOP)提供内置日志记录、zipkin tracer、prometheus vector统计
接口设计
使用opentelemetry,支持tracer+zipkin、prometheus
type ObserverMiddlewareBuilder struct {
logFunc func(accessLog string)
tracer trace.Tracer
vector *prometheus.SummaryVec
}
演示
zipkin tracer(暂未提供多系统微服务调用)
premetheus vector
技术设计
原则
框架提供核心能力,扩展能力以插件方式注册
设计模式
- Option模式
- build模式
- 责任链模式
前后端分离项目演示
登录、登出、登录超时自动退出
详细设计
- 输出错误密码,提示错误信息 // 视频 0″ 开始
- 正常登录,能够访问/welcome页面 // 视频 17″ 开始
- 正常登出后,记住登出前页面;重新登录时重返登出前访问页面 // 视频 28″ 开始
- 未登录状态访问/resources页面,重定向到登录页;完成登录后,记住/resources,返回/resources页面 // 视频 45″ 开始
- 登录后,登录超期(删除redis-session实现),访问页面时重定向至登录页 // 视频 1′12″ 开始
- 登录状态每次请求将重新刷新登录过期时间(middleware实现)// 视频 1′45″ 开始
演示
go 登录、登出、登录超时自动退出
文件上传系统
源码
gitee: https://gitee.com/go_web_1
说明:web框架完成,可通过test文件测试 // 已调整目录结构,移除test文件 测试文件存在对应commit:7e7f7d837b5c94deaab20ea99710cb2b27abaf9a
更多推荐
所有评论(0)