路由组
RouterGroup
是gin 里面的路由组,主要作用是实现gin的路由。
RouterGroup是嵌套在了Engine内部,实际上调用Engine的get,post等方式就是RouterGroup的实现。
另外RouterGroup还实现了如下两个接口:
Engine相当于RouterGroup的子类。
RouterGroup
对象实现了两个接口分别是路由相关的方法,另外还有Use
方法用于定义新的路由和中间件。
RouterGroup嵌套在Engine中,因此通过Engine也可以直接调用路由方法。
路由可以通过 r := gin.Default() 返回的对象来定义,这个方法会返回框架实例,而框架实例,也就是 gin.Engine 的实例,嵌套了 RouterGroup 结构体,因此可以直接通过 r 来定义路由,比如:
r.GET("/test", func(c *gin.Context) {
c.String(200, "Hello world!")
})
//创建一个服务器引擎
engine := gin.Default()
//配置web容器地址
engine.GET("/")
//定义路由组对象
group := gin.RouterGroup{}
group.GET("/test")
//配置服务器端口
engine.Run(":8080")
两种调用方式是等价的。
中间件
中间件是路由的前置函数,在路由点之前执行函数。
如上图所示,路由的前置函数可以由很多个,满足返回值类型为gin.HandlerFunc
且参数是gin.Context
就是中间件。
gin.HandlerFunc是返回值为gin.Context的方法类型。
中间可以直接放在路由之后,也可以通过Use
方法注册。
- 路由处理函数的顺序定义中间件
//定义权限认证中间件
func Certification() gin.HandlerFunc {
return func(context *gin.Context) {
context.Set("username", "xiaoxu")
if context.PostForm("username") != "xiaoxu" {
context.String(200, "用户名错误!")
context.Abort()
} else {
context.Next()
}
}
}
//gin的路由调用拦截器
import "github.com/gin-gonic/gin"
func main() {
engine := gin.Default()
engine.GET("/", Certification(), func(context *gin.Context) {
context.String(200, "Hello World")
})
engine.GET("/index", Certification(), func(context *gin.Context) {
context.String(200, "welcome index !")
})
engine.GET("/test", Certification(), func(context *gin.Context) {
context.String(200, "welcome test")
})
engine.Run("127.0.0.1:80")
}
- Use方法定义
使用 engine.Use() 的时候,定义的中间件是对所有请求都有效的。
使用 g := r.Group(“/user”); g.Use() 的时候,定义的中间件只对 /user 路由分组有效。
//配置web容器地址
get := engine.GET("/")
get.Use(Hello())
func Hello() gin.HandlerFunc {
return func(context *gin.Context) {
context.String(200, "hello")
}
}
对每个路由注册中间件是很繁琐的,而且代码都是一样的,可以通过路由组实现。
// /user 路由分组
group := gin.RouterGroup{}
v1 := group.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint)
}
group.Use(Hello())
项目分层
在实际项目中不可能所有的路由都在一个包下,要进行项目的分层。
控制器仅仅其路由作用,负责调用逻辑层的API。
// 首页
type IndexController struct{}
var indexLogic logic.IndexLogic
func (self IndexController) RegisterRoute(g gin.RouterGroup) {
g.GET("/index", self.getNotice)
}
func (IndexController) getNotice(c *gin.Context) {
notic := indexLogic.GetNotic()
param.SucRes(notic)
}
那么服务器就不在是简单的启动方式了
engine := gin.Default()
//路由
/**
...
**/
//配置服务器端口
engine.Run(":8080")
但是在原理上还是未变化的,最后都需要使用Engine的实例来启动。
但是在各个个控制器中一般传递了gin.RouterGroup
或者gin.Engine
两个都可以使用路由方法,因为前者是嵌套在后者中的。
不论创建那个的实例都是一样的,若是RouterGroup的实例,则需要载创建Engine的是并实现嵌套赋值,若是Engine实例直接调用监听方法即可。
//RouterGroup作为参数构建路由
//创建一个服务器引擎
engine := gin.Default()
//配置RouterGroup
router := gin.RouterGroup{}
c := new(controller.IndexController)
c.RegisterRoute(&router)
//RouterGroup赋值
engine.RouterGroup = router
//配置服务器端口
engine.Run("127.0.0.1:8080")
启动服务器必须使用Engine,所以RouterGroup作为参数是需要内嵌Engine。
如果路由直接使用Engine的话,就可以省略RouterGroup赋值那步。
//gin.Engine做参数
type IndexController struct{}
func (self IndexController) RegisterRoute(g *gin.Engine) {
g.GET("/index", self.getNotice)
}
func (IndexController) getNotice(c *gin.Context) {
lo := logic.IndexLogic{}
notice := lo.GetNotice()
fmt.Println(notice)
}
//服务器启动
//创建一个服务器引擎
engine := gin.Default()
//控制器传参
c := new(controller.IndexController)
c.RegisterRoute(engine)
//配置服务器端口
engine.Run("127.0.0.1:8080")