面试必问,什么是中间件?

中间件用过么?

Middleware是Web的重要组成部分,中间件(通常)是一小段代码,它们接受一个请求,对其进行处理,每个中间件只处理一件事情,完成后将其传递给另一个中间件或最终处理程序,这样就做到了程序的解耦。

全局中间件

  • 所有的请求都要经过此中间件
package main

import (
    "fmt"
    "time"

    "github.com/gin-gonic/gin"
)

// 定义中间
func MiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
        t := time.Now()
        fmt.Println("中间件开始执行了")
        // 设置变量到Context的key中,可以通过Get()取
        c.Set("request", "中间件")
        status := c.Writer.Status()
        fmt.Println("中间件执行完毕", status)
        t2 := time.Since(t)
        fmt.Println("time:", t2)
    }
}

func main() {
    // 1.创建路由, 访问路由时经过此中间件
    // 默认使用了2个中间件Logger(), Recovery()
    r := gin.Default()
    // 注册中间件
    r.Use(MiddleWare())
    {
        r.GET("/ce", func(c *gin.Context) {
            // 取在中间件设置的值,如果取到了说明中间件应用成功
            req, _ := c.Get("request")
            fmt.Println("request:", req)
            // 页面接收
            c.JSON(200, gin.H{"request": req})
        })
    }
    r.Run()
}

总结:我们在访问这个路由的时候,会执行里面的函数,返回想要的数据,中间件的作用就是在执行这个路由的函数之前所做的事情!

那么中间件一般可以做一些什么呢?

比如在微服务当中可以做一些 jwt 权限验证

// CommonJwtAuthMiddleware : with jwt on the verification, no jwt on the verification
type CommonJwtAuthMiddleware struct {
	secret string
}

func NewCommonJwtAuthMiddleware(secret string) *CommonJwtAuthMiddleware {
	return &CommonJwtAuthMiddleware{
		secret: secret,
	}
}

func (m *CommonJwtAuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if len(r.Header.Get("Authorization")) > 0 {
			//has jwt Authorization
			authHandler := handler.Authorize(m.secret)
			authHandler(next).ServeHTTP(w, r)
			return
		} else {
			//no jwt Authorization
			next(w, r)
		}
	}
}

总结:本例子是微服务的例子,在访问某一个接口前先检验jwt验证

中间件中最重要的Next() 方法

package main

import (
    "fmt"
    "time"

    "github.com/gin-gonic/gin"
)

// 定义中间
func MiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
        t := time.Now()
        fmt.Println("中间件开始执行了")
        // 设置变量到Context的key中,可以通过Get()取
        c.Set("request", "中间件")
        // 执行函数
        c.Next()
        // 中间件执行完后续的一些事情
        status := c.Writer.Status()
        fmt.Println("中间件执行完毕", status)
        t2 := time.Since(t)
        fmt.Println("time:", t2)
    }
}

func main() {
    // 1.创建路由
    // 默认使用了2个中间件Logger(), Recovery()
    r := gin.Default()
    // 注册中间件
    r.Use(MiddleWare())
    // {}为了代码规范
    {
        r.GET("/ce", func(c *gin.Context) {
            // 取值
            req, _ := c.Get("request")
            fmt.Println("request:", req)
            // 页面接收
            c.JSON(200, gin.H{"request": req})
        })

    }
    r.Run()
}


// console result
[GIN-debug] Listening and serving HTTP on :8080
中间件开始执行了
request: 中间件
中间件执行完毕 200
time: 177.7µs
[GIN] 2022/11/02 - 20:27:50 | 200 |     190.105µs |             ::1 | GET      "/ce"

总结:在执行next函数的时候,中间件下面的暂时不执行了,先去路由函数执行完成了之后再去执行next后面的代码。

局部中间件

简单展示一下代码吧

r.GET("/ce", MiddleWare(), func(c *gin.Context) {}

总结:其实就是给某一个路由单独走中间件,其他路由不走这个中间件。

你可能感兴趣的:(面试,中间件,职场和发展)