MVC 架构
Iris 对 MVC (Model View Controller) 模式有着非常好的支持,这是其它 go 语言框架所不具备。
Iris Web 框架支持以最快的方式执行,请求数据、模型、持久性数据和绑定。
特点
支持所有 HTTP 方法, 例如,如果想要写一个 GET
那么在控制器中也要写一个 Get()
函数,你可以在一个控制器内定义多个函数。
每个控制器通过 BeforeActivation
自定义事件回调,用来自定义控制器的结构的方法与自定义路径处理程序(甚至有正则表达式路径)。 例子:
import (
"github.com/kataras/iris"
"github.com/kataras/iris/mvc"
)
func main() {
app := iris.New()
mvc.Configure(app.Party("/root"), myMVC)
app.Run(iris.Addr(":8080"))
}
func myMVC(app *mvc.Application) {
// app.Register(...)
// app.Router.Use/UseGlobal/Done(...)
app.Handle(new(MyController))
}
type MyController struct {}
func (m *MyController) BeforeActivation(b mvc.BeforeActivation) {
// b.Dependencies().Add/Remove
// b.Router().Use/UseGlobal/Done // 和你已知的任何标准 API 调用
// 1-> 方法
// 2-> 路径
// 3-> 控制器函数的名称将被解析未一个处理程序 [ handler ]
// 4-> 任何应该在 MyCustomHandler 之前运行的处理程序[ handlers ]
b.Handle("GET", "/something/{id:long}", "MyCustomHandler", anyMiddleware...)
}
// GET: http://localhost:8080/root
func (m *MyController) Get() string { return "Hey" }
// GET: http://localhost:8080/root/something/{id:long}
func (m *MyController) MyCustomHandler(id int64) string { return "MyCustomHandler says Hey" }
通过定义一个附属的服务范围或者一个 Singleton
控制器范围,来实现控制器结构内部数据的持久化(在请求之间共享数据)。
在控制器之间共享依赖关系或者在父 MVC 应用程序上注册它们,以及在控制器里通过 BeforeActivation
可选回调事件,都可以修改每个控制器的依赖关系。 如 func(c *MyController) BeforeActivation(b mvc.BeforeActivation) { b.Dependencies().Add/Remove(...) }
。
访问控制器的字段 Context
(不需要手动绑定)如 Ctx iris.Context
或者当作方法参数输入,如 func(ctx iris.Context, otherArguments...)
。
控制器内部结构模型(在方法函数中设置并由视图呈现)。你可以从控制器的方法中返回模型,或者在请求生命周期中设置字段,并在相同的请求生命周期中将该字段返回到另一个方法。
正如你以前用过的一样,MVC 应用程序有自己的 Router
,它是一个 iris/router.Party
类型的标准 iris api。当 iris/router.Party
如期望的那样开始执行处理程序的时候 , Controllers
可以注册到任意的 Party
,包括子域。
BeginRequest(ctx)
是一个可选函数,经常用在方法执行前,执行一些初始化操作,当调用中间件或者有很多方法使用相同的数据集合的时候非常有用。
EndRequest(ctx)
是一个可选函数,经常用在方法执行后,执行一些初始化操作。
继承,递归,例如我们的 mvc.SessionController
,它有 Session *sessions.Session
和 Manager *sessions.Sessions
作为嵌入式字段,由 BeginRequest
加载, 这里. 这只是一个例子,你可以用使用管理器的 Start
返回的 sessions.Session
, 作为对 MVC 应用程序的动态依赖项。 如mvcApp.Register(sessions.New(sessions.Config{Cookie: "iris_session_id"}).Start)
.
通过控制器方法的输入参数访问动态路径参数,不需要绑定。当你使用 iris 的默认语法来解析控制器处理程序时,你需要在方法后加上 “.” 字符,大写字母是一个新的子路径。 例子:
如果 mvc.New(app.Party("/user")).Handle(new(user.Controller))
func(*Controller) Get()
-GET:/user
.func(*Controller) Post()
-POST:/user
.func(*Controller) GetLogin()
-GET:/user/login
func(*Controller) PostLogin()
-POST:/user/login
func(*Controller) GetProfileFollowers()
-GET:/user/profile/followers
func(*Controller) PostProfileFollowers()
-POST:/user/profile/followers
func(*Controller) GetBy(id int64)
-GET:/user/{param:long}
func(*Controller) PostBy(id int64)
-POST:/user/{param:long}
如果 mvc.New(app.Party("/profile")).Handle(new(profile.Controller))
func(*Controller) GetBy(username string)
-GET:/profile/{param:string}
如果 mvc.New(app.Party("/assets")).Handle(new(file.Controller))
func(*Controller) GetByWildard(path string)
-GET:/assets/{param:path}
方法函数接收器支持的类型: int,int64, bool 和 string。
可选的响应输出参数,如下:
func(c *ExampleController) Get() string |
(string, string) |
(string, int) |
int |
(int, string) |
(string, error) |
error |
(int, error) |
(any, bool) |
(customStruct, error) |
customStruct |
(customStruct, int) |
(customStruct, string) |
mvc.Result or (mvc.Result, error)
mvc.Result是一个只包含: Dispatch(ctx iris.Context)
的 接口。
范例
这个范例相当于 github.com/kataras/iris/blob/maste...
似乎你必须要编写额外的代码,这个并不值当,但请记住,这个范例没有使用 iris mvc 功能,如 Model,Persistence 或者 View 引擎甚至没有使用 Session,它如此简单只是对于学习目的来说的,可能在你应用程序的任何地方都不会使用这么简单的控制器。
在我的个人笔记本电脑上,在每个 20MB 吞吐量的 “/ hello” 路径上使用 MVC 的这个例子的成本是大约 2MB,这对于大多数应用程序都是可以容忍,但你可以选择最适合你的 Iris, 低级处理程序 (low-level handlers) :性能或者高级控制器(high-level controllers):在开发大型应用程序上更易于维护和更少的代码实现。
请仔细阅读注释
package main
import (
"github.com/kataras/iris"
"github.com/kataras/iris/mvc"
"github.com/kataras/iris/middleware/logger"
"github.com/kataras/iris/middleware/recover"
)
func main() {
app := iris.New()
//(可选)添加两个内置处理程序(handlers)
//可以从任何与 http 相关的恐慌(http-relative panics) 中恢复
//并将请求记录到终端。
app.Use(recover.New())
app.Use(logger.New())
// "/" 服务于一个基于根路由的控制器。
mvc.New(app).Handle(new(ExampleController))
// http://localhost:8080
// http://localhost:8080/ping
// http://localhost:8080/hello
// http://localhost:8080/custom_path
app.Run(iris.Addr(":8080"))
}
// ExampleController 服务于 "/", "/ping" and "/hello" 路由。
type ExampleController struct{}
// Get serves
// Method: GET
// Resource: http://localhost:8080
func (c *ExampleController) Get() mvc.Result {
return mvc.Response{
ContentType: "text/html",
Text: "<h1>Welcome</h1>",
}
}
// GetPing serves
// Method: GET
// Resource: http://localhost:8080/ping
func (c *ExampleController) GetPing() string {
return "pong"
}
// GetHello serves
// Method: GET
// Resource: http://localhost:8080/hello
func (c *ExampleController) GetHello() interface{} {
return map[string]string{"message": "Hello Iris!"}
}
// BeforeActivation 会被调用一次,在控制器适应主应用程序之前
// 并且当然也是在服务运行之前
// 在版本 9 之后,你还可以为特定控制器的方法添加自定义路由。
// 在这个控制器,你可以注册自定义方法的处理程序。
// 使用带有 `ca.Router` 的标准路由
// 在不适用 mvc 的情况下,你可以做任何你可以做的事情
// 并将添加的依赖项绑定到
// 一个控制器的字段或者方法函数的输入参数中。
func (c *ExampleController) BeforeActivation(b mvc.BeforeActivation) {
anyMiddlewareHere := func(ctx iris.Context) {
ctx.Application().Logger().Warnf("Inside /custom_path")
ctx.Next()
}
b.Handle(
"GET",
"/custom_path",
"CustomHandlerWithoutFollowingTheNamingGuide",
anyMiddlewareHere,
)
// 或者甚至可以添加基于这个控制器路由的全局中间件,
// 比如在这个例子里面的根路由 "/" :
// b.Router().Use(myMiddleware)
}
// CustomHandlerWithoutFollowingTheNamingGuide serves
// Method: GET
// Resource: http://localhost:8080/custom_path
func (c *ExampleController) CustomHandlerWithoutFollowingTheNamingGuide() string {
return "hello from the custom handler without following the naming guide"
}
// GetUserBy serves
// Method: GET
// Resource: http://localhost:8080/user/{username:string}
// By 是一个保留的“关键字”来告诉框架你要
// 在函数的输入参数中绑定路径参数,它也是
// 有助于在同一个控制器中拥有 "Get“ 和 "GetBy"。
//
// func (c *ExampleController) GetUserBy(username string) mvc.Result {
// return mvc.View{
// Name: "user/username.html",
// Data: username,
// }
// }
/*
在一个控制器中可以使用多个 HTTP 方法,工厂会
为每条路由注册正确的 HTTP 方法,你可以按需取消注释:
func (c *ExampleController) Post() {}
func (c *ExampleController) Put() {}
func (c *ExampleController) Delete() {}
func (c *ExampleController) Connect() {}
func (c *ExampleController) Head() {}
func (c *ExampleController) Patch() {}
func (c *ExampleController) Options() {}
func (c *ExampleController) Trace() {}
*/
/*
func (c *ExampleController) All() {}
// 或者
func (c *ExampleController) Any() {}
func (c *ExampleController) BeforeActivation(b mvc.BeforeActivation) {
// 1 -> HTTP 方法
// 2 -> 路由路径
// 3 -> 控制器的方法名称应该是该路由的处理程序(handlers)。
b.Handle("GET", "/mypath/{param}", "DoIt", optionalMiddlewareHere...)
}
//激活后,所有依赖项都被设置 - 因此只能访问它们
//但仍可以添加自定义控制器或者简单的标准处理程序(handlers)。
func (c *ExampleController) AfterActivation(a mvc.AfterActivation) {}
*/
在控制器中以 HTTP 方法(Get
,Post
,Put
,Delete
…)为前缀的每个 exported
函数都可以作为 HTTP 端点调用。 在上面的示例中,所有函数都写入一个字符串到响应中。 请注意每种方法之前的注释。
HTTP 端点是 Web 应用程序中的可定位 URL(例如 http://localhost:8080/helloworld
),并结合使用的协议:HTTP,Web 服务器的网络位置(包括 TCP 端口):localhost:8080
和目标 URI /helloworld
。
第一条评论声明是一个 HTTP GET 方法, 它通过将 “/helloworld” 附加到基本 URL 来调用。第三个注释指定了 HTTP GET 方法, 该方法通过将 “/helloworld/welcome” 附加到URL来调用。
控制器通过By
关键字知道如何处理 GetBy
方法中的 “name” 或者GetWelcomeBy
方法中的 “name” 和 “numTimes”, 并且在没有样板的情况下构建动态路由;第三条注释指定了一个 HTTP GET 动态方法 ,该方法被以 “/helloworld/welcome” 开头的任何URL调用, URL另外两个路径部分:第一个部分可以接受任何值,第二个部分只能接受数字,即:”localhost:8080/helloworld/welcome/g...“, 否则将会发送一个到 404 Not Found HTTP Error 客户端。
_examples/mvc 和 mvc/controller_test.go 文件用简单的范例解释来每个功能,它们展示了如何使用 Iris MVC Binder, Iris MVC Models 等等的优点…
对于 websocket 控制器请移步 Websockets 章节。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: