gin框架学习-路由分组和中间件

本文涉及的产品
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
注册配置 MSE Nacos/ZooKeeper,118元/月
性能测试 PTS,5000VUM额度
简介: Logger中间件将日志写入gin.DefaultWriter,即使配置了GIN_MODE=release。

前言


感谢开源项目gin-vue-admin,以及1010工作室的视频教程

本人学识尚浅,如有错误,请评论指出,谢谢!

详细可见个人博客:https://linzyblog.netlify.app/


一、路由分组


在我们实际的开发应用中我们希望能个各个功能模块的路由进行分组,同一个模块的不同路由带有同样的前缀。


  • 作用:首先是路由更加的清晰 并且我们在针对某一组路由进行中间件权限校验的时候也比较的方便。


代码示例:


r := gin.Default()
v1 := r.Group("v1")
v1.GET("/test1", func(c *gin.Context) {
  c.JSON(200, gin.H{
    "msg": "这里是test1",
  })
})
v1.GET("/test2", func(c *gin.Context) {
  c.JSON(200, gin.H{
    "msg": "这里是test2",
  })
})
r.Run(":8080")


打开postman选择GET请求,访问http://localhost:8080/v1/test1


7c834730148149dbafc104361e24776c.png


二、中间件


1、中间件简介


Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。


6a0a299373fa45b4a53683a9e9190d32.png


中间件就是作用于两个模块之间的功能软件,可以作为拦截器、记录日志等,比如在前后端开发中


路由--------> 中间件(过滤作用)--------> 控制器


Gin中,中间件的效果可以简单的概括为:


  • 设置好中间件以后,中间件后面的路由都会使用这个中间件
  • 设置在中间件之前的路由则不会生效


2、定义中间件


Gin中的中间件必须是一个gin.HandlerFunc类型,在自定义中间件函数时,有两种写法:


func middleW() gin.HandlerFunc {
  return func(c *gin.Context) {
    ...
  }
}
router.Use(middleW())


或者


func middleW(c *gin.Context) {
  ...
}
router.Use(middleW())


3、注册中间件


在Gin框架中,我们可以注册全局中间件,也可以给单独路由或者路由组注册中间件,可以为路由添加任意数量的中间件。


  • 当我们存在多个中间件的时候,中间件的处理顺序是参考洋葱模型:


a1175dae4b594d2a9e17fafac81ed8d1.png


简而言之,请求是队列处理,响应则是堆栈处理。


  • 定义中间件代码:


//声明一个中间件方法
func middleW() gin.HandlerFunc {
  return func(c *gin.Context) {
    fmt.Println("我在方法前")
    c.Next()
    fmt.Println("我在方法后")
  }
}


1)注册全局中间件


代码示例:


func main() {
  r := gin.Default()
  //注册一个全局中间件
  r.Use(middleW())
  r.GET("/test", func(c *gin.Context) {
    fmt.Println("我在方法内部")
    c.JSON(200, gin.H{
      "msg": "成功了",
    })
  })
  r.Run(":8080")
}


打开postman选择GET请求,访问http://localhost:8080/test

0ab019b39b664bb88780b89eebfdf0e5.png

2bae28763ea342c68dfcd75859a5259d.png


2)单独注册某个路由中间件


代码示例:


func main() {
  r := gin.Default()
  r.GET("/test", middleW(), func(c *gin.Context) {
    fmt.Println("我在方法内部")
    c.JSON(200, gin.H{
      "msg": "成功了",
    })
  })
  r.Run(":8080")
}


打开postman选择GET请求,访问http://localhost:8080/test


0ab019b39b664bb88780b89eebfdf0e5.png

a48c06756f1b4e5b9717c7aade7bcd99.png


3)注册路由组中间件


代码示例:


func main() {
  r := gin.Default()
  //定义一个路由组 并注册中间件
  v1 := r.Group("v1").Use(middleW())
  v1.GET("/test1", func(c *gin.Context) {
    fmt.Println("我在方法内部")
    c.JSON(200, gin.H{
      "msg": "这里是test1",
    })
  })
  v1.GET("/test2", func(c *gin.Context) {
    fmt.Println("我在方法内部")
    c.JSON(200, gin.H{
      "msg": "这里是test2",
    })
  })
  r.Run()
}


打开postman选择GET请求,访问http://localhost:8080/v1/test1


9399ac3ab79c4a26a82225ad76a3304c.png


b9a2405bb57c4580964dc77e113e012e.png


4、中间件的嵌套


中间件可以嵌套使用,这里有三个Gin框架相关的函数。


1)Next()


表示跳过当前中间件剩余内容, 去执行下一个中间件。 当所有操作执行完之后,以出栈的执行顺序返回,执行中间件的剩余代码。


中间件定义:


//定义中间件1
func middlewOne() gin.HandlerFunc {
  return func(c *gin.Context) {
    fmt.Println("我在方法前,我是1")
    c.Next()
    fmt.Println("我在方法后,我是1")
  }
}
//定义中间件2
func middlewTwo() gin.HandlerFunc {
  return func(c *gin.Context) {
    fmt.Println("我在方法前,我是2")
    c.Next()
    fmt.Println("我在方法后,我是2")
  }
}
func main() {
  r := gin.Default()
  //使用多个中间件
  r.GET("/test", middlewOne(), middlewTwo(), func(c *gin.Context) {
    fmt.Println("我在方法内部")
    c.JSON(200, gin.H{
      "msg": "这里是test1",
    })
  })
  r.Run()
}


打开postman选择GET请求,访http://localhost:8080/test


2a3b0545289743c7b266a4630944bf74.png

7d647b6124b54ce4bb5bb1bfafa1352d.png


2)return


终止执行当前中间件剩余内容,执行下一个中间件。 当所有的函数执行结束后,以出栈的顺序执行返回,但不执行return后的代码。


//定义中间件1
func middlewOne() gin.HandlerFunc {
  return func(c *gin.Context) {
    fmt.Println("我在方法前,我是1")
    c.Next()
    fmt.Println("我在方法后,我是1")
  }
}
//定义中间件2
func middlewTwo() gin.HandlerFunc {
  return func(c *gin.Context) {
    fmt.Println("我在方法前,我是2")
    return
    fmt.Println("我在方法后,我是2")
  }
}
//定义中间件3
func middlewThree() gin.HandlerFunc {
  return func(c *gin.Context) {
    fmt.Println("我在方法前,我是3")
    c.Next()
    fmt.Println("我在方法后,我是3")
  }
}
func main() {
  r := gin.Default()
  //使用多个中间件
  r.GET("/test", middlewOne(), middlewTwo(), middlewThree(), func(c *gin.Context) {
    fmt.Println("我在方法内部")
    c.JSON(200, gin.H{
      "msg": "这里是test1",
    })
  })
  r.Run()
}


打开postman选择GET请求,访问http://localhost:8080/test

cce05fc51f28498e90a1740c2d4ca02c.png

8115efe92b494c978c5c3c08ab445bfa.png


3Abort()


只执行当前中间件, 操作完成后,以出栈的顺序,依次返回上一级中间件。


//定义中间件1
func middlewOne() gin.HandlerFunc {
  return func(c *gin.Context) {
    fmt.Println("我在方法前,我是1")
    c.Next()
    fmt.Println("我在方法后,我是1")
  }
}
//定义中间件2
func middlewTwo() gin.HandlerFunc {
  return func(c *gin.Context) {
    fmt.Println("我在方法前,我是2")
    c.Abort()
    fmt.Println("我在方法后,我是2")
  }
}
//定义中间件3
func middlewThree() gin.HandlerFunc {
  return func(c *gin.Context) {
    fmt.Println("我在方法前,我是3")
    c.Next()
    fmt.Println("我在方法后,我是3")
  }
}
func main() {
  r := gin.Default()
  //使用多个中间件
  r.GET("/test", middlewOne(), middlewTwo(), middlewThree(), func(c *gin.Context) {
    fmt.Println("我在方法内部")
    c.JSON(200, gin.H{
      "msg": "这里是test1",
    })
  })
  r.Run()
}


打开postman选择GET请求,访问http://localhost:8080/test


04f7b5cc80e641c2a814c946a513abf6.png

4222e681c5f84f5dab50b84c4e7005e0.png


5、中间件注意事项


1)gin默认中间件


gin.Default()默认使用了Logger和Recovery中间件,其中:


Logger中间件将日志写入gin.DefaultWriter,即使配置了GIN_MODE=release。


Recovery中间件会recover任何panic。如果有panic的话,会写入500响应码。


如果不想使用上面两个默认的中间件,可以使用gin.New()新建一个没有任何默认中间件的路由。


2)gin中间件中使用goroutine


当在中间件或handler中启动新的goroutine时,不能使用原始的上下文(c *gin.Context),必须使用其只读副本(c.Copy())。


参考大佬资料:https://blog.csdn.net/qq_49723651/article/details/123694746

目录
相关文章
|
2月前
|
数据采集 中间件 开发者
Scrapy爬虫框架-自定义中间件
Scrapy爬虫框架-自定义中间件
|
27天前
|
消息中间件 NoSQL Java
springboot整合常用中间件框架案例
该项目是Spring Boot集成整合案例,涵盖多种中间件的使用示例,每个案例项目使用最小依赖,便于直接应用到自己的项目中。包括MyBatis、Redis、MongoDB、MQ、ES等的整合示例。
84 1
|
3月前
|
缓存 中间件 网络架构
Python Web开发实战:高效利用路由与中间件提升应用性能
在Python Web开发中,路由和中间件是构建高效、可扩展应用的核心组件。路由通过装饰器如`@app.route()`将HTTP请求映射到处理函数;中间件则在请求处理流程中插入自定义逻辑,如日志记录和验证。合理设计路由和中间件能显著提升应用性能和可维护性。本文以Flask为例,详细介绍如何优化路由、避免冲突、使用蓝图管理大型应用,并通过中间件实现缓存、请求验证及异常处理等功能,帮助你构建快速且健壮的Web应用。
30 1
|
5月前
|
JSON 中间件 数据处理
实践出真知:通过项目学习Python Web框架的路由与中间件设计
【7月更文挑战第19天】探索Python Web开发,掌握Flask或Django的关键在于理解路由和中间件。路由连接URL与功能,如Flask中@app.route()定义请求响应路径。中间件在请求处理前后执行,提供扩展功能,如日志、认证。通过实践项目,不仅学习理论,还能提升构建高效Web应用的能力。示例代码展示路由定义及模拟中间件行为,强调动手实践的重要性。
60 1
|
5月前
|
缓存 监控 安全
中间件在Python Web框架中的角色与应用场景
【7月更文挑战第21天】中间件在Python Web开发中作为服务器与应用间的软件层,拦截、处理请求和响应,无需改动应用代码。它扩展框架功能,复用跨应用逻辑,加强安全,优化性能。如Django中间件处理请求/响应,Flask通过WSGI中间件实现类似功能,两者均在不触及核心代码前提下,灵活增强应用行为,是现代Web开发关键组件。
57 0
|
5月前
|
缓存 中间件 网络架构
Python Web开发实战:高效利用路由与中间件提升应用性能
【7月更文挑战第20天】在Python Web开发中,路由与中间件是构建高效应用的核心。路由通过装饰器如`@app.route()`在Flask中映射请求至处理函数;中间件(如`@app.before_request`, `@app.after_request`)则在请求流程中插入自定义逻辑。优化路由包括减少冲突、利用动态参数及蓝图;中间件可用于缓存响应、请求验证和异常处理,显著提升性能和可维护性。良好设计是关键,示例代码展示了如何在Flask中实现这些策略。
58 0
|
5月前
|
中间件 数据库 开发者
解析Python Web框架的四大支柱:模板、ORM、中间件与路由
【7月更文挑战第20天】Python Web框架如Django、Flask、FastAPI的核心包括模板(如Django的DTL和Flask的Jinja2)、ORM(Django的内置ORM与Flask的SQLAlchemy)、中间件(Django的全局中间件与Flask的装饰器实现)和路由(Django的urls.py配置与Flask的@app.route()装饰器)。这些组件提升了代码组织和数据库操作的便捷性,确保了Web应用的稳定性和可扩展性。
66 0
|
5月前
|
中间件 API 开发者
深入理解Python Web框架:中间件的工作原理与应用策略
【7月更文挑战第19天】Python Web中间件摘要:**中间件是扩展框架功能的关键组件,它拦截并处理请求与响应。在Flask中,通过`before_request`和`after_request`装饰器模拟中间件行为;Django则有官方中间件系统,需实现如`process_request`和`process_response`等方法。中间件用于日志、验证等场景,但应考虑性能、执行顺序、错误处理和代码可维护性。
82 0
|
6月前
|
消息中间件 存储 中间件
【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka
【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka
1506 0
|
5月前
|
消息中间件 编解码 Docker
Docker部署RabbitMQ消息中间件
【7月更文挑战第4天】Docker部署RabbitMQ消息中间件
277 3