1、beego快速入门
1.1 新建项目
新建一个项目:
[root@zsx src]# bee new quickstart
2023/02/19 15:55:50.370 [D] init global config instance failed. If you do not use this, just ignore it. open conf/app.conf: no such file or directory
2023/02/19 15:55:50 INFO ▶ 0001 Generate new project support go modules.
2023/02/19 15:55:50 INFO ▶ 0002 Creating application...
create /home/zhangshixing/go_work_space/src/quickstart/go.mod
create /home/zhangshixing/go_work_space/src/quickstart/
create /home/zhangshixing/go_work_space/src/quickstart/conf/
create /home/zhangshixing/go_work_space/src/quickstart/controllers/
create /home/zhangshixing/go_work_space/src/quickstart/models/
create /home/zhangshixing/go_work_space/src/quickstart/routers/
create /home/zhangshixing/go_work_space/src/quickstart/tests/
create /home/zhangshixing/go_work_space/src/quickstart/static/
create /home/zhangshixing/go_work_space/src/quickstart/static/js/
create /home/zhangshixing/go_work_space/src/quickstart/static/css/
create /home/zhangshixing/go_work_space/src/quickstart/static/img/
create /home/zhangshixing/go_work_space/src/quickstart/views/
create /home/zhangshixing/go_work_space/src/quickstart/conf/app.conf
create /home/zhangshixing/go_work_space/src/quickstart/controllers/default.go
create /home/zhangshixing/go_work_space/src/quickstart/views/index.tpl
create /home/zhangshixing/go_work_space/src/quickstart/routers/router.go
create /home/zhangshixing/go_work_space/src/quickstart/tests/default_test.go
create /home/zhangshixing/go_work_space/src/quickstart/main.go
2023/02/19 15:55:50 SUCCESS ▶ 0003 New application successfully created!
启动项目:
[root@zsx src]# cd quickstart/
[root@zsx quickstart]# go mod tidy
[root@zsx quickstart]# bee run
______
| ___ \
| |_/ / ___ ___
| ___ \ / _ \ / _ \
| |_/ /| __/| __/
\____/ \___| \___| v2.0.4
2023/02/19 15:56:46 INFO ▶ 0001 Using 'quickstart' as 'appname'
2023/02/19 15:56:46 INFO ▶ 0002 Initializing watcher...
quickstart/controllers
quickstart/routers
quickstart
2023/02/19 15:56:49 SUCCESS ▶ 0003 Built Successfully!
2023/02/19 15:56:49 INFO ▶ 0004 Restarting 'quickstart'...
2023/02/19 15:56:49 SUCCESS ▶ 0005 './quickstart' is running...
2023/02/19 15:56:49.917 [I] [parser.go:413] generate router from comments
2023/02/19 15:56:49.917 [I] [server.go:241] http server Running on http://:8080
1.2 项目路由设置
前面我们已经创建了beego项目,而且我们也看到它已经运行起来了,那么是如何运行起来的呢?让我们从入口文
件quickstart/main.go
先分析起来吧:
package main
import (
_ "quickstart/routers"
beego "github.com/beego/beego/v2/server/web"
)
func main() {
beego.Run()
}
我们看到 main 函数是入口函数,但是我们知道 Go 的执行过程是如下图所示的方式:
这里我们就看到了我们引入了一个包_ "quickstart/routers"
,这个包只引入执行了里面的init
函数,那么让
我们看看这个里面做了什么事情:
package routers
import (
"quickstart/controllers"
beego "github.com/beego/beego/v2/server/web"
)
func init() {
beego.Router("/", &controllers.MainController{})
}
路由包里面我们看到执行了路由注册 beego.Router
,这个函数的功能是映射 URL 到 controller,第一个参数是
URL
(用户请求的地址),这里我们注册的是 /
,也就是我们访问的不带任何参数的 URL,第二个参数是对应的
Controller
,也就是我们即将把请求分发到那个控制器来执行相应的逻辑,我们可以执行类似的方式注册如下路
由:
beego.Router("/user", &controllers.UserController{})
这样用户就可以通过访问 /user
去执行 UserController
的逻辑。这就是我们所谓的路由,更多更复杂的路由
规则请查询后面的web的路由设置。
再回来看看 main 函数里面的 beego.Run
, beego.Run
执行之后,我们看到的效果好像只是监听服务端口这个
过程,但是它内部做了很多事情:
-
解析配置文件
beego会自动解析在 conf 目录下面的配置文件
app.conf
,通过修改配置文件相关的属性,我们可以定义:开启的端口,是否开启 session,应用名称等信息。
-
执行用户的 hookfunc
beego会执行用户注册的 hookfunc,默认的已经存在了注册 mime,用户可以通过函数
AddAPPStartHook
注册自己的启动函数。
-
是否开启 session
会根据上面配置文件的分析之后判断是否开启 session,如果开启的话就初始化全局的 session。
-
是否编译模板
beego 会在启动的时候根据配置把 views 目录下的所有模板进行预编译,然后存在 map 里面,这样可以有效
的提高模板运行的效率,无需进行多次编译。
-
是否开启文档功能
根据 EnableDocs 配置判断是否开启内置的文档路由功能
-
是否启动管理模块
beego 目前做了一个很酷的模块,应用内监控模块,会在 8088 端口做一个内部监听,我们可以通过这个端口
查询到 QPS、CPU、内存、GC、goroutine、thread 等统计信息。
-
监听服务端口
这是最后一步也就是我们看到的访问 8080 看到的网页端口,内部其实调用了
ListenAndServe
,充分利用了goroutine 的优势。
一旦 run 起来之后,我们的服务就监听在两个端口了,一个服务端口 8080 作为对外服务,另一个 8088 端口实行
对内监控。
通过这个代码的分析我们了解了 beego 运行起来的过程,以及内部的一些机制。接下来让我们去剥离 Controller
如何来处理逻辑的。
1.3 controller 逻辑
前面我们了解了如何把用户的请求分发到控制器,这小节我们就介绍大家如何来写控制器,首先我们还是从源码分
析入手quickstart/controllers/default.go
:
package controllers
import (
beego "github.com/beego/beego/v2/server/web"
)
type MainController struct {
beego.Controller
}
func (c *MainController) Get() {
c.Data["Website"] = "beego.me"
c.Data["Email"] = "astaxie@gmail.com"
c.TplName = "index.tpl"
}
上面的代码显示首先我们声明了一个控制器 MainController
,这个控制器里面组合了 web.Controller
,这就
是 Go 的组合方式,也就是 MainController
自动拥有了所有 web.Controller
的方法。
而 web.Controller
拥有很多方法,其中包括 Init
、Prepare
、Post
、Get
、Delete
、Head
等方法。我们
可以通过重写的方式来实现这些方法,而我们上面的代码就是重写了 Get
方法。
我们先前介绍过 beego 是一个 RESTful 的框架,所以我们的请求默认是执行对应 req.Method
的方法。例如浏览
器的是 GET
请求,那么默认就会执行 MainController
下的 Get
方法。这样我们上面的 Get 方法就会被执行
到,这样就进入了我们的逻辑处理。(用户可以改变这个行为,通过注册自定义的函数名,更加详细的请参考路由
设置)。
里面的代码是需要执行的逻辑,这里只是简单的输出数据,我们可以通过各种方式获取数据然后赋值到 c.Data
中,这是一个用来存储输出数据的 map,可以赋值任意类型的值,这里我们只是简单举例输出两个字符串。
最后一个就是需要去渲染的模板,c.TplName
就是需要渲染的模板,这里指定了 index.tpl
,如果用户不设置
该参数,那么默认会去到模板目录的 controller/<方法名>.tpl
查找,文件和文件夹必须小写,例如上面的方法
会去查找 maincontroller/get.tpl
。
用户设置了模板之后系统会自动的调用 Render
函数(这个函数是在 web.Controller
中实现的),所以无需用
户自己来调用渲染。
当然也可以不使用模版,直接用 c.Ctx.WriteString
输出字符串,如:
func (c *MainController) Get() {
c.Ctx.WriteString("hello")
}
至此我们的控制器分析基本完成了,接下来让我们看看如何来编写 model。
1.4 model 分析
我们知道 Web 应用中我们用的最多的就是数据库操作,而 model 层一般用来做这些操作,我们的 bee new
例子
不存在 Model 的演示,但是 bee api
应用中存在 model 的应用。说的简单一点,如果您的应用足够简单,那么
Controller 可以处理一切的逻辑,如果您的逻辑里面存在着可以复用的东西,那么就抽取出来变成一个模块。因此
Model 就是逐步抽象的过程,一般我们会在 Model 里面处理一些数据读取,如下是一个日志分析应用中的代码片
段:
package models
import (
"path/filepath"
"strings"
)
var (
NotPV []string = []string{"css", "js", "class", "gif", "jpg", "jpeg", "png", "bmp", "ico", "rss", "xml", "swf"}
)
const big = 0xFFFFFF
func LogPV(urls string) bool {
ext := filepath.Ext(urls)
if ext == "" {
return true
}
for _, v := range NotPV {
if v == strings.ToLower(ext) {
return false
}
}
return true
}
所以如果您的应用足够简单,那么就不需要 Model 了;如果你的模块开始多了,需要复用,需要逻辑分离了,那
么 Model 是必不可少的。接下来我们将分析如何编写 View 层的东西。
1.5 View 编写
在前面编写 Controller 的时候,我们在 Get 里面写过这样的语句 c.TplName = "index.tpl"
,设置显示的模板
文件,默认支持 tpl
和 html
的后缀名,如果想设置其他后缀你可以调用 beego.AddTemplateExt
接口设置,
那么模板如何来显示相应的数据呢?beego 采用了 Go 语言默认的模板引擎,所以和 Go 的模板语法一样。
我们看看快速入门里面的代码(去掉了 css 样式):
<!DOCTYPE html>
<html>
<head>
<title>Beego</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
</style>
</head>
<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.
</div>
</header>
<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>
</html>
我们在 Controller 里面把数据赋值给了 data(map 类型),然后我们在模板中就直接通过 key 访问 .Website
和 .Email
。这样就做到了数据的输出,接下来我们讲解如何让静态文件输出。
1.6 静态文件处理
前面我们介绍了如何输出静态页面,但是我们的网页往往包含了很多的静态文件,包括图片、JS、CSS 等,刚才创
建的应用里面就创建了如下目录:
[root@zsx quickstart]# tree static/
static/
├── css
├── img
└── js
└── reload.min.js
3 directories, 1 file
beego 默认注册了 static 目录为静态处理的目录,注册样式:URL 前缀和映射的目录(在/main.go
文件中
beego.Run()
之前加入):
StaticDir["/static"] = "static"
用户可以设置多个静态文件处理目录,例如你有多个文件下载目录 download1、download2,你可以这样映射
(在 /main.go
文件中 beego.Run()
之前加入):
beego.SetStaticPath("/download1", "download1")
beego.SetStaticPath("/download2", "download2")
这样用户访问 URL http://localhost:8080/download1/1.txt
则会请求 download1 目录下的 1.txt 文件。
[root@zsx quickstart]# curl http://localhost:8080/download1/1.txt
1
[root@zsx quickstart]# curl http://localhost:8080/download2/2.txt
2
比较好的选择是将上述的操作放在quickstart/routers/router.go
:
package routers
import (
"quickstart/controllers"
beego "github.com/beego/beego/v2/server/web"
)
func init() {
beego.SetStaticPath("/download1", "download1")
beego.SetStaticPath("/download2", "download2")
beego.Router("/", &controllers.MainController{})
}