1、创建项目
1.1 bee创建项目
beego 的项目基本都是通过 bee
命令来创建的,所以在创建项目之前确保你已经安装了 bee 工具和 beego。如果你还没有安装,那么请查阅 和 。
现在一切就绪我们就可以开始创建项目了,打开终端,进入 $GOPATH/src
所在的目录:
➜ src bee new quickstart[INFO] Creating application.../gopath/src/quickstart//gopath/src/quickstart/conf//gopath/src/quickstart/controllers//gopath/src/quickstart/models//gopath/src/quickstart/routers//gopath/src/quickstart/tests//gopath/src/quickstart/static//gopath/src/quickstart/static/js//gopath/src/quickstart/static/css//gopath/src/quickstart/static/img//gopath/src/quickstart/views//gopath/src/quickstart/conf/app.conf/gopath/src/quickstart/controllers/default.go/gopath/src/quickstart/views/index.tpl/gopath/src/quickstart/routers/router.go/gopath/src/quickstart/tests/default_test.go/gopath/src/quickstart/main.go2014/11/06 18:17:09 [SUCC] New application successfully created!
通过一个简单的命令就创建了一个 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
是入口文件。
1.2 运行项目
beego 项目创建之后,我们就开始运行项目,首先进入创建的项目,我们使用 bee run
来运行该项目,这样就可以做到热编译的效果:
➜ src cd quickstart➜ quickstart bee run2014/11/06 18:18:34 [INFO] Uses 'quickstart' as 'appname'2014/11/06 18:18:34 [INFO] Initializing watcher...2014/11/06 18:18:34 [TRAC] Directory(/gopath/src/quickstart/controllers)2014/11/06 18:18:34 [TRAC] Directory(/gopath/src/quickstart)2014/11/06 18:18:34 [TRAC] Directory(/gopath/src/quickstart/routers)2014/11/06 18:18:34 [TRAC] Directory(/gopath/src/quickstart/tests)2014/11/06 18:18:34 [INFO] Start building...2014/11/06 18:18:35 [SUCC] Build was successful2014/11/06 18:18:35 [INFO] Restarting quickstart ...2014/11/06 18:18:35 [INFO] ./quickstart is running...2014/11/06 18:18:35 [app.go:96] [I] http server Running on :8080
这样我们的应用已经在 8080
端口(beego 的默认端口)跑起来了.你是不是觉得很神奇,为什么没有 nginx 和 apache 居然可以自己干这个事情?是的,Go 其实已经做了网络层的东西,beego 只是封装了一下,所以可以做到不需要 nginx 和 apache。让我们打开浏览器看看效果吧:
你内心是否激动了?开发网站如此简单有没有。好了,接下来让我们一层一层的剥离来大概的了解 beego 是怎么运行起来的。
2、路由设置
前面我们已经创建了 beego 项目,而且我们也看到他已经运行起来了,那么是如何运行起来的呢?让我们从入口文件先分析起来吧:
package mainimport ( _ "quickstart/routers" "github.com/astaxie/beego")func main() { beego.Run()}
我们看到main函数是入口函数,但是我们知道Go的执行过程是如下图所示的方式:
这里我们就看到了我们引入了一个包_ "quickstart/routers"
,这个包只引入执行了里面的init函数,那么让我们看看这个里面做了什么事情:
package routersimport ( "quickstart/controllers" "github.com/astaxie/beego")func init() { beego.Router("/", &controllers.MainController{}) }
路由包里面我们看到执行了路由注册beego.Router
, 这个函数的功能是映射URL到controller,第一个参数是URL(用户请求的地址),这里我们注册的是 /
,也就是我们访问的不带任何参数的URL,第二个参数是对应的 Controller,也就是我们即将把请求分发到那个控制器来执行相应的逻辑,我们可以执行类似的方式注册如下路由:
beego.Router("/user", &controllers.UserController{})
这样用户就可以通过访问 /user
去执行 UserController
的逻辑。这就是我们所谓的路由,更多更复杂的路由规则请查询
再回来看看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 如何来处理逻辑的。
3、Controller运行机制
前面我们了解了如何把用户的请求分发到控制器,这小节我们就介绍大家如何来写控制器,首先我们还是从源码分析入手:
package controllersimport ( "github.com/astaxie/beego")type MainController struct { beego.Controller}func (this *MainController) Get() { this.Data["Website"] = "beego.me" this.Data["Email"] = "astaxie@gmail.com" this.TplNames = "index.tpl" }
上面的代码显示首先我们声明了一个控制器 MainController
,这个控制器里面内嵌了 beego.Controller
,这就是 Go 的嵌入方式,也就是MainController
自动拥有了所有 beego.Controller
的方法。
而 beego.Controller
拥有很多方法,其中包括 Init
、Prepare
、Post
、Get
、Delete
、Head
等 方法。我们可以通过重写的方式来实现这些方法,而我们上面的代码就是重写了 Get
方法。
我们先前介绍过 beego 是一个 RESTful 的框架,所以我们的请求默认是执行对应 req.Method
的方法。例如浏览器的是 GET
请求,那么默认就会执行 MainController
下的 Get
方法。这样我们上面的 Get 方法就会被执行到,这样就进入了我们的逻辑处理。(用户可以改变这个行为,通过注册自定义的函数名,更加详细的请参考)
里面的代码是需要执行的逻辑,这里只是简单的输出数据,我们可以通过各种方式获取数据,然后赋值到 this.Data
中,这是一个用来存储输出数据的 map,可以赋值任意类型的值,这里我们只是简单举例输出两个字符串。
最后一个就是需要去渲染的模板,this.TplNames
就是需要渲染的模板,这里指定了 index.tpl
,如果用户不设置该参数,那么默认会去到模板目录的 Controller/<方法名>.tpl
查找,例如上面的方法会去 MainController/Get.tpl
。
用户设置了模板之后系统会自动的调用 Render
函数(这个函数是在 beego.Controller 中实现的),所以无需用户自己来调用渲染。
当然也可以不使用模版,直接用 this.Ctx.WriteString
输出字符串,如:
func (this *MainController) Get() { this.Ctx.WriteString("hello")}
至此我们的控制器分析基本完成了,接下来让我们看看如何来编写 model。
4、Model逻辑
我们知道 Web 应用中我们用的最多的就是数据库操作,而 model 层一般用来做这些操作,我们的bee new
例子不存在 Model 的演示,但是bee api
应用中存在 model 的应用。说的简单一点,如果你的应用足够简单,那么 Controller 可以处理一切的逻辑,如果您的逻辑里面存在着可以复用的东西,那么就抽取出来变成一个模块。因此 Model 就是逐步抽象的过程,一般我们会在 Model 里面处理一些数据读取,如下是一个日志分析应用中的代码片段:
package modelsimport ( "loggo/utils" "path/filepath" "strconv" "strings")var ( NotPV []string = []string{"css", "js", "class", "gif", "jpg", "jpeg", "png", "bmp", "ico", "rss", "xml", "swf"})const big = 0xFFFFFFfunc 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 层的东西。
5、View渲染
在前面编写 Controller 的时候,我们在 Get 里面写过这样的语句 this.TplNames = "index.tpl"
,设置显示的模板文件,默认支持 tpl
和 html
的后缀名,如果想设置其他后缀你可以调用 beego.AddTemplateExt
接口设置,那么模板如何来显示相应的数据呢?beego 采用了 Go 语言默认的模板引擎,所以和 Go 的模板语法一样,Go 模板的详细使用方法请参考
我们看看快速入门里面的代码(去掉了 css 样式):
Beego Welcome to Beego!
Beego is a simple & powerful Go web framework which is inspired by tornado and sinatra.
Official website: { {.Website}}
Contact me: { {.Email}}
我们在 Controller 里面把数据赋值给了 data(map 类型),然后我们在模板中就直接通过 key 访问 .Website
和 .Email
。这样就做到了数据的输出。接下来我们讲讲解如何让静态文件输出。
6、静态文件处理
前面我们介绍了如何输出静态页面,但是我们的网页往往包含了很多的静态文件,包括图片、JS、CSS 等,刚才创建的应用里面就创建了如下目录:
├── static │ ├── css │ ├── img │ └── js
beego 默认注册了 static 目录为静态处理的目录,注册样式:URL 前缀和映射的目录:
StaticDir["/static"] = "static"
用户可以设置多个静态文件处理目录,例如你有多个文件下载目录 download1、download2,你可以这样映射:
beego.SetStaticPath("/down1", "download1") beego.SetStaticPath("/down2", "download2")
这样用户访问 URL http://localhost/down1/123.txt
则会请求 download1 目录下的 123.txt 文件。