
使用 Iris MVC 重构代码。
通过创建彼此独立的组件,开发人员可以在其他应用程序中快速轻松地重用组件。 可以将一个应用程序的相同(或相似)视图重构为具有不同数据的另一个应用程序,因为该视图只是处理数据向用户显示的方式。
Iris 拥有 **对MVC(模型视图控制器)架构模式的一流支持**, 在Go世界中其他任何地方都找不到这些东西。 你必须要引入 [iris/mvc](https://github.com/kataras/iris/tree/master/mvc) 子包。
```
import "github.com/kataras/iris/v12/mvc"
```
Iris Web 框架以最快的执行速度支持请求数据,模型,持久性数据和绑定。
如果你不熟悉 Web 后台开发, 请先阅读MVC架构模式,这是一个很好的开始。 [wikipedia article](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller).
**特点**
支持所有 HTTP 方法,例如, 如果要提供`GET` 服务, 则控制器应具有一个名为 `Get()`的函数,你可以在同一控制器中定义多个方法函数。
每个控制器可以通过 `BeforeActivation` 自定义回调事件,自定义控制器的 struct 的方法用作具有自定义路径(甚至带有regex参数化的路径)的处理程序。 例如:
```
import (
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/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-> 将控制器的函数名称解析为处理程序
// 4-> 应该在 MyCustomHandler 之前运行的任何处理程序
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"
}
```
在你的控制器结构体中持久化数据(在请求之间共享数据),通过定义依赖的服务或者一个`单列` 控制器作用域。
共享控制器之间的依赖关系或在父 MVC 应用程序上注册它们, 并能够在Controller内部的`BeforeActivation`可选事件回调上修改每个控制器的依赖关系, 即, `func(c *MyController) BeforeActivation(b mvc.BeforeActivation) { b.Dependencies().Add/Remove(...) }`。
一个控制器字段访问 `Context`(不需要手动绑定), 即 `Ctx iris.Context` 或者通过一个 方法的输入参数。 即 `func(ctx iris.Context, otherArguments...)`。
控制器结构内部的模型(在Method函数中设置并由View呈现)。你可以从控制器的方法返回模型,或者在请求生命周期中设置一个字段,然后将该字段返回到同一请求生命周期中的另一个方法。
接下来如同你前面所知的一样, mvc 应用有它自己的 `路由` ,它的路由是 `iris/router.Party`类型之一,同时也是标准的 iris api 。 `控制器`可以被注册到任何的 `Party`中,也包括子域, Party 将会如同期望的那样开始和执行处理程序的工作。
可选的 `BeginRequest(ctx)` 函数,将会执行任何初始化在方法执行前,可用于调用中间件或许多方法使用相同的数据集合时。
可选的 `EndRequest(ctx)` 函数, 将会执行任何终止操作在所有的方法执行之后。
继承,递归, 我 [mvc session-controller example](https://github.com/kataras/iris/tree/master/_examples/mvc/session-controller), 有 `Session *sessions.Session` 作为结构体字段, 它被会话管理的 `Start` 方法作为一个动态以来想填充到 MVC 应用: `mvcApp.Register(sessions.New(sessions.Config{Cookie: "iris_session_id"}).Start)`.
通过控制器方法的输入参数访问动态路径参数,无需绑定。 当你使用 Iris 的默认语法从一个控制器中去解析处理程序 , 你需要给方法添加 `By` 后缀, 大写字母是一个新的子路径。 例如:
如果 `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。
可选的, 通过输出参数响应,就如通我们在这章 [Dependency Injection](https://github.com/kataras/iris/wiki/dependency-injection) 内容中所展示的那样。 例如。
```
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` 是 `hero.Result` 类型的一个别名, 同时它也是一个接口。
```
type Result interface {
// Dispatch 应该发送响应到 context 的响应编写器中。
Dispatch(ctx iris.Context)
}
```
## [示例](https://github.com/kataras/iris/wiki/MVC#example)
此示例等效于 <https://github.com/kataras/iris/blob/master/_examples/hello-world/main.go>
你需要添加代码,这看上去似乎有些得不偿失。但请记住,这个例子并没有使用 iris mvc 的模型, Persistence 或者视图引擎还有 Session 等功能。它仅仅是一个为学习准备的简单例子,你可能永远都不会在你的应用程序中使用如此简单的控制器。
在此示例中,在我的个人笔记本电脑上使用 MVC 模式,在"/hello" 路径上服务每 20MB JSON 的成本是 ~2MB 。
虽然这对于大多数应用程序来说是已经足够,但你还可以选择最适合你的 Iris 功能组合,低级处理程序: 性能更好或者高级控制器: 在大项目中更容易管理和简化代码。
**请仔细阅读注释**
```
package main
import (
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/mvc"
"github.com/kataras/iris/v12/middleware/logger"
"github.com/kataras/iris/v12/middleware/recover"
)
func main() {
app := iris.New()
// 可选的,增加两个内置处理程序
// 可以从任何 http 相对的恐慌中恢复
// 和将请求记录到终端。
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 服务
// 方法: GET
// 资源: http://localhost:8080
func (c *ExampleController) Get() mvc.Result {
return mvc.Response{
ContentType: "text/html",
Text: "<h1>Welcome</h1>",
}
}
// GetPing 服务
// 方法: GET
// 资源: http://localhost:8080/ping
func (c *ExampleController) GetPing() string {
return "pong"
}
// GetHello 服务
// 方法: GET
// 资源: http://localhost:8080/hello
func (c *ExampleController) GetHello() interface{} {
return map[string]string{"message": "Hello Iris!"}
}
// BeforeActivation 只调用一次, 在控制器适应主应用程序前
// 当然也是在主程序运行前。
// 在版本 9 之后,你还可以为特定控制器的方法添加自定义路由。
// 这里你也可以不使用 mvc , 只通过 `ca.Router` 函数使用标准的路由去
// 注册自定义方法的处理程序去做一些事情。
// 并且增加绑定到控制器的字段或者方法函数输入参数上的依赖项。
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 服务
// 方法: GET
// 资源: http://localhost:8080/custom_path
func (c *ExampleController) CustomHandlerWithoutFollowingTheNamingGuide() string {
return "hello from the custom handler without following the naming guide"
}
// GetUserBy 服务
// 方法: GET
// 资源: 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 -> 此控制器的方法名称,该名称应为此路由的处理程序。
b.Handle("GET", "/mypath/{param}", "DoIt", optionalMiddlewareHere...)
}
// 激活之后, 所有依赖都被设置为 -ed - 所以它们都是只读的。
// 但是任然也可以增加自定义控制器或者简单的标准处理程序。
func (c *ExampleController) AfterActivation(a mvc.AfterActivation) {}
*/
```
在控制其中,每个以 HTTP 方法(`Get`, `Post`, `Put`, `Delete`...)为前缀的 `导出的` 函数,都可作为 HTTP 端点调用。在上面的例子中, ,所有函数都将字符串写入响应。注意每种方法之前的注释。
一个 HTTP 端点是一个Web应用程序中的可定位 URL, 例如`http://localhost:8080/helloworld`,它结合所使用的协议: HTTP,Web服务器的网络位置(包括 TCP 端口): `localhost:8080` 和目标 URI `/helloworld`。
第一条注释指出这是一种[HTTP GET](https://www.w3schools.com/tags/ref_httpmethods.asp) 方法,该方法通过在基本 URL 后面附加 "/helloworld" 来调用。 第三条注释指定一个 [HTTP GET](https://www.w3schools.com/tags/ref_httpmethods.asp) 方法, 该方法通过在 URL 后面附加 "/helloworld/welcome" 来调用。
因为 `By` 关键字,控制器知道如何去处理 `GetBy`上的 "name" 参数 或者 `GetWelcomeBy`上的 "name" 和 "numTimes" 参数,并且构建无样板的动态路由;第三个注释指定一个 [HTTP GET](https://www.w3schools.com/tags/ref_httpmethods.asp) 动态方法,它由任何以"/helloworld/welcome" 开头并且跟随两个路径部分的 URL 调用。第一个部分可以接受任何值并且第二部分只能接受数字,即: "<http://localhost:8080/helloworld/welcome/golang/32719>", 否则,一个 [404 Not Found HTTP 错误](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5) 将会被发送到客户端。
> [_examples/mvc](https://github.com/kataras/iris/tree/master/_examples/mvc) 和 [mvc/controller_test.go](https://github.com/kataras/iris/blob/master/mvc/controller_test.go) 文件 用简单的范例解释每个功能, 它们展示了你要如何采用 Iris MVC Binder, Iris MVC Models 和更多其它内容...
> 对于 Websocket 控制器,请访问 [Websockets](https://github.com/kataras/iris/wiki/Websockets) 章节。
