• 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模式
  • 责任链模式

前后端分离项目演示

登录、登出、登录超时自动退出

详细设计
  1. 输出错误密码,提示错误信息 // 视频 0″ 开始
  2. 正常登录,能够访问/welcome页面 // 视频 17″ 开始
  3. 正常登出后,记住登出前页面;重新登录时重返登出前访问页面 // 视频 28″ 开始
  4. 未登录状态访问/resources页面,重定向到登录页;完成登录后,记住/resources,返回/resources页面 // 视频 45″ 开始
  5. 登录后,登录超期(删除redis-session实现),访问页面时重定向至登录页 // 视频 1′12″ 开始
  6. 登录状态每次请求将重新刷新登录过期时间(middleware实现)// 视频 1′45″ 开始
演示

go 登录、登出、登录超时自动退出

文件上传系统

go 文件上传系统

源码

gitee: https://gitee.com/go_web_1

说明:web框架完成,可通过test文件测试 // 已调整目录结构,移除test文件 测试文件存在对应commit:7e7f7d837b5c94deaab20ea99710cb2b27abaf9a

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐