zoukankan      html  css  js  c++  java
  • go web gin 框架 中间件的学习和使用

     
    package main
    
    import (
    	"fmt"
    	"github.com/gin-gonic/gin"
    	"net/http"
    	"time"
    )
    
    type Student struct {
    	Name    string `json:"name"`
    	Country string `json:"country"`
    	City    string `json:"city"`
    }
    
    // handlerfun  处理函数的格式
    /*
    func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
    	return group.handle(http.MethodGet, relativePath, handlers)
    }
    */
    
    // 自定义中间件  注意: 中间件必须是一个handlerfunc 类型
    func Myhandlerfun(c *gin.Context) {
    	fmt.Println("路由函数 start.....")
    
    	time.Sleep(3) // make this functinon sleep a secent so that we can see the diffirent clearly
    	c.JSON(http.StatusOK, gin.H{
    		"cotent": "ok",
    	})
    
    
    
    }
    
    // 自定义中间件:
    func Mytestmi(c *gin.Context) {
    	fmt.Println("m1 start.....")
    	fmt.Println("---------------this is for middleware test----------")
    	ti := time.Now()
    	c.Next() // 调用后续处理的函数 包括后续的中间件。 所有后续中函数和中间件执行完了 以后,
    	timecost := time.Since(ti)
    	fmt.Printf("处理函数消耗的时间是%v
     ", timecost)
    	fmt.Println("中间件函数 Mytestmi 退出")
    	fmt.Println("m1 stop.....")
    
    }
    
    // 再定义一个中间件
    func m2(c *gin.Context)  {
    	fmt.Println("m2 start.....")
    	fmt.Println("--------------m2 test--------------")
    	//c.Abort() //阻止 后续的执行函数操作     查询结果 查询,路由函数正常执行, m3 没有执行。
    
    }
    
    // 	c.Abort() 阻止调用后续的执行函数。 再创建一个中间件,在上一个中间件中 c.Abort() ,然后看下 后续的中间件和 路由执行函数是否有执行。
    
    func m3(c *gin.Context)  {
    	fmt.Println("m3 start.....")
    	c.Set("hostname","v_jsonchang")
    	fmt.Println("----------------this is m3 test---------------")
    	fmt.Println("m3 stop.....")
    }
    
    
    // 是否登录判断的中间件
    func authorMiddle(c *gin.Context)  {
    	c.Next()
    	c.Abort()
    
    
    	/*
    	大致逻辑思路
    	if 是用户
    	c.Next()
    	else
    	c.Abort()0
    	*/
    }
    
    // 写法
    func AuthorCheckMiddle(check bool) gin.HandlerFunc  {
    
    	// 连接数据库
    	// 或者一些其他的准备工作[这部分在程序运行的时候就执行了]
    
    	/*
    	 运行程序的时候的日志信息:
    	[GIN-debug] GET    /index                    --> main.Myhandlerfun (4 handlers)
    	[GIN-debug] GET    /home                     --> main.main.func1 (4 handlers)
    	[GIN-debug] GET    /student/info             --> main.main.func2 (6 handlers)
    	[GIN-debug] POST   /student/add              --> main.main.func3 (6 handlers)
    	数据库连接中........
    	查找数据库.......
    	数据正确 用户存在的
    	[GIN-debug] GET    /authtest/test            --> main.main.func4 (4 handlers)
    	[GIN-debug] GET    /mytest/test              --> main.main.func5 (4 handlers)
    	[GIN-debug] GET    /mytest                   --> main.main.func6 (3 handlers)
    	[GIN-debug] Listening and serving HTTP on :8922
    
    	*/
    
    	// 测试例子
    	fmt.Println("数据库连接中........")
    	fmt.Println("查找数据库.......")
    	fmt.Println("数据正确 用户存在的")
    
    
    
    	/*
    
    
    	*/
    	return func(c *gin.Context) {
    		if check {
    			fmt.Println("需要校验")
    			fmt.Println("开始校验-------------")
    			// 存放具体的逻辑
    			// 是否登录的判断 。。。。
    			fmt.Println("校验结束-------------")
    
    		} else {
    			c.Next()
    		}
    	}
    
    }
    
    
    
    
    
    
    func main() {
    	r := gin.Default()
    	//r.Use(Mytestmi) // 全局的中间件 如果想全局设置的话。
    	r.GET("/index", Mytestmi, Myhandlerfun)
    
    	// 可以给某个路由 直接添加 写好的中间件,自行添加和去掉,对比输出 结果
    	// 缺点:加入路由比较多,自己每一个都要加一下, 解决方法: 直接给整体加一个,使用方法: use 函数。
    	r.GET("/home", Mytestmi, func(c *gin.Context) {
    		time.Sleep(5) // 让程序睡一会 模拟耗时的函数处理
    		c.JSON(http.StatusOK, gin.H{
    			"home":    "shanxi",
    			"weather": "good",
    		})
    
    		/*
    			没有加中间件的执行日志信息:
    			日志信息
    			[GIN-debug] Listening and serving HTTP on :7777
    			[GIN] 2021/02/26 - 15:29:27 |?[97;42m 200 ?[0m|       994.3µs |       127.0.0.1 |?[97;44m GET     ?[0m "/home"
    			[GIN] 2021/02/26 - 15:29:35 |?[97;42m 200 ?[0m|      6.9904ms |       127.0.0.1 |?[97;44m GET     ?[0m "/home"
    
    			输出:
    
    			{
    			    "home": "shanxi",
    			    "weather": "good"
    			}
    
    			加了中间件之后,再次执行的日志信息
    
    			[GIN] 2021/02/26 - 15:32:09 |?[97;42m 200 ?[0m|      9.9996ms |       127.0.0.1 |?[97;44m GET     ?[0m "/home"
    			---------------this is for middleware test----------
    			处理函数消耗的时间是1.0001ms
    			 中间件函数 Mytestmi 退出
    		*/
    	})
    
    	// 创建一个路由分组 进行整体的中间件的使用
    	studentGroup := r.Group("/student")
    
    	// studentGroup 分组整体 使用中间件
    	studentGroup.Use(Mytestmi,m2,m3) // 再添加一个中间件
    	// 分组路由1
    	studentGroup.GET("/info", func(c *gin.Context) {
    		c.JSON(http.StatusOK, gin.H{
    			"school": "深圳大学",
    			"Class":  "三年级",
    			"Number": 100,
    		})
    	})
    
    	studentGroup.POST("/add", func(c *gin.Context) {
    		fmt.Println("路由函数 开始.....")
    
    		//实例化 一个学生结构体
    		stu := &Student{}
    		// 请求json数据绑定到 结构体
    		err := c.ShouldBindJSON(&stu)
    		if err != nil {
    			c.JSON(http.StatusInternalServerError,gin.H{
    				"err": err.Error(),
    			})
    		} else {
    			c.JSON(http.StatusOK,gin.H{
    				"result":"ok",
    				"message":"add successful",
    				"Name":stu.Name,
    				"Country":stu.Country,
    				"City":stu.City,
    			})
    		}
    		fmt.Println("路由函数 结束.....")
    
    	})
    
    
    	//   AuthorCheckMiddle  测试
    	authtest := r.Group("/authtest")
    	authtest.Use(AuthorCheckMiddle(false)) // true 需要校验  false 不需要校验 可以看到输出的变化,打开是有校验的打印信息,关闭是没有走校验
    	authtest.GET("/test", func(c *gin.Context) {
    		c.JSON(http.StatusOK,gin.H{
    			"auth":"ok",
    		})
    	})
    
    
    	/*
    
    	加中间件之前
    	日志没有显示 中间件的信息。
    
    	[GIN-debug] Listening and serving HTTP on :8922
    	[GIN] 2021/02/26 - 16:02:28 |?[97;42m 200 ?[0m|            0s |       127.0.0.1 |?[97;44m GET     ?[0m "/student/info"
    	[GIN] 2021/02/26 - 16:02:41 |?[97;42m 200 ?[0m|            0s |       127.0.0.1 |?[97;44m GET     ?[0m "/student/info"
    	[GIN] 2021/02/26 - 16:02:42 |?[97;42m 200 ?[0m|            0s |       127.0.0.1 |?[97;44m GET     ?[0m "/student/info"
    	[GIN] 2021/02/26 - 16:03:34 |?[90;43m 404 ?[0m|            0s |       127.0.0.1 |?[97;46m POST    ?[0m "/student/info"
    	[GIN] 2021/02/26 - 16:03:46 |?[97;41m 500 ?[0m|            0s |       127.0.0.1 |?[97;46m POST    ?[0m "/student/add"
    	[GIN] 2021/02/26 - 16:04:40 |?[97;42m 200 ?[0m|            0s |       127.0.0.1 |?[97;46m POST    ?[0m "/student/add"
    	[GIN] 2021/02/26 - 16:04:46 |?[97;42m 200 ?[0m|            0s |       127.0.0.1 |?[97;46m POST    ?[0m "/student/add"
    
    	输出:
    
    	http://127.0.0.1:8922/student/info  get 请求
    
    	{
    	    "Class": "三年级",
    	    "Number": 100,
    	    "school": "深圳大学"
    	}
    
    	http://127.0.0.1:8922/student/add  post 请求
    	{
    	    "City": "shenzhen",
    	    "Country": "china",
    	    "Name": "stefan",
    	    "message": "add successful",
    	    "result": "ok"
    	}
    
    
    
    
    	studentGroup.Use(Mytestmi) 使用中间件之后 请求日志:
    
    
    	[GIN-debug] Listening and serving HTTP on :8922
    	---------------this is for middleware test----------
    	处理函数消耗的时间是995.7µs
    	 中间件函数 Mytestmi 退出
    	[GIN] 2021/02/26 - 16:09:14 |?[97;42m 200 ?[0m|      2.9967ms |       127.0.0.1 |?[97;44m GET     ?[0m "/student/info"
    	---------------this is for middleware test----------
    	处理函数消耗的时间是0s
    	 中间件函数 Mytestmi 退出
    	[GIN] 2021/02/26 - 16:09:34 |?[97;42m 200 ?[0m|     27.0001ms |       127.0.0.1 |?[97;46m POST    ?[0m "/student/add"
    
    	通过日志可以看出  学生分组路由已经添加了 中间件的函数。
    
    
    
    
    
    
    	*/
    
    	//如果想要设置全局的中间件,就直接给 r 设置即可
    
    	/*
    		r := gin.Default()
    		r.Use(Mytestmi)  use 函数中,中间件 只需要传入函数名字即可,不需要后面的括号
    	*/
    	testgroup := r.Group("/mytest")
    	testgroup.Use(Mytestmi,m2,m3)
    	testgroup.GET("/test", func(c *gin.Context) {
    
    		name,ok := c.Get("hostname") // "name" 测试 就是 匿名用户
    		if ! ok {
    			name = "匿名用户"
    
    		} else {
    			c.JSON(http.StatusOK,gin.H{
    				"hostname":name,
    			})
    		}
    
    
    	})
    
    	r.GET("/mytest", func(c *gin.Context) {
    		c.JSON(http.StatusOK,gin.H{
    			"message":"ok",
    		})
    
    	})
    
    
    
    
    	r.Run(":8922")
    
    }
    
    /*
    
    请求日志
    
    [GIN] 2021/02/26 - 15:20:13 |?[97;42m 200 ?[0m|      2.9978ms |       127.0.0.1 |?[97;44m GET     ?[0m "/index"
    ---------------this is for middleware test----------
    处理函数消耗的时间是998.1µs
     中间件函数 Mytestmi 退出
    [GIN] 2021/02/26 - 15:22:27 |?[97;42m 200 ?[0m|       998.1µs |       127.0.0.1 |?[97;44m GET     ?[0m "/index"
    
    
    */
    
    
    /*
    添加两个中间件,观察 执行的顺序
    
    
    日志输出:
    
    [GIN-debug] Listening and serving HTTP on :8922
    m1 start.....
    ---------------this is for middleware test----------
    m2 start.....
    --------------m2 test--------------
    m2 stop.....
    路由函数 开始.....
    路由函数 结束.....
    处理函数消耗的时间是2.9738ms
     中间件函数 Mytestmi 退出
    m1 stop.....
    
    
    
    
    
    执行顺序: 最开始的 进入中间件1--------中间件2.... 中间件3--------- 路由函数------再到中间件1 内部处理 最后中间件1 退出
    */
    

      

    执行流程图

     

    中间件和处理函数的执行流程

    [GIN-debug] Listening and serving HTTP on :8922
    m1 start.....
    ---------------this is for middleware test----------
    m2 start.....
    --------------m2 test--------------
    m2 stop.....
    路由函数 开始.....
    路由函数 结束.....
    处理函数消耗的时间是2.9738ms
     中间件函数 Mytestmi 退出
    m1 stop.....
    
    
    
    
    
    执行顺序: 最开始的 进入中间件1--------中间件2.... 中间件3--------- 路由函数------再到中间件1 内部处理 最后中间件1 退出 
    

      

  • 相关阅读:
    类型转换
    with语句用法
    微软工具下载网址
    第2章信息系统服务管理
    声明变量
    管理机中录入485总表的操作方法
    任务 uitableview uiscrollview uiresponder
    如何去掉UITableViewController中的分隔线setSeparatorStyle
    NSRunLoop 概述和原理
    使用 Notifications
  • 原文地址:https://www.cnblogs.com/zexin88/p/14452873.html
Copyright © 2011-2022 走看看