进阶 www.iris-go.com 2026-10-20 02:39:14 · 12 阅读
第3章 从上下文注册依赖
从上下文注册依赖项 当你想创建一个 iris.Handler 形式的中间件,同时又想为潜在的(MVC)Controller 方法或依赖注入 handler 绑定任意输入参数时,ctx.RegisterDependency 就是让你在请求时构建并添加依赖项的方法。go// RegisterDependency 在请求时注册一个 struct、slice
// 或指向 struct 的指针类型的依赖项,
// 供链路中的下一个 handler 使用。每种类型只能有一个值。
// 注意:强烈建议在服务器启动前,
// 通过 Party.ConfigureContainer 或 mvc.Application.Register
// 注册依赖项,以获得最小性能开销。
RegisterDependency(v interface{})
// UnregisterDependency 根据类型移除一个依赖项。
// 返回该类型的依赖项是否被成功找到并移除。
UnregisterDependency(typ reflect.Type) bool1
2
3
4
5
6
7
8
9
10
11
12
我们先为假想中的应用创建一个自定义中间件。go// Role struct 值示例。 type Role struct { Name string } const roleContextKey = "myapp.role" // RoleMiddleware 自定义中间件示例。 func RoleMiddleware(ctx iris.Context) { // [自行实现:从请求中提取角色...] if ctx.URLParam("name") != "kataras" { ctx.StopWithStatus(iris.StatusUnauthorized) return } // role := Role{Name: "admin"} // 将 role 值共享给后续的 handler。 ctx.Values().Set(roleContextKey, role)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
当你能直接操作中间件本身时:使用 RegisterDependency 在请求时把 struct 类型的值注册为依赖项,供任何需要依赖注入的用户 handler 使用。这样,使用你中间件的用户就不必再通过调用 APIContainer.RegisterDependency(和 mvc.Application.Register)来手动注册 Role 类型的依赖项了。go ctx.RegisterDependency(role)1
go ctx.Next() }1
2
go// GetRole 从 context values 中获取角色, // 需先执行 `roleMiddleware`。 func GetRole(ctx iris.Context) (Role, bool) { v := ctx.Values().Get(roleContextKey) if v != nil { if role, ok := v.(Role); ok { return role, true } } return Role{}, false }1
2
3
4
5
6
7
8
9
10
11
12
现在可以使用我们的 RoleMiddleware 了,包括一个通用的 `iris.Handler` 以及一个接受一个或多个依赖项的 handler。创建 main.go 文件并粘贴以下代码: ```go package main import "github.com/kataras/iris/v12" func main() { app := iris.New() app.Use(RoleMiddleware) app.Get("/", commonHandler) c := app.ConfigureContainer() c.RegisterDependency(func(ctx iris.Context) Role { role, ok := GetRole(ctx) if !ok { // 这里永远不会执行到这段代码 // 但你可以通过以下方法阻止 // 依赖该依赖项的 handler 继续执行 // 使用 `ctx.StopExecution` / `ctx.StopWithXXX` 方法 // 或者返回一个 `error` 类型的第二个输出参数 ctx.StopExecution() return Role{} } return role }) c.Get("/dep", handlerWithDependencies) // http://localhost:8080?name=kataras // http://localhost:8080/dep?name=kataras app.Listen(":8080") } func commonHandler(ctx iris.Context) { role, _ := GetRole(ctx) ctx.WriteString(role.Name) } func handlerWithDependencies(role Role) string { return role.Name } ``` 当你无法访问中间件代码本身时,可以注册一个请求依赖项,该依赖项从 Context 中获取值并返回,使得 Type 为 Role 的 handler 或函数的输入参数可以进行绑定。 这就是全部了。
2
3
4
5
6
7
8
9
10
11
12
我们先为假想中的应用创建一个自定义中间件。go// Role struct 值示例。 type Role struct { Name string } const roleContextKey = "myapp.role" // RoleMiddleware 自定义中间件示例。 func RoleMiddleware(ctx iris.Context) { // [自行实现:从请求中提取角色...] if ctx.URLParam("name") != "kataras" { ctx.StopWithStatus(iris.StatusUnauthorized) return } // role := Role{Name: "admin"} // 将 role 值共享给后续的 handler。 ctx.Values().Set(roleContextKey, role)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
当你能直接操作中间件本身时:使用 RegisterDependency 在请求时把 struct 类型的值注册为依赖项,供任何需要依赖注入的用户 handler 使用。这样,使用你中间件的用户就不必再通过调用 APIContainer.RegisterDependency(和 mvc.Application.Register)来手动注册 Role 类型的依赖项了。go ctx.RegisterDependency(role)1
go ctx.Next() }1
2
go// GetRole 从 context values 中获取角色, // 需先执行 `roleMiddleware`。 func GetRole(ctx iris.Context) (Role, bool) { v := ctx.Values().Get(roleContextKey) if v != nil { if role, ok := v.(Role); ok { return role, true } } return Role{}, false }1
2
3
4
5
6
7
8
9
10
11
12
现在可以使用我们的 RoleMiddleware 了,包括一个通用的 `iris.Handler` 以及一个接受一个或多个依赖项的 handler。创建 main.go 文件并粘贴以下代码: ```go package main import "github.com/kataras/iris/v12" func main() { app := iris.New() app.Use(RoleMiddleware) app.Get("/", commonHandler) c := app.ConfigureContainer() c.RegisterDependency(func(ctx iris.Context) Role { role, ok := GetRole(ctx) if !ok { // 这里永远不会执行到这段代码 // 但你可以通过以下方法阻止 // 依赖该依赖项的 handler 继续执行 // 使用 `ctx.StopExecution` / `ctx.StopWithXXX` 方法 // 或者返回一个 `error` 类型的第二个输出参数 ctx.StopExecution() return Role{} } return role }) c.Get("/dep", handlerWithDependencies) // http://localhost:8080?name=kataras // http://localhost:8080/dep?name=kataras app.Listen(":8080") } func commonHandler(ctx iris.Context) { role, _ := GetRole(ctx) ctx.WriteString(role.Name) } func handlerWithDependencies(role Role) string { return role.Name } ``` 当你无法访问中间件代码本身时,可以注册一个请求依赖项,该依赖项从 Context 中获取值并返回,使得 Type 为 Role 的 handler 或函数的输入参数可以进行绑定。 这就是全部了。