第三章-(分组控制)

分组的意义

分组控制(Group Control)是 Web 框架应提供的基础功能之一。所谓分组,是指路由的分组。如果没有路由分组,我们需要针对每一个路由进行控制。但是真实的业务场景中,往往某一组路由需要相似的处理。例如:

  • /post开头的路由匿名可访问。
  • /admin开头的路由需要鉴权。
  • /api开头的路由是 RESTful 接口,可以对接第三方平台,需要三方平台鉴权。

大部分情况下的路由分组,是以相同的前缀来区分的。因此,我们今天实现的分组控制也是以前缀来区分,并且支持分组的嵌套。例如/post是一个分组,/post/a/post/b可以是该分组下的子分组。作用在/post分组上的中间件(middleware),也都会作用在子分组,子分组还可以应用自己特有的中间件。

中间件可以给框架提供无限的扩展能力,应用在分组上,可以使得分组控制的收益更为明显,而不是共享相同的路由前缀这么简单。例如/admin的分组,可以应用鉴权中间件;/分组应用日志中间件,/是默认的最顶层的分组,也就意味着给所有的路由,即整个框架增加了记录日志的能力。

一个分组group应当所具备的属性:1.前缀,即知道该路由节点的父节点是谁,2.中间件,中间件极大增强了扩展能力(下章节写)3.嵌套父节点 4.引擎对象

type RouterGroup struct {
prefix string
middleware []HandlerFunc
parent *RouterGroup
engine *Engine

}

接下来,将原本engine对象的方法教给routergroup

func (group *RouterGroup)Group(NowUrl string)*RouterGroup{
newGroup:=&RouterGroup{
prefix: group.prefix+NowUrl,
parent: group,
engine: group.engine,
}
group.engine.groups = append(group.engine.groups,newGroup)
return newGroup
}

//添加路由
//gin源码的影子

func (group *RouterGroup)addRoute(method string,NowUrl string,handler HandlerFunc){
pattern :=group.prefix+ NowUrl
log.Printf("Route %4s - %s", method, pattern)
group.engine.router.AddRoute(method, pattern, handler)
}

func (group *RouterGroup)Get(pattern string,handler HandlerFunc){
group.addRoute("GET",pattern,handler)
}

func (group *RouterGroup)Post(pattern string,handler HandlerFunc){
group.addRoute("POST",pattern,handler)
}


修改engine的创建方法和属性:
type Engine struct{
*RouterGroup
router *Router
groups []*RouterGroup
}
//核心创建方法
func New()*Engine{
engine := &Engine{router:NewRouter()}
engine.RouterGroup = &RouterGroup{engine:engine}
engine.groups = []*RouterGroup{engine.RouterGroup}
return engine
}
在这里要注意的是,routergroup对象与engine对象其实是相当于django中的双向绑定,这样一来并不需要修改router当中的内容,可以通过两个对象间的相互调用实现功能
测试:

func main(){
fmt.Println("框架启动")
r:= finto.New()
r.Get("/", func(c *finto.Context) {
c.Html(http.StatusOK, "<h1>Hello Finto</h1>")
})
group1 := r.Group("/group1")
group1.Get("/hello", func(context *finto.Context) {
context.Html(http.StatusOK,"<a>group1 hello</a>")
})
group2 := r.Group("/group2")
group2.Get("/hello", func(context *finto.Context) {
context.Html(http.StatusOK,"<a>group2 hello</a>")
})


r.Run(":9999")
}


在浏览器中可以看到测试结果

 

 

心得:

1.engine和routergroup互相嵌套,相当于java/python中的继承,这样一来他们互相都拥有了对方的属性和方法

2.将routergroup实现engine中的get,post方法,这样可以让engine的抽象程度更高。

 



posted @ 2021-11-16 17:28  fanyiaaa  阅读(160)  评论(0编辑  收藏  举报