4.1 路由统一管理
路由的本质是将用户请求的requesturi与后端实现的业务函数进行绑定,比如用户访问http://localhot/user/register , requesturi 为/user/register ,代表用户需要调用注册业务,后端需要提供一个函数,或者展示注册页面,或者提供注册账号服务。另外,随着系统的日益复杂,路由配置参数越来越多,如果不统一管理将会导致前短接口混乱,不利于开发和维护。
那么,设计一个路由管理模块,需要考虑哪些因素呢?一般来说有如下几点:
1、 每一个控制器对应一个小模块,在控制器内部实现路由注册功能,这样有利于代码维护,并且思路清晰
2、 只需要对控制器进行注册,即可需要控制器中的路由注册,
3、 路由需要有容错功能,比如http://localhot//user/register 和http://localhot/user/register 应该具备相似的操作结果
当前系统设计路由如下
//具体控制器 type PageController struct { restgo.Controller } //实现Router方法 func (ctrl *PageController)Router(router *gin.Engine){ router.POST("page/create",ctrl.create) router.POST("page/update",ctrl.update) router.POST("page/query",ctrl.query) router.POST("page/delete",ctrl.delete) router.POST("page/findOne",ctrl.findOne) router.GET("/",ctrl.showIndex) } Main.go 主函数中调用如下代码 func registerRouter(router *gin.Engine){ new(controller.PageController).Router(router) } func main(){ router := gin.Default() //…… registerRouter(router *gin.Engine) }
如果我们需要添加一个控制器,在registerRouter中添加注册就可以了。
4.2 错误信息统一配置
错误信息统一处理是为了提高系统友好性,将不能识别的路由以及内部跳转的路由统一配置,别于前端统一定制。
1、路由路径错误
路由路径错误,比如大小写敏感,/user/register 被写作了/user/Register,再比如/user/register 变成了//user/register。
2、后端未提供服务
有一些统一处理的路由规则,如果规则和服务之间尚未提供明确的服务,则会调用错误信息。我们可以对这一特效加以利用,在下一个章节会重点提及。
3、系统runtime类错误
比如外部传递俩个参数,a和b,内部计算c=a/b当b为0时则会出现runtime错误,此时会调用错误配置方法.
4.3 定制自己的路由框架
如上所示展示了路由管理模块需要考虑的一些因素,下图展示一个路由管理模块的大致流程。
1、预处理uri,主要是对uri进行预处理,包括格式判断,过滤斜杠等.
2、如何判断页面,我们约定使用.shtml结尾的都是页面,不包含任务后缀的都是api
3、如何判断模板是否存在:我们通过统一判断文件路径是否存在来判断模板是否存在,为了实现该功能,首先需要做出约定
所有模板都存放到view文件夹下;模板名和文件名存在一一对应关系,如下所示则对于模板文件位置为view/user/list.html
{{define "user/list.html"}}
//somthing
{{end}}
接着在Config中对模板进行初始化
f, _ := filepath.Glob("view/**/*") for _, b := range f { cfg.TempFileMap[b] = 0 }
最后在默认路由函数中判断requesturi是否存在在cfg.TempFileMap中,具体代码如下
var urimap map[string]int = make(map[string]int) //Controller.go //对未定义的路由规则进行处理 func NoRoute(ctx *gin.Context) { uri := ctx.Request.RequestURI isAjax := "XMLHttpRequest"==ctx.GetHeader("X-Requested-With") isPage := strings.Contains(ctx.Request.RequestURI,".shtml") uri = strings.TrimLeft(uri, "/") uri = strings.TrimSuffix(uri, ".shtml") //如果已经定义过了则是一定存在的 //存在则=计算统计次数 //不存在则为-1 //0 代表初始化 //如果定义了, stat, has := urimap[uri] //如果有 if !has { //没有则先初始化一下 urimap[uri] = 0 } if 0 == stat { //寻找初始化的数据 cfg := GetCfg() var flag int = -1 for fpath, _ := range cfg.TempFileMap { fpath = strings.Replace(fpath,"\\","/",-1) if strings.Index(fpath, uri) > -1 { flag = 1 break } fmt.Print(fpath) } urimap[uri] = stat + flag } //如果不存在则跳转出错页面 if 0 > urimap[uri] { NoMethod(ctx) } else { //如果是AJAX if isPage{ //response html ctx.HTML(200, uri+".html", "Q") }else if isAjax{ //response json ctx.JSON(200,nil) } } } func NoMethod(ctx *gin.Context) { uri := ctx.Request.RequestURI fmt.Printf("NoMethod" + uri) uri = strings.TrimLeft(uri, "/") uri = strings.TrimSuffix(uri, ".shtml") //ctx.HTML(http.StatusOK, model+"/"+action+".html", gin.H{"title": "test"}) ctx.HTML(200, uri+".html", "Q") }
本文源代码源代码获取地址 https://github.com/winlion/restgo
待提供源代码清单
10.1 restgo后台管理框架
https://github.com/winlion/restgo-admin
10.2 天天任务清单小程序
https://github.com/winlion/dailytask
10.3 工业大数据采集
10.4 restgo cms
10.5 restgo 千人大群
golang实战使用gin+xorm搭建go语言web框架restgo详解1.1 go语言的困境
golang实战使用gin+xorm搭建go语言web框架restgo详解1.2 我要做什么
golang实战使用gin+xorm搭建go语言web框架restgo详解2 框架基本架构
golang实战使用gin+xorm搭建go语言web框架restgo详解3 系统常用配置参数
golang实战使用gin+xorm搭建go语言web框架restgo详解4 路由配置
golang实战使用gin+xorm搭建go语言web框架restgo详解5 控制器C
golang实战使用gin+xorm搭建go语言web框架restgo详解5.2 跳转和重定向
golang实战使用gin+xorm搭建go语言web框架restgo详解5.3 资源控制器
golang实战使用gin+xorm搭建go语言web框架restgo详解5.4 控制器参数绑定
golang实战使用gin+xorm搭建go语言web框架restgo详解5.5 控制器模型绑定
golang实战使用gin+xorm 搭建 go语言web框架restgo搭建详解5.6 控制器参数校验
Golang go语言整合gin+xorm 搭建 web框架restgo搭建详解5.7 控制器数据响应
golang实战使用gin+xorm搭建go语言web框架restgo详解5.9 控制器controller编程
golang实战使用gin+xorm搭建go语言web框架restgo详解6.1 模型M和Orm
golang实战使用gin+xorm搭建go语言web框架restgo详解6.4 推荐编程方式
golang实战使用gin+xorm搭建go语言web框架restgo详解7 视图层V
golang实战使用gin+xorm搭建go语言web框架restgo详解8 关于模板
golang实战使用gin+xorm搭建go语言web框架restgo详解9 session、日志、鉴权
作者简介:胡文林,持续创业者,长期从事技术开源工作。微信号jiepool-winlion