前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >什么是Gin中间件

什么是Gin中间件

作者头像
会呼吸的Coder
发布2020-02-17 17:54:23
2.6K0
发布2020-02-17 17:54:23
举报
文章被收录于专栏:会呼吸的Coder

Gin中间件是什么?Gin中间件的作用是什么?要怎么样使用中间件呢?

1. Gin中间件的作用

好吧,简单来说,Gin中间件的作用有两个:

  1. Web请求到到达我们定义的HTTP请求处理方法之前,拦截请求并进行相应处理(比如:权限验证,数据过滤等),这个可以类比为前置拦截器前置过滤器
  2. 在我们处理完成请求并响应客户端时,拦截响应并进行相应的处理(比如:添加统一响应部头或数据格式等),这可以类型为后置拦截器后置过滤器
2. Gin中间件的定义

在Gin框架中,中间件的类型定义如下代码所示,可以看出,中间件实际上就是一个以gin.Context为形参的函数而已,与我们定义处理HTTP请求的Handler本质上是一样的,并没有什么神秘可言。

代码语言:javascript
复制
type HandlerFunc func(*Context)
3. Gin内置中间件
在使用Gin框架开发Web应用时,常常需要自定义中间件,不过,Gin也内置一些中间件,我们可以直接使用,下面是内置中间件列表:
代码语言:javascript
复制
func BasicAuth(accounts Accounts) HandlerFunc
func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc
func Bind(val interface{}) HandlerFunc
func ErrorLogger() HandlerFunc
func ErrorLoggerT(typ ErrorType) HandlerFunc
func Logger() HandlerFunc
func LoggerWithConfig(conf LoggerConfig) HandlerFunc
func LoggerWithFormatter(f LogFormatter) HandlerFunc
func LoggerWithWriter(out io.Writer, notlogged ...string) HandlerFunc
func Recovery() HandlerFunc
func RecoveryWithWriter(out io.Writer) HandlerFunc
func WrapF(f http.HandlerFunc) HandlerFunc
func WrapH(h http.Handler) HandlerFunc

中间的使用

1. 不使用默认中间件

使用gin.Default()返回的gin.Engine时,已经默认使用了RecoveryLogger中间件,从下面gin.Default()方法的源码可以看出:func Default() *Engine {

代码语言:javascript
复制
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery())
return engine
}

当我们不想使用这两个中间件时,可以使用gin.New()方法返回一个不带中间件的gin.Engine对象:

router := gin.New()

2. 全局使用中间件

直拉使用gin.Engine结构体的Use()方法便可以在所有请求应用中间件,这样做,中间件便会在全局起作用。

代码语言:javascript
复制
router := gin.New()
router.Use(gin.Recovery())
3. 路由分组使用中间件

更多的时候,我们会根据业务不同划分不同路由分組(RouterGroup ),不同的路由分组再应用不同的中间件,这样就达到了不同的请求由不同的中间件进行拦截处理

代码语言:javascript
复制
router := gin.New()
user := router.Group("user", gin.Logger(),gin.Recovery())
{
user.GET("info", func(context *gin.Context) {
})
user.GET("article", func(context *gin.Context) {
})
}
4. 单个路由使用中间件

除了路由分组,单个请求路由,也可以应用中间件,如下:

代码语言:javascript
复制
router := gin.New()
router.GET("/test",gin.Recovery(),func(c *gin.Context){
c.JSON(200,"test")
})

也可以在单个路由中使用多箇中间件,如下:

代码语言:javascript
复制
router := gin.New()
router.GET("/test",gin.Recovery(),gin.Logger(),func(c *gin.Context){
c.JSON(200,"test")
})

自定义中间件

上面的讲解中,我们看到,虽然Gin提供了一些中间件,我们直接使用即可,但内置中间件可能满足不我们业务开发的需求,在开发过程中我们需要开自己的中间件,这在Gin框架中是非常简单的一件事。

在前面,我们看到Gin框架自带的中间件方法,都是返回HandlerFunc类型,其定义如下:

代码语言:javascript
复制
type HandlerFunc func(*Context)

HandlerFunc规范了Gin中间件的定义,所以自定义中间件,如下:

代码语言:javascript
复制
func MyMiddleware(c *gin.Context){
    
}

定义好中间件,便可使用中间件,这里演示的是全局使用,也可以在单个路由或路由分组中使用:

代码语言:javascript
复制
router = gin.Default()
router.Use(MyMiddleware)

或者,通过自定义方法,返回一箇中间件函数,这是Gin框架中更常用的方式:

代码语言:javascript
复制
func MyMiddleware(){
return func(c *gin.Context){
}
}

使用自定义的中间件,注意MyMiddleware方法后面有加括号:

代码语言:javascript
复制
router = gin.Default()
router.Use(MyMiddleware())

数据传递

当我们在中间件拦截并预先处理好数据之后,要如何将数据传递我们定义的处理请求的HTTP方法呢?可以使用gin.Context中的Set()方法,其定义如下,Set()通过一个key来存储作何类型的数据,方便下一层处理方法获取。

代码语言:javascript
复制
func (c *Context) Set(key string, value interface{})

当我们在中间件中通过Set方法设置一些数值,在下一层中间件或HTTP请求处理方法中,可以使用下面列出的方法通过key获取对应数据。

其中,gin.Context的Get方法返回interface{},通过返回exists可以判断key是否存在。

代码语言:javascript
复制
func (c *Context) Get(key string) (value interface{}, exists bool)

当我们确定通过Set方法设置对应数据类型的值时,可以使用下面方法获取应数据类型的值。

代码语言:javascript
复制
func (c *Context) GetBool(key string) (b bool)
func (c *Context) GetDuration(key string) (d time.Duration)
func (c *Context) GetFloat64(key string) (f64 float64)
func (c *Context) GetInt(key string) (i int)
func (c *Context) GetInt64(key string) (i64 int64)
func (c *Context) GetString(key string) (s string)
func (c *Context) GetStringMap(key string) (sm map[string]interface{})
func (c *Context) GetStringMapString(key string) (sms map[string]string)
func (c *Context) GetStringMapStringSlice(key string) (smss map[string][]string)
func (c *Context) GetStringSlice(key string) (ss []string)
func (c *Context) GetTime(key string) (t time.Time)

示例代码:

代码语言:javascript
复制
func MyMiddleware(c *gin.Context){
c.Set("mykey",10)
}
router := gin.New()
router.GET("test",MyMiddleware,func(c *gin.Context){
c.GetInt("mykey")
})

拦截请求与后置拦截

1. 拦截请求

我们说过,中间件的最大作用就是拦截过滤请求,比如我们有些请求需要用户登录或者需要特定权限才能访问,这时候便可以中间件中做过滤拦截,当用户请求不合法时,可以使用下面列出的gin.Context的几个方法中断用户请求:

下面三个方法中断请求后,直接返回200,但响应的body中不会有数据。

代码语言:javascript
复制
func (c *Context) Abort()
func (c *Context) AbortWithError(code int, err error) *Error
func (c *Context) AbortWithStatus(code int)

使用AbortWithStatusJSON()方法,中断用户请求后,则可以返回json格式的数据.

代码语言:javascript
复制
func (c *Context) AbortWithStatusJSON(code int, jsonObj interface{})
2. 后置拦截

前面我们讲的都是到达我们定义的HTTP处理方法前进行拦截,其实,如果在中间件中调用gin.ContextNext()方法,则可以请求到达并完成业务处理后,再经过中间件后置拦截处理,Next()方法定义如下:。

代码语言:javascript
复制
func (c *Context) Next()

在中间件调用Next()方法,Next()方法之前的代码会在到达请求方法前执行,Next()方法之后的代码则在请求方法处理后执行:func MyMiddleware(c *gin.Context){

代码语言:javascript
复制
c.Next()
】}
代码语言:javascript
复制
示例代码
代码语言:javascript
复制
func MyMiddleware(c *gin.Context){
c.Set("key",1000)
c.Next()
c.JSON(http.StatusOK,c.GetInt("key"))
}
router := gin.New()
router.GET("test", MyMiddleware, func(c *gin.Context) {
k := c.GetInt("key")
c.Set("key", k+2000)
})
router.Run()

上面示例程序运行结果为3000,通过上面这样一个简单的示例程序,我们可以看到中间件在请求拦截请求,处理数据并控制Web请求流程的作用。

小结

学习Gin框架,中间件middleware非常重要的一块知识,它可以我们定义处理HTTP请求的方法前拦截不合法的HTTP请求,或者预先处理好数据,或响应时添加统一的响应头部,因此在使用Gin开发Web应用时,中间件是必用的知识。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 初级程序员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. Gin中间件的作用
  • 2. Gin中间件的定义
  • 3. Gin内置中间件
  • 在使用Gin框架开发Web应用时,常常需要自定义中间件,不过,Gin也内置一些中间件,我们可以直接使用,下面是内置中间件列表:
  • 中间的使用
    • 1. 不使用默认中间件
      • 2. 全局使用中间件
        • 3. 路由分组使用中间件
          • 4. 单个路由使用中间件
          • 自定义中间件
          • 数据传递
          • 拦截请求与后置拦截
            • 1. 拦截请求
              • 2. 后置拦截
              • 小结
              相关产品与服务
              消息队列 TDMQ
              消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档