路由控制
beego的路由设置有三种方式:固定路由、正则路由、自动路由。(具体可见:传送门)
下面以固定路由和自定义方法为例
修改视图
在views/index.tpl 里的<body> 标签修改如下(添加了一个form表单和一个上传文件功能):
<body>
<header>
<h1 class="logo">Welcome to Beego</h1>
<div class="description">
Beego is a simple & powerful Go web framework which is inspired by tornado and sinatra.<br>
Username:{{.Username}}<br>
Age:{{.Age}}<br>
Email:{{.Eemail}}<br>
</div>
</header>
<div class="postform">
<form id="user" action="http://127.0.0.1:8080/" method="post">
名字:<input name="username" type="text" />
年龄:<input name="age" type="text" />
邮箱:<input name="Email" type="text" />
<input type="submit" value="提交" />
</form>
<form enctype="multipart/form-data" action="http://127.0.0.1:8080/upload" method="post">
<input type="file" name="uploadname" />
<input type="submit">
</form>
</div>
<footer>
<div class="author">
Official website:
<a href="http://{{.Website}}">{{.Website}}</a> /
Contact me:
<a class="email" href="mailto:{{.Email}}">{{.Email}}</a>
</div>
</footer>
<div class="backdrop"></div>
<script src="/static/js/reload.min.js"></script>
</body>
注意:
form不指定method属性的话默认是GET,所以应该声明下method="post"。不指定action的话默认是发送请求至当前页面的url,因此还是建议指定下action。
在static/css/index.css 里修改如下(只是为了居中):
.description,
.postform {
text-align: center;
font-size: 16px;
}
然而可能有个问题,就是在重复启动项目的过程中,由于之前已经请求加载过一次css文件了,被服务器保存在缓存中,所以我们本次修改后的css文件不会被服务器更新,解决方法即在views/index.tpl 中修改如下:
<link href="../static/css/index.css?ver=1" rel="stylesheet" type="text/css" />
ver = n,n代表版本号,加一个版本号即可。
路由器
在routers/router.go 里添加如下代码:
func init() {
// 设置固定路由,指定url和对应的控制器
beego.Router("/", &controllers.MainController{})
beego.Router("/admin", &controllers.UserController{})
beego.Router("/admin/index", &controllers.ArticleController{})
beego.Router("/admin/addpkg", &controllers.AddController{})
// 设置自定义路由,指定发送到/upload的post请求对应控制器里的UploadFile方法
beego.Router("/upload", &controllers.MainController{}, `post:UploadFile`)
beego.Router("/TestPostJson", &controllers.MainController{}, `post:TestPostJson`)
beego.Router("/TestGetJson", &controllers.MainController{}, `get:TestGetJson`)
}
beego的固定路由方式是典型的 RESTful 方式:一个固定的路由,一个控制器,然后根据用户请求方法不同请求控制器中对应的方法。比如url是/admin,根据上面代码,则会请求ArticleController控制器的方法。(请求的 method 和函数名一致,例如 GET 请求执行 Get 函数,POST 请求执行 Post 函数,所以只需要在控制器里重写Get方法和Post方法)
而自定义路由方式,则多了beego.Router的第三个参数。冒号前面部分表示发送到url的http请求的method,如果是星号* 则表示所有。冒号后面表示对应匹配的方法,如post:UploadFile 表示传到该url的post请求指定对应控制器里的UploadFile函数来处理,而*:UploadFile 表示所有传到该url的请求都用UploadFile函数来处理。
控制器
在controllers/default.go 里添加如下代码(这里MainController 还重写了Post方法):
type MainController struct {
beego.Controller
}
type UserController struct {
beego.Controller
}
type ArticleController struct {
beego.Controller
}
type AddController struct {
beego.Controller
}
type user struct {
/*
定义 struct 时,字段名后如果有 form 这个 tag,则会以把 form 表单里的 name 和 tag 的名称一样的字段赋值给这个字段,
否则就会把 form 表单里与字段名一样的表单内容赋值给这个字段(通过form这个tag)。
如上面例子中,会把表单中的 username 和 age 分别赋值给 user 里的 Name 和 Age 字段,
而 Email 里的内容则会赋给 Email 这个字段(与字段名一样的表单内容,无需form)
*/
// 如果要忽略一个字段,有两种办法,一是:字段名小写开头,
// 二是:form 标签的值设置为"-"。这里明显是第二种
Id int `form:"-"`
Name interface{} `form:"username"`
Age int `form:"age"`
Email string
}
func (c *MainController) Get() {
// c.Data["XXX"]这个map数据结构可以直接被views视图以{{.XXX}}来获取
c.Data["Website"] = "MainController"
c.Data["Email"] = "MainController@gmail.com"
// 设置要渲染的模板
c.TplName = "index.tpl"
}
func (c *MainController) Post() {
// 新建一个user
u := user{}
// 接下来是为了验证以post提交的form的数据是否存储在c的Data这个map数据结构中,事实证明不是的。
beego.Debug("\n",
"Id:", 123, "\n",
"Name", c.Data["Username"], "\n",
"Age", c.Data["Age"], "\n",
"Email",c.Data["Eemail"])
// 将c,即MainController,里存储的数据转化到user格式的u变量,注意必须传入地址
if err := c.ParseForm(&u); err != nil {
log.Fatal("ParseForm err ", err)
}
// 现在u是个有数据的user了,取出来存到c里去
c.Data["Username"] = u.Name
c.Data["Age"] = u.Age
c.Data["Eemail"] = u.Email
// 输出u里的四个属性值
beego.Debug("\n",
"Id:", u.Id, "\n",
"Name", u.Name, "\n",
"Age", u.Age, "\n",
"Email", u.Email, "\n")
c.Data["Website"] = "MainController"
c.Data["Email"] = "MainController@gmail.com"
c.TplName = "index.tpl"
}
// 上传文件的post请求处理
func (c *MainController) UploadFile() {
// 获取控制器数据流里的文件
f, h, err := c.GetFile("uploadname")
if err != nil {
log.Fatal("getfile err ", err)
}
defer f.Close()
// 保存位置在 static/upload, 没有文件夹要先创建,不然文件保存失败
c.SaveToFile("uploadname", "static/upload/" + h.Filename)
c.Data["Website"] = "MainController"
c.Data["Email"] = "MainController@gmail.com"
c.TplName = "index.tpl"
}
func (c *UserController) Get() {
c.Data["Website"] = "UserController"
c.Data["Email"] = "UserController@gmail.com"
c.TplName = "index.tpl"
}
func (c *ArticleController) Get() {
c.Data["Website"] = "ArticleController"
c.Data["Email"] = "ArticleController@gmail.com"
c.TplName = "index.tpl"
}
func (c *AddController) Get() {
c.Data["Website"] = "AddController"
c.Data["Email"] = "AddController@gmail.com"
c.TplName = "index.tpl"
}
type User struct {
Id int
Username string
Password string
}
// POST JSON数据
func (c *MainController) TestPostJson() {
ob := &User{}
var err error
// POST过来的数据保存在requestBody里,由于是JSON格式,使用json.Unmarshal转为ob
if err = json.Unmarshal(c.Ctx.Input.RequestBody, &ob); err == nil {
// 输出ob
beego.Debug("\n",
"Unmarshal success", "\n",
"show Student :", "\n",
"Id", ob.Id, "\n",
"Username", ob.Username, "\n",
"Password", ob.Password, "\n",
)
// 再把ob转为JSON数据输出,注意传进Data["json"]的数据本身不能是JSON数据
c.Data["json"] = ob
c.ServeJSON()
}
c.Data["Website"] = "MainController"
c.Data["Email"] = "MainController@gmail.com"
c.TplName = "index.tpl"
}
// GET JSON数据
func (c *MainController) TestGetJson() {
ob := &User{520, "StellaChan", "19970227"}
// 将User类型的ob使用json.Marshal转为JSON格式
if b, err := json.Marshal(ob); err == nil {
// 输出ob
beego.Debug("\n",
b, "\n",
string(b), "\n",
ob, "\n",
)
// 再把ob转为JSON数据输出,注意传进Data["json"]的数据本身不能是JSON数据
c.Data["json"] = ob
c.ServeJSON()
}
}
首先我们声明了几个控制器,控制器里面内嵌了beego.Controller,这就是 Go 的嵌入方式,也就是这些控制器都自动拥有了所有 beego.Controller 的方法。
而 beego.Controller 拥有很多方法,其中包括 Init、Prepare、Post、Get、Delete、Head 等方法。我们可以通过重写的方式来实现这些方法,而我们上面的代码就是重写了 Get 和 Post 方法。
上述代码使用了固定路由和自定义路由两种。方法里面的代码是需要执行的逻辑,我们可以通过各种方式获取数据,然后赋值到 this.Data 中,这是一个用来存储输出数据的 map 数据结构,可以赋值任意类型的值。c.Data["XXX"]这个map数据结构可以直接被views视图以{{.XXX}}来获取,语法详见beego模板语法指南:传送门。
最后一个就是需要去渲染的模板,this.TplName 就是需要渲染的模板,这里指定了 index.tpl,如果用户不设置该参数,那么默认会去到模板目录的 Controller/<方法名>.tpl 查找,例如 maincontroller/get.tpl (文件、文件夹必须小写)。
用户设置了模板之后系统会自动的调用 Render 函数(这个函数是在 beego.Controller 中实现的),所以无需用户自己来调用渲染。
当然也可以不使用模版,直接用 this.Ctx.WriteString 输出字符串,如:
func (this *MainController) Get() {
this.Ctx.WriteString("hello")
}
这样就会单纯返回一个字符串并显示。
上述代码还涉及文件上传以及一些http请求的处理逻辑,下面我们会一一再详讲。
运行
现在先启动我们的项目,记得在main函数里不要运行到上一节的数据库函数,只需要如下:
func main() {
beego.Run()
}
普通页面请求GET
输入http://127.0.0.1:8080/
界面显示如下:

后台显示如下:

请求的host为127.0.0.1,url为“/”,method为GET,请求响应结果状态码为200,表示响应成功。
界面红框部分很明显是控制器的方法在作用:
func (c *MainController) Get() {
// c.Data["XXX"]这个map数据结构可以直接被views视图以{{.XXX}}来获取
c.Data["Website"] = "MainController"
c.Data["Email"] = "MainController@gmail.com"
// 设置要渲染的模板
c.TplName = "index.tpl"
}
我们在路由器还有其他的url跟控制器的设置
输入 http://127.0.0.1:8080/admin :

输入 http://127.0.0.1:8080/admin/index :

输入 http://127.0.0.1:8080/admin/addpkg :

可以看到输出与我们在控制器里的代码设置一致,程序运行正确。
POST
POST 表单
填写表单并提交:

后台输出结果如下:

第一部分的输出对应代码如下:
beego.Debug("\n",
"Id:", 123, "\n",
"Name", c.Data["Username"], "\n",
"Age", c.Data["Age"], "\n",
"Email",c.Data["Eemail"])
这里是为了验证以post提交的表单数据,是否是存储在c的Data这个map数据结构中,然而可以看到输出的结果为<nil>,即为空,所以不能通过c.Data直接取数据(实际上,提交的表单数据是保存在c.Ctx.Request.Form中)
而后使用c.ParseForm(&u), 根据u的结构体构造(form 这个 tag),将表单数据保存在u中,于是就可以通过u.XX的方式提取出数据了。
之后代码如下:
// 现在u是个有数据的user了,取出来存到c里去
c.Data["Username"] = u.Name
c.Data["Age"] = u.Age
c.Data["Eemail"] = u.Email
可以看到页面的输出结果:

POST 文件
先在static文件夹里新建一个文件夹,名为upload

选择文件并提交上传:

后台输出结果如下:

可以看到文件夹里多了刚上传的文件:

在beego中,如果只是单纯的文件上传的话还是很方便处理的,有c.GetFile("")和c.SaveToFile("") 两个函数分别负责获取上传的文件以及保存文件。
JSON数据请求
GET JSON
输入http://127.0.0.1:8080/TestGetJson
界面显示如下:

后台显示如下:

对应代码如下:
type User struct {
Id int
Username string
Password string
}
// GET JSON数据
func (c *MainController) TestGetJson() {
ob := &User{520, "StellaChan", "19970227"}
// 将User类型的ob使用json.Marshal转为JSON格式
if b, err := json.Marshal(ob); err == nil {
// 输出ob
beego.Debug("\n",
b, "\n",
string(b), "\n",
ob, "\n",
)
// 把ob转为JSON数据输出,注意传进Data["json"]的数据本身不能是JSON数据
c.Data["json"] = ob
c.ServeJSON()
}
}
先定义了个User结构体,然后声明一个User类型变量ob并且初始化值。其实这个时候就可以通过赋值给c.Data["json"]的方式将User类型变量ob 以JSON格式输出到页面(或者反馈给发送了GET请求的客户端)。
中间展示的是通过json.Marshal将User类型的ob转为JSON格式的变量b,此时b直接输出是ASCII码值,必须转为字符串string类型才能正常显示。
POST JSON
正常网页没法做到POST,因此本人此处借助Postman来发送post请求。
先在Headers指定post的数据格式为JSON:

再在Body中写入要Post的JSON数据,并且点击Send:

后台显示如下(可以看到成功接收了JSON数据并解析):

对应代码如下:
// POST JSON数据
func (c *MainController) TestPostJson() {
ob := &User{}
var err error
// POST过来的数据保存在requestBody里,由于是JSON格式,使用json.Unmarshal转为ob
if err = json.Unmarshal(c.Ctx.Input.RequestBody, &ob); err == nil {
// 输出ob
beego.Debug("\n",
"Unmarshal success", "\n",
"show Student :", "\n",
"Id", ob.Id, "\n",
"Username", ob.Username, "\n",
"Password", ob.Password, "\n",
)
// 再把ob转为JSON数据输出,注意传进Data["json"]的数据本身不能是JSON数据
c.Data["json"] = ob
c.ServeJSON()
}
c.Data["Website"] = "MainController"
c.Data["Email"] = "MainController@gmail.com"
c.TplName = "index.tpl"
}
与GET JSON类似,先声明一个User类型变量ob,然后通过json.Unmarshal将JSON类型的c.Ctx.Input.RequestBody (我们前文有提到POST的数据保存在这里)转为User类型的变量ob。之后的步骤类似,最后我们再通过赋值给c.Data["json"]的方式将User类型变量ob 以JSON格式输出到页面(或者反馈给发送了POST请求的客户端)。

本文介绍Beego框架中的路由设置方法,包括固定路由、正则路由和自动路由,并详细讲解了如何处理表单提交、文件上传及JSON数据交互。
路由跳转教程&spm=1001.2101.3001.5002&articleId=82354287&d=1&t=3&u=10ec0d2c7d9e447b9aaec584f1139afa)
5453

被折叠的 条评论
为什么被折叠?



