goframe项目详解(基于开源项目 易理解)(五)

上一篇我们讲解了goframe的share文件夹的请求上下文绑定 

goframe项目详解(基于开源项目 易理解)(四)-CSDN博客

接下来我们讲解system目录:

app/system/admin.go文件

package admin

import (
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
)

// 后台系统初始化
func Init() {
	// 后台系统路由注册
	g.Server().Group("/admin", func(group *ghttp.RouterGroup) {
		// 暂未开放。
	})
}

定义了一个名为 admin 的包,其中包含一个 Init 函数。

Init 函数的作用是在 g.Server() 中为 /admin 路径注册一个路由组。不过在当前的代码中,这个路由组内暂时没有添加具体的路由处理逻辑,只是有一个注释表明暂未开放

g.Server().Group("/admin", func(group *ghttp.RouterGroup) {
		// 暂未开放。
	})

g.Server().Group("/admin", func(group *ghttp.RouterGroup)) 中第二个参数是一个匿名函数,该函数接收一个 *ghttp.RouterGroup 类型的参数 group

在这个匿名函数内部,可以使用传入的 group 对象来进一步配置和注册该分组下的路由。例如,可以使用 group.GETgroup.POST 等方法来添加具体的路由处理函数,或者使用其他方法来设置中间件、进行路由绑定等操作。

这段代码使用 g.Server().Group 方法创建了一个以 /admin 为前缀的路由组。但目前这个路由组内部还没有添加具体的路由处理逻辑,只是有一个注释说明暂未开放。

在后续的开发中,可以在这个闭包内部使用 group 对象添加各种具体的路由处理函数,例如:

g.Server().Group("/admin", func(group *ghttp.RouterGroup) {
    group.GET("/dashboard", func(r *ghttp.Request) {
        // 处理 /admin/dashboard 的 GET 请求
    })
})

接下来我们看app/system/index.go这个文件,看看这个路由


package index

import (
	"focus/app/system/index/internal/api"
	"focus/app/system/index/internal/service"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/text/gstr"
)

// 前台系统初始化
func Init() {
	s := g.Server()

	// 前台系统自定义错误页面
	s.BindStatusHandler(401, func(r *ghttp.Request) {
		if !gstr.HasPrefix(r.URL.Path, "/admin") {
			service.View.Render401(r)
		}
	})
	s.BindStatusHandler(403, func(r *ghttp.Request) {
		if !gstr.HasPrefix(r.URL.Path, "/admin") {
			service.View.Render403(r)
		}
	})
	s.BindStatusHandler(404, func(r *ghttp.Request) {
		if !gstr.HasPrefix(r.URL.Path, "/admin") {
			service.View.Render404(r)
		}
	})
	s.BindStatusHandler(500, func(r *ghttp.Request) {
		if !gstr.HasPrefix(r.URL.Path, "/admin") {
			service.View.Render500(r)
		}
	})

	// 前台系统路由注册
	s.Group("/", func(group *ghttp.RouterGroup) {
		group.Middleware(service.Middleware.Ctx)
		group.ALLMap(g.Map{
			"/":            api.Index,          // 首页
			"/login":       api.Login,          // 登录
			"/register":    api.Register,       // 注册
			"/category":    api.Category,       // 栏目
			"/topic":       api.Topic,          // 主题
			"/topic/:id":   api.Topic.Detail,   // 主题 - 详情
			"/ask":         api.Ask,            // 问答
			"/ask/:id":     api.Ask.Detail,     // 问答 - 详情
			"/article":     api.Article,        // 文章
			"/article/:id": api.Article.Detail, // 文章 - 详情
			"/reply":       api.Reply,          // 回复
			"/search":      api.Search,         // 搜索
			"/captcha":     api.Captcha,        // 验证码
			"/user/:id":    api.User.Index,     // 用户 - 主页
		})
		// 权限控制路由
		group.Group("/", func(group *ghttp.RouterGroup) {
			group.Middleware(service.Middleware.Auth)
			group.ALLMap(g.Map{
				"/user":     api.User,     // 用户
				"/content":  api.Content,  // 内容
				"/interact": api.Interact, // 交互
				"/file":     api.File,     // 文件
			})
		})
	})
}


​

定义了一个名为 index 的包,其中的 Init 函数用于初始化前台系统的相关设置和路由。

以下是对代码的详细解释:

  1. 首先获取 g.Server 对象 s 。
  2. 为一些特定的错误状态码(401、403、404、500)绑定了处理函数。这些处理函数会根据请求的路径是否以 /admin 开头来决定是否调用 service.View 中的相应方法来渲染自定义的错误页面。
  3. 为根路径 / 注册了一个路由组。
    • 为该路由组设置了 service.Middleware.Ctx 中间件。
    • 定义了一系列的路由和对应的处理函数(api 包中的相应方法)。
    • 又创建了一个子路由组,为其设置了 service.Middleware.Auth 中间件,并定义了一些需要权限控制的路由及对应的处理函数。

总的来说,这段代码完成了前台系统的错误处理和路由的注册与配置。

func Init() {
	s := g.Server()

定义了一个名为 Init 的函数,在这个函数内部获取了 g.Server() 的实例并将其赋值给变量 s

问题:g.Server()是什么?

在 GoFrame 框架中,g.Server() 用于获取默认的 HTTP 服务器实例。

通过这个服务器实例,可以进行各种配置,如设置路由、中间件、监听端口、处理请求等操作,以构建和启动一个完整的 HTTP 服务。

s.BindStatusHandler(401, func(r *ghttp.Request) {
		if !gstr.HasPrefix(r.URL.Path, "/admin") {
			service.View.Render401(r)
		}
	})

为 HTTP 服务器设置状态码为 401(未授权)的处理函数。

当服务器接收到状态码为 401 的响应,并且请求的 URL 路径不以 /admin 开头时,就会调用 service.View.Render401(r) 来处理这个请求。

这通常用于在特定条件下为未授权的请求提供自定义的 401 错误页面或执行特定的错误处理逻辑。

s.Group("/", func(group *ghttp.RouterGroup) {
		group.Middleware(service.Middleware.Ctx)
		group.ALLMap(g.Map{
			"/":            api.Index,          // 首页
			"/login":       api.Login,          // 登录
			"/register":    api.Register,       // 注册
			"/category":    api.Category,       // 栏目
			"/topic":       api.Topic,          // 主题
			"/topic/:id":   api.Topic.Detail,   // 主题 - 详情
			"/ask":         api.Ask,            // 问答
			"/ask/:id":     api.Ask.Detail,     // 问答 - 详情
			"/article":     api.Article,        // 文章
			"/article/:id": api.Article.Detail, // 文章 - 详情
			"/reply":       api.Reply,          // 回复
			"/search":      api.Search,         // 搜索
			"/captcha":     api.Captcha,        // 验证码
			"/user/:id":    api.User.Index,     // 用户 - 主页
		})

这段代码是在根路径 `"/"` 下创建了一个路由组,并进行了以下配置:

1. 为该路由组设置了名为 `service.Middleware.Ctx` 的中间件。

2. 使用 `ALLMap` 方法定义了一系列的路由及其对应的处理函数:

- `"/"` 对应 `api.Index` ,可能是首页的处理函数。

- `"/login"` 对应 `api.Login` ,登录页面的处理函数。

- `"/register"` 对应 `api.Register` ,注册页面的处理函数。

- 以此类推,为不同的路由路径指定了相应的处理逻辑。 通过这种方式,将相关的路由及其处理函数组织在一起,方便管理和维护。

其中

func(group *ghttp.RouterGroup) 是一个匿名函数的定义。

在这里,它被作为参数传递给 g.Server().Group 方法。这个匿名函数接收一个 *ghttp.RouterGroup 类型的参数 group ,在这个函数内部,可以使用 group 来配置路由组的相关设置,比如添加中间件、定义路由及其处理函数等。

再问细一点:s.Group("/", func(group *ghttp.RouterGroup) 这个匿名函数func(group *ghttp.RouterGroup) 的作用是什么?

在这段代码中,`func(group *ghttp.RouterGroup)` 是一个匿名函数,它的作用是定义分组路由的相关设置。 具体来说,通过 `s.group("/", func(group *ghttp.RouterGroup) {...})` 语句创建了一个根路径(`/`)的路由分组。在这个匿名函数内部,可以进行以下操作:

1. 设置中间件:使用 `group.middleware(middleware.middlewareHandlerResponse)` 为该分组路由设置中间件。中间件可以在处理请求之前或之后执行一些额外的逻辑,例如身份验证、日志记录、数据处理等。

2. 绑定控制器或处理函数:使用 `group.bind(controller)` 将控制器或处理函数与路由路径进行绑定。这样,当访问匹配该路由路径的请求时,就会调用相应的控制器方法或处理函数来处理请求。 通过这种方式,可以将相关的路由路径和处理逻辑组织在一个分组中,便于管理和维护路由配置,同时可以为分组内的路由统一应用中间件等设置。

这种分组路由的设计有助于提高代码的结构清晰度和可维护性,特别是在大型项目中,当路由数量较多时,可以更方便地对不同功能或模块的路由进行分类和管理。 例如,在上述代码的具体示例中,为 `/app/demo/open/welcome` 和 `/app/demo/comm/show` 这两个路由路径分别绑定了相应的控制器方法,并为分组路由设置了一个名为 `middlewareHandlerResponse` 的中间件。当访问这两个路径的请求到达时,会先执行中间件的逻辑,然后再执行对应的控制器方法。

问题:group.Middleware(service.Middleware.Ctx)为什么传参要传入ctx,ctx是什么?

在 GoFrame 框架中,`group.Middleware(service.Middleware.Ctx)` 这样的写法通常用于注册中间件到分组路由中。 `ctx` 是 `context.Context` 类型的对象,它用于在 GoFrame 应用中传递上下文信息。

    `context.Context` 是 Go 语言标准库中用于在 goroutine 之间传递请求作用域特定的值、取消信号和截止时间等元数据的类型。 在 Web 应用中,`ctx` 可以包含与当前请求相关的各种信息,例如用户身份验证信息、请求的截止时间、跟踪请求的标识等。通过将 `ctx` 传递给中间件,中间件可以访问和操作这些上下文信息,以实现各种功能,例如权限验证、日志记录、处理请求的超时等。 具体来说,当使用 `group.Middleware(service.Middleware.Ctx)` 注册中间件时,`service.Middleware.Ctx` 可能是一个已经创建或配置好的包含特定上下文信息的对象。将其传递给中间件,使得中间件能够基于这个上下文进行相应的处理。 中间件可以根据 `ctx` 中的信息做出决策,执行特定的逻辑,并可能修改请求的处理流程或响应的内容。多个中间件可以按照注册的顺序依次执行,形成一个中间件链,共同处理请求。

例如,在一个 Web 服务中,可能有一个验证用户身份的中间件,它可以从 `ctx` 中获取用户身份信息进行验证;还有一个记录请求日志的中间件,它可以使用 `ctx` 中的相关数据来记录详细的请求日志。

这样,通过使用 `ctx` 传递上下文信息,使得中间件能够更加灵活地处理请求,并在不同的中间件之间共享和传递相关的状态和数据,从而实现更复杂和可扩展的 Web 应用逻辑。不同的中间件可以根据 `ctx` 中的信息执行各自特定的任务,协同完成整个请求的处理过程。

	group.ALLMap(g.Map{
			"/":            api.Index,          // 首页
			"/login":       api.Login,          // 登录
			"/register":    api.Register,       // 注册
			"/category":    api.Category,       // 栏目
			"/topic":       api.Topic,          // 主题
			"/topic/:id":   api.Topic.Detail,   // 主题 - 详情
			"/ask":         api.Ask,            // 问答
			"/ask/:id":     api.Ask.Detail,     // 问答 - 详情
			"/article":     api.Article,        // 文章
			"/article/:id": api.Article.Detail, // 文章 - 详情
			"/reply":       api.Reply,          // 回复
			"/search":      api.Search,         // 搜索
			"/captcha":     api.Captcha,        // 验证码
			"/user/:id":    api.User.Index,     // 用户 - 主页
		}

在 GoFrame 框架中使用 `group.ALLMap` 方法注册一系列的路由和对应的处理函数。 具体解释如下:

`group.ALLMap` 可能是用于注册多种 HTTP 方法(如 GET、POST、PUT 等)对应的路由`g.Map` 是一个映射(map),其中的键是路由路径(如 `"/"`、`"/login"` 等),值是对应的处理函数(如 `api.Index`、`api.Login` 等)。

例如,`"/"` 路径对应的处理函数是 `api.Index`,`"/login"` 路径对应的处理函数是 `api.Login`,以此类推。 这意味着当客户端向服务器发送匹配这些路径的请求时,相应的处理函数将被调用以处理请求并生成响应。

我们接着往下看:

	group.Group("/", func(group *ghttp.RouterGroup) {
			group.Middleware(service.Middleware.Auth)
			group.ALLMap(g.Map{
				"/user":     api.User,     // 用户
				"/content":  api.Content,  // 内容
				"/interact": api.Interact, // 交互
				"/file":     api.File,     // 文件
			})
		})

在 GoFrame 框架中定义了一个路由分组。 `group.Group("/", func(group *ghttp.RouterGroup) {...})` 表示创建了一个以 `"/"` 为根路径的路由分组,并在这个分组内定义了相关的路由和中间件。 在分组内,首先设置了一个中间件 `service.Middleware.Auth`,这意味着访问这个分组下的路由时都会先经过这个中间件的处理。 然后通过 `group.ALLMap(g.Map{...})` 注册了多个路由及其对应的处理函数。例如,`"/user"` 路径对应的处理函数是 `api.User`,`"/content"` 路径对应的处理函数是 `api.Content` 等等。 总的来说,这段代码实现了对一组相关路由的组织和配置,包括中间件的应用和路由与处理函数的绑定。

问题:func(group *ghttp.RouterGroup)是什么?

func(group *ghttp.RouterGroup) 是一个定义了函数的表达式,它表示定义了一个名为 func 的函数,该函数接收一个参数 group,参数的类型是 *ghttp.RouterGroup

ghttp.RouterGroup 通常是 GoFrame 框架中用于路由分组管理的一个结构体。通过接收 *ghttp.RouterGroup 类型的参数,函数可以对路由组进行操作,例如注册路由、添加中间件、设置其他与路由相关的配置等。

在 GoFrame 框架中,使用路由组可以更方便地组织和管理相关的路由。例如,可以在一个路由组中设置共同的中间件,或者将具有相似功能或特性的路由放在同一个组中进行统一处理。

在你提供的代码示例中,s.group("/", func(group *ghttp.RouterGroup) {...}) 创建了一个以 "/" 为根路径的路由分组,并在该匿名函数内部对这个路由组进行了进一步的配置,比如添加中间件 group.Middleware(service.Middleware.Auth) 和注册路由 group.ALLMap(g.Map{...}) 等操作。这样可以将与根路径相关的路由和处理逻辑集中在一起进行管理。

问题:都有哪些路由器中间件?

大家可以看一下这篇文章

goframe常见的路由器中间件-CSDN博客

  • 15
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值