当前位置: 首页 > article >正文

go-zero学习笔记(五)

 api自定义中间件


1. 修改.api文件


	syntax="v1"
	
	type (
		GetInfoReq {
			IDs []string `json:"IDs"`
		}
	
		GetInfoData {
			ID     string `json:"ID"`
			Name   string `json:"Name"`
			MD5    string `json:"md5"`
			Size   int64  `json:"Size"`
			Uptime int64  `json:"uptime"`
		}
	
		GetInfoResp {
			Data      []*GetInfoData `json:"data"`
			Msg       string         `json:"msg"`
			Code      int64          `json:"code"`
			RequestID string         `json:"requestId"`
		}
	)
	
	// 修饰其紧挨的service块,且一个server块只能修饰一个service块
	@server(
		prefix: api/demo/v1         
		group: demo                 
		middleware: CheckMiddleware, TestMiddleware  
	)
	service demo-api {
		@doc(
			summary: "信息获取"
		)
		@handler GetInfoHandler
		post /Info/get (GetInfoReq) returns (GetInfoResp)
	}

         在server块中新增checkMiddleware, testMiddleware  两个中间件,其中checkMiddleware, testMiddleware为中间件名称。


    middleware: CheckMiddleware, TestMiddleware  

        之前说过, server修饰的是其紧挨的service 块,因此在server块中新增中间件,会为其紧挨的service 块中的每个接口都增加中间件checkMiddleware, testMiddleware,因此,请注意作用域,如何部分接口不需要中间件,请分开定义。

2. 执行命令
 

goctl api go -api ./api/demo.api -dir . -style gozero

  生成关于中间件部分的代码主要如下:

3. 编写中间件逻辑代码

        接下来就可以在Handle函数中添加对应的逻辑了,在next(w, r)前后都可以添加,

package middleware

import "net/http"

type CheckMiddleware struct {
}

func NewCheckMiddleware() *CheckMiddleware {
	return &CheckMiddleware{}
}

func (m *CheckMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// TODO generate middleware implement function, delete after code implementation

		// Passthrough to next handler if need

		/******
		请求到来后需要执行的代码
		代码块a
		*/

		next(w, r)

		/******
		请求返回时需要执行的代码
		代码块A
		*/
	}
}

package middleware

import "net/http"

type TestMiddleware struct {
}

func NewTestMiddleware() *TestMiddleware {
	return &TestMiddleware{}
}

func (m *TestMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// TODO generate middleware implement function, delete after code implementation

		// Passthrough to next handler if need
		/******
		请求到来后需要执行的代码
		代码块b
		*/
		
		next(w, r)
		
		/******
		请求返回时需要执行的代码
		代码块B
		*/
	}
}

        如果你需要外部传递参数,可以在对应的结构体中添加,如在TestMiddleware 结构体中添加变量,并在New函数中传入

type TestMiddleware struct {
	Num   int
	Class string
}

func NewTestMiddleware(num int, class string) *TestMiddleware {
	return &TestMiddleware{
		Num:   num,
		Class: class,
	}
}

4. 修改servicecontext.go文件

通过函数间的调用关系,可以发现,中间件中的Handle函数是在servicecontext.go被调用的。

type ServiceContext struct {
	Config          config.Config
	CheckMiddleware rest.Middleware
	TestMiddleware  rest.Middleware
	DemoRpc         demo.DemoClient
}

func NewServiceContext(c config.Config) *ServiceContext {
	return &ServiceContext{
		Config:          c,
		CheckMiddleware: middleware.NewCheckMiddleware().Handle,
		TestMiddleware:  middleware.NewTestMiddleware(5, "rongyu").Handle,
		DemoRpc:         demo.NewDemoClient(zrpc.MustNewClient(c.DemoRpcConf).Conn()),
	}
}

        如果,你对中间件的结构体进行了修改,新增了变量,则需要修改上述代码的NewTestMiddleware处将值传进去。

        通过阅读代码可以发现,中间件在ServiceContext 中定义,在main函数中初始化,随后被传入到RegisterHandlers中使用。

func main() {
	flag.Parse()

	var c config.Config
	conf.MustLoad(*configFile, &c)

	server := rest.MustNewServer(c.RestConf)
	defer server.Stop()

	ctx := svc.NewServiceContext(c)
	handler.RegisterHandlers(server, ctx)

	fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
	server.Start()
}


func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
	server.AddRoutes(
		rest.WithMiddlewares(
			[]rest.Middleware{serverCtx.CheckMiddleware, serverCtx.TestMiddleware},
			[]rest.Route{
				{
					Method:  http.MethodPost,
					Path:    "/Info/get",
					Handler: demo.GetInfoHandler(serverCtx),
				},
			}...,
		),
		rest.WithPrefix("/api/demo/v1"),
	)
}


5. 多个中间件的执行顺序

        在上述介绍中, 一共写了四段代码a、A、b、B,中间件的顺序是CheckMiddleware, TestMiddleware, 那么代码a、A、b、B的被执行的先后顺序是a、b、B、A。类似于一个U型仓,最底下是 next(w, r)。可以理解为前面是队列,后面是栈。


http://www.kler.cn/a/558944.html

相关文章:

  • Windows系统第一次运行C语言程序,环境配置,软件安装等遇到的坑及解决方法
  • 嵌入式之内存管理
  • 【2025.2最新版】从零开始的HTML网页开发学习笔记(包含网页基础概念 HTML语法 前端工具VsCode介绍)
  • mysql之B+ 树索引 (InnoDB 存储引擎)机制
  • 反射和注解
  • 自制操作系统前置知识汇编学习
  • 实验-安装Proteus
  • ZLMediaKi集群设置
  • 简说spring 的设计模式
  • Python项目源码33:待办事项列表应用2.0(命令行界面+Json+类)
  • Java基础常见的面试题(易错!!)
  • QT闲记-状态栏,模态对话框,非模态对话框
  • 485. 最大连续 1 的个数
  • 【CI/CD】Jenkinsfile管理+参数化构建+邮件通知以及Jenkins + SonarQube 代码审查
  • 【数据库维护】如何解决Clickhouse数据库Too many parts报错
  • 当“欲望号街车”遇阻:解锁自由的疯狂选择题
  • 【C语言】指针(5)
  • 回合制文字版格斗游戏(类的运用)
  • 复刻Dummy机械臂保姆教程
  • 二、Spring Framework基础:IoC(控制反转)和DI(依赖注入)