MVC
Gerasimos (Makis) Maropoulos在6月11日编辑了本页面·12次修改
使用Iris MVC实现代码重用。
通过创建相互独立的组件,开发人员能够在其他应用程序中快速、轻松地重用组件。一个应用程序的相同(或类似)视图可以被重构为具有不同数据的另一个应用程序,因为视图只是处理如何向用户显示数据。
Iris对MVC (Model - View - Controller)架构模式提供了一流的支持,你在Go世界的任何地方都找不到这些东西。您必须导入iris/mvc子包。
import "github.com/kataras/iris/v12/mvc"
Iris web框架支持以最快的速度执行请求数据、模型、持久性数据和绑定。
如果您是后端web开发的新手,请首先阅读有关MVC体系结构模式的文章,wikipedia的那篇文章是一个很好的开始。
注意:在继续之前,请阅读依赖项注入部分。
特性
支持所有HTTP方法,例如,如果想要服务于GET,那么控制器应该有一个名为GET()的函数,您可以在同一个控制器中定义多个方法函数。
通过每个控制器激活前的自定义事件回调,将自定义控制器结构的方法作为具有自定义路径的处理程序(即使是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.Listen(":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
// and any standard Router API call you already know
// 1-> Method
// 2-> Path
// 3-> The controller's function name to be parsed as handler
// 4-> Any handlers that should run before the MyCustomHandler
b.Handle("GET", "/something/{id:int64}", "MyCustomHandler", anyMiddleware...)
}
// GET: http://localhost:8080/root
func (m *MyController) Get() string {
return "Hey"
}
// GET: http://localhost:8080/root/something/{id:int64}
func (m *MyController) MyCustomHandler(id int64) string {
return "MyCustomHandler says Hey"
}
在控制器结构内的持久性数据(在请求之间共享数据),通过为依赖关系定义服务或拥有一个单例控制器作用域。
在控制器之间共享依赖关系或在父MVC应用程序上注册它们,以及修改每个控制器对控制器内部的BeforeActivation可选事件回调的依赖关系的能力。
例如:
func(c *MyController) BeforeActivation(b mvc.BeforeActivation)
{
b.dependencies().add /Remove(…)
}
以控制器字段的形式访问上下文(不需要手动绑定),即Ctx iris.Context 或通过方法的输入参数,i.e func(ctx iris.Context, otherArguments...)
.
在控制器结构中建模(在方法函数处设置并由视图呈现)。您可以从控制器的方法返回模型,或者在请求生命周期中设置一个字段,并将该字段返回给同一请求生命周期中的另一个方法。
mvc应用程序有自己的路由器,它是iris/ Router.party的一种类型,标准的iris api。控制器可以注册给任何一方,包括子域,团队的begin和done处理程序如预期的那样工作。
可选的BeginRequest(ctx)函数在方法执行之前执行任何初始化,当许多方法使用相同的数据集合时,调用middlewares很有用。
可选的EndRequest(ctx)函数在任何方法执行后执行任何收尾。
递归继承,例如我们的mvc会话控制器示例,有Session *sessions.Session。会话作为结构字段,由会话管理器填充。
通过控制器方法的输入参数访问动态路径参数,不需要绑定。当您使用Iris的默认语法来解析控制器中的处理程序时,您需要使用By 单词作为方法的后缀,大写是一个新的子路径。例子:
If 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:int64}
func(*Controller) PostBy(id int64)
-POST:/user/{param:int64}
If mvc.New(app.Party("/profile")).Handle(new(profile.Controller))
func(*Controller) GetBy(username string)
-GET:/profile/{param:string}
If mvc.New(app.Party("/assets")).Handle(new(file.Controller))
func(*Controller) GetByWildcard(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 只是 hero.Result 一种类型别名。
type Result interface {
// Dispatch should sends the response to the context's response writer.
// Dispatch应该将响应发送到上下文的响应编写器。
Dispatch(ctx iris.Context)
}
例子
这个示例相当于一个简单的hello world应用程序。
似乎你需要编写额外的代码不值得,但请记住,这个示例没有使用像模型这样的iris mvc特性,持久性或视图引擎都不会影响会话,它对于学习来说非常简单,你可能永远不会在你的应用中使用简单控制器。
在这个例子中,我们在“/hello”路径上使用MVC服务JSON的成本大约是2MB / 20MB吞吐量,在我的个人笔记本上,大多数应用程序都可以容忍这种情况,但您可以选择最适合您的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()
// Optionally, add two built'n handlers
// that can recover from any http-relative panics
// and log the requests to the terminal.
//可以选择添加两个构建的n处理程序
//可以从任何相对于http的panics中恢复
//并将请求记录到终端。
app.Use(recover.New())
app.Use(logger.New())
// Serve a controller based on the root Router, "/".
//服务一个控制器基于根路由器,"/"。
mvc.New(app).Handle(new(ExampleController))
// http://localhost:8080
// http://localhost:8080/ping
// http://localhost:8080/hello
// http://localhost:8080/custom_path
app.Listen(":8080")
}
// ExampleController serves the "/", "/ping" and "/hello".
//ExampleController为“/”、“/ping”和“/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 called once, before the controller adapted to the main application
// and of course before the server ran.
// After version 9 you can also add custom routes for a specific controller's methods.
// Here you can register custom method's handlers
// use the standard router with `ca.Router` to
// do something that you can do without mvc as well,
// and add dependencies that will be binded to
// a controller's fields or method function's input arguments.
//before activation调用一次,在控制器适应主应用程序之前
//当然,在服务运行之前。
//在版本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,
)
// or even add a global middleware based on this controller's router,
// which in this example is the root "/":
// b.Router().Use(myMiddleware)
//或者甚至添加一个基于控制器路由器的全局中间件,
//在本例中是根“/”
// 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 is a reserved "keyword" to tell the framework that you're going to
// bind path parameters in the function's input arguments, and it also
// helps to have "Get" and "GetBy" in the same controller.
// By是一个保留的“关键字”,它告诉框架您将要
//绑定路径参数在函数的输入参数,它也
//有助于在同一个控制器中拥有“Get”和“GetBy”。
//
// func (c *ExampleController) GetUserBy(username string) mvc.Result {
// return mvc.View{
// Name: "user/username.html",
// Data: username,
// }
// }
/* Can use more than one, the factory will make sure
that the correct http methods are being registered for each route
for this controller, uncomment these if you want:
可以使用多个,工厂将确保为这个控制器的每个路由注册正确的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() {}
// OR
func (c *ExampleController) Any() {}
func (c *ExampleController) BeforeActivation(b mvc.BeforeActivation) {
// 1 -> the HTTP Method
// 2 -> the route's path
// 3 -> this controller's method name that should be handler for that route.
b.Handle("GET", "/mypath/{param}", "DoIt", optionalMiddlewareHere...)
}
// After activation, all dependencies are set-ed - so read only access on them
// but still possible to add custom controller or simple standard handlers.
//激活后,所有依赖项都被设置为只读访问
//但仍然可以添加自定义控制器或简单的标准处理程序。
func (c *ExampleController) AfterActivation(a mvc.AfterActivation) {}
*/
在控制器中,每个导出的带有HTTP方法(Get, Post, Put, Delete…)前缀的func都可以作为HTTP端点调用。在上面的示例中,所有funcs都向响应写入一个字符串。注意每个方法前面的注释。
HTTP终端是web应用程序中的可目标URL,例如http://localhost:8080/helloworld,并组合使用的协议:HTTP,web服务器的网络位置(包括TCP端口):localhost:8080和目标URI /helloworld。
第一个注释声明这是一个HTTP GET方法,通过将“/helloworld”附加到基URL来调用。第三条注释指定了一个HTTP GET方法,通过将“/helloworld/welcome”附加到URL来调用该方法。
控制器知道如何处理GetBy上的“name”或GetWelcomeBy上的“name”和“numTimes”,由于采用了By关键字,并构建了无样板的动态路由;第三条注释指定了一个HTTP GET动态方法,该方法由以“/helloworld/welcome”开头并后面跟着两个路径部分的任何URL调用,第一个可以接受任何值,第二个只能接受数字,i,e:“http://localhost:8080/helloworld/welcome/golang/32719”,否则一个404 Not Found HTTP错误将被发送给客户端。
_examples/mvc和mvc/controller_test。go文件用简单的范例解释了每个特性,它们展示了你可以如何采用先进的Iris MVC绑定器,Iris MVC模型和更多…