MVC 架构

file

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) 的  接口

范例

这个范例相当于 https://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 方法(GetPostPutDelete ...)为前缀的每个 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另外两个路径部分:第一个部分可以接受任何值,第二个部分只能接受数字,即:"http://localhost:8080/helloworld/welcome/g...", 否则将会发送一个到 404 Not Found HTTP Error 客户端。

_examples/mvcmvc/controller_test.go 文件用简单的范例解释来每个功能,它们展示了如何使用 Iris MVC Binder, Iris MVC Models 等等的优点...

对于 websocket 控制器请移步 Websockets 章节。

本文章首发在 LearnKu.com 网站上。
上一篇 下一篇
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~