Skip to content

Commit 2ab314a

Browse files
committed
完成了框架的基本架构
1 parent 6a327f7 commit 2ab314a

File tree

6 files changed

+393
-9
lines changed

6 files changed

+393
-9
lines changed

13.4.md

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,157 @@
66
MVC设计模式是目前Web应用开发中最常见的一种架构模式,通过分离 Model(模型)、View(视图)和 Controller(控制器),可以更容易实现易于扩展的UI。Model指后台返回的数据;View指需要渲染的页面,通常是模板页面,渲染后的结果通常是HTML;Controller指Web开发人员编写的处理不同URL的控制器,如前面小节讲述的路由就是转发到控制器的过程,controller在整个的MVC框架中起到了一个核心的作用,处理业务逻辑,因此控制器是整个框架中必不可少的一部分,Model和View会更具不同的业务可以不写,例如没有数据处理的逻辑处理,没有页面输出的302调整之类的就不需要Model和View,但是controller是必不可少的。
77

88
## beego的REST设计
9+
前面小节介绍了路由实现了注册struct的功能,而struct中实现了REST方式,因此我们需要设计一个用于逻辑处理controller的基类,这里主要设计了两个类型,一个struct、一个interface
10+
11+
type Controller struct {
12+
Ct *Context
13+
Tpl *template.Template
14+
Data map[interface{}]interface{}
15+
ChildName string
16+
TplNames string
17+
Layout []string
18+
TplExt string
19+
}
20+
21+
type ControllerInterface interface {
22+
Init(ct *Context, cn string) //初始化上下文和子类名称
23+
Prepare() //开始执行之前的一些处理
24+
Get() //method=GET的处理
25+
Post() //method=POST的处理
26+
Delete() //method=DELETE的处理
27+
Put() //method=PUT的处理
28+
Head() //method=HEAD的处理
29+
Patch() //method=PATCH的处理
30+
Options() //method=OPTIONS的处理
31+
Finish() //执行完成之后的处理 Render() error //执行完method对应的方法之后渲染页面
32+
}
33+
34+
那么前面介绍的路由add的时候是定义了ControllerInterface类型,因此,只要我们实现这个接口就可以,所以我们的基类Controller实现如下的方法:
35+
36+
func (c *Controller) Init(ct *Context, cn string) {
37+
c.Data = make(map[interface{}]interface{})
38+
c.Layout = make([]string, 0)
39+
c.TplNames = ""
40+
c.ChildName = cn
41+
c.Ct = ct
42+
c.TplExt = "tpl"
43+
}
44+
45+
func (c *Controller) Prepare() {
46+
47+
}
48+
49+
func (c *Controller) Finish() {
50+
51+
}
52+
53+
func (c *Controller) Get() {
54+
http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
55+
}
56+
57+
func (c *Controller) Post() {
58+
http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
59+
}
60+
61+
func (c *Controller) Delete() {
62+
http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
63+
}
64+
65+
func (c *Controller) Put() {
66+
http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
67+
}
68+
69+
func (c *Controller) Head() {
70+
http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
71+
}
72+
73+
func (c *Controller) Patch() {
74+
http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
75+
}
76+
77+
func (c *Controller) Options() {
78+
http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
79+
}
80+
81+
func (c *Controller) Render() error {
82+
if len(c.Layout) > 0 {
83+
var filenames []string
84+
for _, file := range c.Layout {
85+
filenames = append(filenames, path.Join(ViewsPath, file))
86+
}
87+
t, err := template.ParseFiles(filenames...)
88+
if err != nil {
89+
Trace("template ParseFiles err:", err)
90+
}
91+
err = t.ExecuteTemplate(c.Ct.ResponseWriter, c.TplNames, c.Data)
92+
if err != nil {
93+
Trace("template Execute err:", err)
94+
}
95+
} else {
96+
if c.TplNames == "" {
97+
c.TplNames = c.ChildName + "/" + c.Ct.Request.Method + "." + c.TplExt
98+
}
99+
t, err := template.ParseFiles(path.Join(ViewsPath, c.TplNames))
100+
if err != nil {
101+
Trace("template ParseFiles err:", err)
102+
}
103+
err = t.Execute(c.Ct.ResponseWriter, c.Data)
104+
if err != nil {
105+
Trace("template Execute err:", err)
106+
}
107+
}
108+
return nil
109+
}
110+
111+
func (c *Controller) Redirect(url string, code int) {
112+
c.Ct.Redirect(code, url)
113+
}
114+
115+
上面的controller基类完成了接口定义的函数,通过路由根据url执行相应的controller的原则,会以此执行如下的函数:
116+
117+
Init() 初始化
118+
Prepare() 执行之前的初始化,每个继承的子类可以来实现该函数
119+
method() 根据不同的method执行不同的函数:GET、POST、PUT、HEAD等,子类来实现这些函数,如果没实现,那么默认都是403
120+
Render() 可选,根据全局变量AutoRender来判断是否执行
121+
Finish() 执行完之后执行的操作,每个继承的子类可以来实现该函数
9122

10123
## 应用指南
124+
上面beego框架中完成了controller基类的设计,那么我们在我们的应用中可以这样来设计我们的方法:
125+
126+
package controllers
127+
128+
import (
129+
"github.com/astaxie/beego"
130+
)
131+
132+
type MainController struct {
133+
beego.Controller
134+
}
135+
136+
func (this *MainController) Get() {
137+
this.Data["Username"] = "astaxie"
138+
this.Data["Email"] = "astaxie@gmail.com"
139+
this.TplNames = "index.tpl"
140+
}
141+
142+
上面的方式我们实现了子类MainController,实现了Get方法,那么如果用户通过其他的方式(POST/HEAD等)来访问该资源都将返回403,而如果是Get来访问,因为我们设置了AutoRender=true,那么在执行玩Get方法之后会自动执行Render函数,就会显示如下界面:
143+
144+
![](images/13.4.beego.png?raw=true)
145+
146+
index.tpl的代码如下所示,我们可以看到数据的设置和显示都是相当的简单方便:
147+
148+
<!DOCTYPE html>
149+
<html>
150+
<head>
151+
<title>beego welcome template</title>
152+
</head>
153+
<body>
154+
<h1>Hello, world!{{.Username}},{{.Email}}</h1>
155+
</body>
156+
</html>
157+
11158

12159
## links
13160
* [目录](<preface.md>)
14161
* 上一章: [自定义路由器设计](<13.3.md>)
15-
* 下一节: [数据库操作](<13.5.md>)
162+
* 下一节: [日志和配置设计](<13.5.md>)

0 commit comments

Comments
 (0)