目录
初识beego
bee 工具简介
bee 工具是一个为了协助快速开发 beego 项目而创建的项目,通过 bee 您可以很容易的进行 beego 项目的创建、热编译、开发、测试、和部署。
bee工具的安装
go get -u github.com/beego/bee/v2
安装完之后,bee
可执行文件默认存放在 $GOPATH/bin
里面,所以您需要把 $GOPATH/bin
添加到您的环境变量中,才可以进行下一步。
new
命令
new
命令是新建一个 Web 项目,我们在命令行下执行 bee new <项目名>
就可以创建一个新的项目。但是注意该命令必须在 $GOPATH/src
下执行。最后会在 $GOPATH/src
相应目录下生成如下目录结构的项目:
api
命令
上面的 new
命令是用来新建 Web 项目,不过很多用户使用 beego 来开发 API 应用。所以这个 api
命令就是用来创建 API 应用的,执行命令之后如下所示:
run
命令
我们在开发 Go 项目的时候最大的问题是经常需要自己手动去编译再运行,bee run
命令是监控 beego 的项目,通过 fsnotify监控文件系统。但是注意该命令必须在 $GOPATH/src/appname
下执行。
pack
命令
pack
目录用来发布应用的时候打包,会把项目打包成 zip 包,这样我们部署的时候直接把打包之后的项目上传,解压就可以部署了
version
命令
这个命令是动态获取 bee、beego 和 Go 的版本,这样一旦用户出现错误,可以通过该命令来查看当前的版本
generate
命令
这个命令是用来自动化的生成代码的,包含了从数据库一键生成 model,还包含了 scaffold 的,通过这个命令,让大家开发代码不再慢
migrate
命令
这个命令是应用的数据库迁移命令,主要是用来每次应用升级,降级的SQL管理。
dockerize
命令
这个命令可以通过生成Dockerfile文件来实现docker化你的应用。
例子:
生成一个以1.6.4版本Go环境为基础镜像的Dockerfile,并暴露9000端口:
$ bee dockerize -image="library/golang:1.6.4" -expose=9000
______
| ___ \
| |_/ / ___ ___
| ___ \ / _ \ / _ \
| |_/ /| __/| __/
\____/ \___| \___| v1.6.2
2016/12/26 22:34:54 INFO ▶ 0001 Generating Dockerfile...
2016/12/26 22:34:54 SUCCESS ▶ 0002 Dockerfile generated.
更多帮助信息可执行bee help dockerize
创建项目
bee new quickstart
通过一个简单的命令就创建了一个 beego 项目。他的目录结构如下所示
quickstart
|-- conf
| `-- app.conf
|-- controllers
| `-- default.go
|-- main.go
|-- models
|-- routers
| `-- router.go
|-- static
| |-- css
| |-- img
| `-- js
|-- tests
| `-- default_test.go
`-- views
`-- index.tpl
从目录结构中我们也可以看出来这是一个典型的 MVC 架构的应用,main.go
是入口文件。
运行项目
beego 项目创建之后,我们还需要初始化go.mod
文件。进入目录之后,使用go mod init
初始化模块依赖。
接着我们就开始运行项目,首先进入创建的项目,我们使用 bee run
来运行该项目,这样就可以做到热编译的效果:
cd quickstart
bee run
项目路由设置
前面我们已经创建了 beego 项目,而且我们也看到它已经运行起来了,那么是如何运行起来的呢?让我们从入口文件先分析起来吧:
package main
import (
_ "quickstart/routers"
"github.com/beego/beego/v2/server/web"
)
func main() {
web.Run()
}
我们看到 main 函数是入口函数,但是我们知道 Go 的执行过程是如下图所示的方式:
这里我们就看到了我们引入了一个包 _ "quickstart/routers"
,这个包只引入执行了里面的 init 函数,那么让我们看看这个里面做了什么事情:
package routers
import (
"quickstart/controllers"
"github.com/beego/beego/v2/server/web"
)
func init() {
web.Router("/", &controllers.MainController{})
}
路由包里面我们看到执行了路由注册 web.Router
, 这个函数的功能是映射 URL 到 controller,第一个参数是 URL (用户请求的地址),这里我们注册的是 /
,也就是我们访问的不带任何参数的 URL,第二个参数是对应的 Controller,也就是我们即将把请求分发到那个控制器来执行相应的逻辑,我们可以执行类似的方式注册如下路由:
web.Router("/user", &controllers.UserController{})
web.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 的优势
controller 逻辑
前面我们了解了如何把用户的请求分发到控制器,这小节我们就介绍大家如何来写控制器,首先我们还是从源码分析入手:
package controllers
import (
"github.com/beego/beego/v2/server/web"
)
type MainController struct {
web.Controller
}
func (this *MainController) Get() {
this.Data["Website"] = "beego.vip"
this.Data["Email"] = "astaxie@gmail.com"
this.TplName = "index.tpl"
}
上面的代码显示首先我们声明了一个控制器 MainController
,这个控制器里面组合了 web.Controller
,这就是 Go 的组合方式,也就是 MainController
自动拥有了所有 web.Controller
的方法。
而 web.Controller
拥有很多方法,其中包括 Init
、Prepare
、Post
、Get
、Delete
、Head
等方法。我们可以通过重写的方式来实现这些方法,而我们上面的代码就是重写了 Get
方法。
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 编写
在前面编写 Controller 的时候,我们在 Get 里面写过这样的语句 this.TplName = "index.tpl"
,设置显示的模板文件,默认支持 tpl
和 html
的后缀名,如果想设置其他后缀你可以调用 beego.AddTemplateExt
接口设置,那么模板如何来显示相应的数据呢?beego 采用了 Go 语言默认的模板引擎,所以和 Go 的模板语法一样,Go 模板的详细使用方法请参考《Go Web 编程》模板使用指南
<!DOCTYPE html>
<html>
<head>
<title>Beego</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<header class="hero-unit" style="background-color:#A9F16C">
<div class="container">
<div class="row">
<div class="hero-text">
<h1>Welcome to Beego!</h1>
<p class="description">
Beego is a simple & powerful Go web framework which is inspired by tornado and sinatra.
<br />
Official website: <a href="http://{{.Website}}">{{.Website}}</a>
<br />
Contact me: {{.Email}}
</p>
</div>
</div>
</div>
</header>
</body>
</html>
我们在 Controller 里面把数据赋值给了 data(map 类型),然后我们在模板中就直接通过 key 访问 .Website
和 .Email
。这样就做到了数据的输出。接下来我们讲解如何让静态文件输出。
静态文件处理
前面我们介绍了如何输出静态页面,但是我们的网页往往包含了很多的静态文件,包括图片、JS、CSS 等,刚才创建的应用里面就创建了如下目录:
├── static
│ ├── css
│ ├── img
│ └── js
beego 默认注册了 static 目录为静态处理的目录,注册样式:URL 前缀和映射的目录(在/main.go
文件中web.Run()
之前加入):
StaticDir["/static"] = "static"
用户可以设置多个静态文件处理目录,例如你有多个文件下载目录 download1、download2,你可以这样映射(在 /main.go
文件中 web.Run()
之前加入):
web.SetStaticPath("/down1", "download1")
web.SetStaticPath("/down2", "download2")
这样用户访问 URL http://localhost:8080/down1/123.txt
则会请求 download1 目录下的 123.txt 文件。