GoWeb——Beego框架的使用

  • Post author:
  • Post category:其他




1、Beego框架概述

Beego是用Go语言开发的高效的HTTP框架,可以用来快速开发APl、Web应用及后端服务等各种应用。Beego是一个RESTful的框架,主要设计灵感来源于Tornado、Sinatra和Flask这3个框架。它还结合了Go语言自身的一些特性(接口、结构体嵌入等)。



1.1、Beego架构简介

Beego是基于多个独立模块构建的,是一个高度解耦的框架。最初在设计Beego时就考虑到了功能模块化,用户即使不适用Beego的HTTP逻辑,也可以独立使用这些模块(例如可以使用cache模块来处理缓存逻辑,使用日志模块来记录操作信息,使用config模块来解析各种格式

的文件)。



1.2、Beego的执行逻辑

在这里插入图片描述

执行逻辑可以拆分为以下几段:

  1. main文件监听启动端口接收请求。
  2. 请求经过路由和参数过滤功能被转发给绑定URL的控制器处理。
  3. 控制器(Controller)调用Model、Session管理、日志处理、缓存处理模块,以及辅助工具包进行相应的业务处理。其中,模型(Modl)通过ORM直接操作数据库。
  4. 业务处理完成,返回响应或视图(View)给请求方。



1.3、Beego项目基本结构

在实际的项目中,可能有增减或改动。

beego
- conf   #配置文件目录
	- app.conf #配置文件
- controllers #控制器目录
	- default.go #默认控制器文件
- main.go #入口
- models #模型目录
- routers #路由目录
	- router.go #路由文件
- static #静态文件目录
	- css # css文件目录
	- img #图片文件目录
	- js #js文件目录
- tests #测试文件目录
	- default_test.go #默认测试文件
- views #视图目录
	- index.tpl #默认视图文件



2、Beego安装



2.1、安装Beego核心包

go get -u github.com/astaxie/beego

# beego v2版本
go get -u github.com/beego/beego/v2



2.2、安装Beego orm包

Beego的orm包用于操作数据库,它是一个独立的模块,需要单独安装。最新开发版把orm包移动到了client目录下面,所以安装使用如下命令:

go get github.com/astaxie/beego/client/orm

之前的稳定版本安装使用如下命令:

go get github.com/astaxie/beego/orm

如果以上稳定版本命令无法下载orm包,则使用“go get github.com/astaxie/beego/client/orm”命令下载安装。



2.3、安装bee工具包

bee工具包是beego开发的辅助工具,用于快速创建项目、运行项目及打包项目。安装方法如下:

# go 1.16 以前的版本
go get -u github.com/beego/bee/v2
 
# go 1.16及以后的版本
go install github.com/beego/bee/v2@latest

安装完之后,bee 可执行文件默认存放在

$GOPATH/bin

里面,所以需要把

$GOPATH/bin

添加到环境变量中,才可以进行下一步。



3、创建并运行Beego第一个项目



3.1、使用bee创建项目

安装好bee工具包后,直接选择一个目录,打开命令行终端输入:

s bee new beego

命令行终端会返回如下信息,如果最后是“New application successfully created!”,则代表项目创建成功:

在这里插入图片描述



3.2、运行项目

在项目创建成功后,会生成一个名为“beego”的项目目录,可以通过bee工具运行项目。进入刚才创建好的项目根目录下,运行“bee run”命令:

cd ./beego
bee run

在这里插入图片描述

如果运行成功,则命令行终端会输出如下:

在这里插入图片描述

通过浏览器访问htp:/localhost:8080,可以看到“Welcome to Beego”页面,如图所示。

在这里插入图片描述



4、Beego参数配置



4.1、Beego默认参数

在默认情况下,conf/app.conf就是默认的配置文件。该文件的内容形式如下:

appname = beego #应用名称
httpport = 8080 #端口
runmode = dev #运行模式:dev、test、prod



4.2、Beego自定义参数

也可以自定义参数配置,然后通过beego.AppConfig对象的方法读取配置。例如,在app.conf增加下面自定义配置:

# MySQL数据库的配置参数
mysql_user = "root"
mysql_password = "123456"
mysql_host = "127.0.0.1:3306"
mysql_dbname = "beego"

下面是读取配置的代码:

beego.AppConfig.String("mysql_user")
beego.AppConfig.String("mysql_password")
beego.AppConfig.String("mysql_host")
beego.AppConfig.String("mysql_dbname")



4.3、不同运行级别的参数

在Beego中,runmode参数可以被设置为不同的运行级别,一般用来区分不用的运行环境,例如dev、test等。如果希望数据库配置在不同环境中账号密码都不一样,则可以使用如下配置方式:

# 配置运行级别
runmode = "dev"
[dev]
mysql_user = "root"
mysql_password = "123456"
mysql_host = "127.0.0.1:3306"
mysql_dbname = "beego"
[test]
mysql_user = "root1"
mysql_password = "123456"
mysql_host = "127.0.0.1:3306"
mysql_dbname = "beego"
[prod]
mysql_user = "root2"
mysql_password = "123456"
mysql_host = "127.0.0.1:3306"
mysql_dbname = "beego"

上面的例子,为dev、test、prod这3个环境配置了不同的数据库参数。在通过beego.AppConfig读取参数时,由runmode决定读取哪个环境的参数。



4.4、使用多个配置文件

在实际项目中,一般都使用多个配置文件管理配置,多个配置文件也方便模块化管理配置。例如,新建一个名为ysql.conf的配置文件,用来保存数据库配置。该文件的内容如下:

[dev]
mysql_user = "root"
mysql_password = "123456"
mysql_host = "127.0.0.1:3306"
mysql_dbname = "beego"

在conf/app.conf主配置文件中,通过“include”命令将小ySQL配置文件包含进去:

appname = beego
httpport = 8080
runmode = dev

#包含MySQL配置文件
include "mysql.conf"

这种通过“include”命令包含其他配置文件的方式,跟把所有配置都写在一个配置文件的效果是一样的。区别就是:在使用多个配置文件时,各个模块的配置更加清晰。

无论是使用“include’”命令包含配置文件,还是直接将所有配置都写在一个配置文件,读取配置的方式是一样的。



5、Beego控制器



5.1、路由配置

Beego提供两种设置处理器函数的路由配置的方式。



5.1.1、直接绑定处理器函数。

直接绑定处理器函数,就是直接将一个URL路由和一个函数绑定起来。示例如下:

//将URL和一个匿名函数绑定起来,这个URL的GET请求由这个匿名函数处理
beego.Get("/hello", func(ctx *context.Context) {
	ctx.Output.Body([]byte("hi beego"))
})

// 定义一个处理器函数
func Index(ctx *context.Context) {
	ctx.Output.Body([]byte("hello beego"))
}

//将URL /index路由和index()函数绑定起来,由Index()函数处理这个URL的POST请求
beego.Post("/index", Index)

在这里插入图片描述

在这里插入图片描述

下面是Beego支持的常用基础函数:

beego.Get (router, beego.FilterFunc)
beego.Post (router, beego.FilterFunc)
beego.Any (router, beego.FilterFunc)

其中beego.Any()函数用于处理任意HTTP请求,可以根据不同的HTTP请求方法选择用不同的函数设置路由。



5.1.2、绑定一个控制器对象

Beego默认支持RESTful风格。RESTful路由使用beego.Router()函数设置。

示例如下:

// “/”的所有HTTP请求方法都由MainController控制器的对应函数处理
beego.Router("/",&controllers.MainController{))
// “/user”的所有HTTP请求方法都由UserControl1er控制器的对应函数处理
// 例如:GET/user请求由Get()函数处理,P0ST/user请求由Post()函数处理
beego.Router("/user",&controllers.UserController{})



5.1.3、URL路由方式

1.固定路由

前面介绍的URL路由例子都属于固定路由方式。固定路由是指URL规则是固定的一个URL。

示例如下:

beego.Router("/user",&controllers.UserController{})

2.正则路由

正则路由比较灵活。一个正则路由代表的是一序列的URL。正则路由更像是一种URL模板。

URL正则路由示例如下:

/user/:id
/user/:id([0-9]+)
/user/:username([\w]+)
/1ist_:cat([0-9]+)_:page([0-9]+).html
/api/*

在Controller对象中,可以通过下面的方式获取URL路由匹配的参数:

this.Ctx.Input.Param(":id")

3.自动路由

自动路由是指,通过反射获取控制器的名字和控制器实现的所有函数名字,自动生成URL路由。使用自动路由,需要用beego.AutoRouter()函数注册控制器。

示例如下:

beego.AutoRouter(&controllers.UserController())

然后可以通过如下形式访问路由:

/user/1ogin //调用UserContro11er中的Login()方法

除前缀两个“

/:Controller/:Method

”形式的匹配外,对于剩下的URL,Beego会自动将它们解析为参数保存在this.Ctx.Input.Params中。

4.路由命名空间

路由命名空间(namespace),一般用来做API接口开发版本处理。示例如下:

//创建版本2的命名空间
ns2 := beego.NewNamespace("/v2", 
	beego.NSNamespace("/user",
		//URL路由: /v2/user/info
		beego.NSRouter("/info", &controllers.User2Controller{})
	),
)
//注册namespace
beego.AddNamespace(ns2)

通过NewNamespace()函数可以创建多个命名空间,NSNamespace()函数可以无限嵌套命名空间。从上面的例子可以看出来,命名空间的作用其实就是定义URL路由的前缀。如果一个命名空间定义URL路由为“/user”,则这个命名空间下面定义的所有路由的前缀都是以“/user”开头的。

下面是命名空间支持的常用路由设置函数:

NewNamespace(prefix string, funcs ...interface{})
NSNamespace(prefix string, funcs ...interface())
NSPost (rootpath string, f FilterFunc)

这些路由设置函数的参数,跟前面的路由设置函数类似,

区别是:命名空间的函数名前面多了NS前缀。



5.2、控制器函数

控制器函数是指处理用户请求的函数。Beego框架支持beego.FilterFunc()函数和控制器函数两种处理用户请求的函数。



5.2.1、beego.FilterFunc()函数

beego.FilterFunc()是最简单的请求处理函数,其定义如下:

type FilterFunc func(*context.Context)

即只要定义一个函数,并且接收一个Context参数,则这个函数就可以作为处理用户请求的函数。示例如下:

func DoLogin(ctx *context.Context){
	//省去处理请求的逻辑
	//通过Context获取请求参数,返回请求结果
}

有了处理函数,就可以将处理函数跟一个URL路由绑定起来。示例如下:

beego.Get ("/user/login", DoLogin)



5.2.2、控制器函数

控制器函数是Beego的RESTful API的实现方式。在Beego的设计中,控制器就是一个嵌套了beego.Controller的结构体对象。示例如下:

//定义一个新的控制器
type UserController struct {
	//嵌套beego基础控制器
	beego.Controller
}

结构体嵌套类似于其他高级语言中的“继承”特性,嵌套beego.Controller控制器,就拥有了beego.Controller定义的属性和方法。



5.3、获取请求参数

基础控制器beego.Controller,提供了多种读取请求参数的函数。

下面分别介绍各种获取参数的场景。



5.3.1、默认获取参数方式

基础控制器beego.Controller提供了形如“GetXXX()”的一系列函数来获取参数,其中“XXX”是指返回不同的数据类型,比如GetInt()等函数。示例如下:

type UserController struct {
	beego.Controller
}

//处理GET请求
func (this *UserController) Get() {
	//获取参数,返回int类型
	id, _ := this.GetInt("uid")
	//获取参数,返回string类型。如果参数不存在,则返回none作为默认值
	username := this.GetString("username", "none")
	//获取参数,返回float类型。如果参数不存在,则返回0作为默认值
	balance, _ := this.GetFloat("balance", 0)
	str := fmt.Sprint("id:", id, "\tusername:", username, "\tbalance:", balance)
	this.Ctx.Output.Body([]byte(str))
}

注册路由:

beego.Router("/user", &controllers.UserController{})

在这里插入图片描述

下面是常用的获取参数的函数定义:

GetString(key string,def ...string) string
GetInt(key string,def...int)(int, error)
GetBool(key string,def ...bool)(bool, error)

默认情况下,用户请求的参数都是字符串类型。如果要转换成其他类型,则有类型转换失败的可能性。因此除GetString()函数外,其他形如“GetXXX”的函数都返回两个值:第1个值是需要获取的参数值;第2个值是error,表示是数据类型转换是否失败。



5.3.2、绑定结构体方式

针对POST请求的表单数据,Beeg0支持直接将表单数据绑定到一个结构体变量。示例如下:

//定义一个结构体用来保存表单数据
type UserForm struct {
	//忽略掉Id字段
	Id int `form:"-"`
	//表单字段名为name
	Name string `form:"name"`
	Phone string `form:"phone"`
}

如果表单的字段跟结构体的字段(小写)同名,则不需要设置fom标签。表单的HTML代码示例如下:

<form acton="/user" method="POST">
	手机号:<input name="phone" type="text" /><br/>
	用户名:<input name="name" type="text" />
<input type="submit" value="提交" />
</form>

表单对应的控制器函数代码示例如下:

//处理POST请求,绑定结构体获取参数
func (this *UserController) Post() {
	//定义保存表单数据的结构体对象
	u := models.UserForm{}
	//通过ParseForm()函数,将请求参数绑定到结构体变量
	if err := this.ParseForm(&u); err != nil {

	}
	this.Ctx.Output.Body([]byte(u.ToString()))
}

在这里插入图片描述

用struct绑定请求参数的方式,仅适用于POST请求。



5.3.3、处理JSON请求参数

一般在接口开发时,有时会将JSON请求参数保存在HTTP请求的请求体中。这时就不能使用绑定结构体方式获取JSON数据,需要直接读取请求体的内容,然后格式化数据。处理JSON参数的步骤如下:

  1. 在app.conf配置文件中添加一行:

    CopyRequestBody=true

  2. 通过

    this.Ctx.Input.RequestBody

    语句获取HTTP请求中请求体的内容。
  3. 通过

    json.Unmarshal()

    函数反序列化JSON字符串,将JSON参数绑定到结构体变量。

JSON请求参数的示例如下:

//JSON结构体
type UserJson struct {
	//忽略掉Id字段
	Id int `json:"-"`
	//JSON字段名为name
	Name string `json:"name"`
	Phone string `json:"phone"`
}

func (this *UserJson) ToString() string {
	str := "name:" + this.Name + ",phone:" + this.Phone
	return str
}

控制器代码:

type UserJsonController struct {
	beego.Controller
}

// 处理GET请求,默认获取参数
func (this *UserJsonController) Post() {
	u := models.UserJson{}
	
	//获取请求题内容
	body := this.Ctx.Input.RequestBody
	//反序列化JSON数据,将结果保存到u
	if err := json.Unmarshal(body, &u); err != nil {
		
	}
	this.Ctx.Output.Body([]byte(u.ToString()))
}

注册路由:

beego.Router("userjson", &controllers.UserJsonController{})

在这里插入图片描述

如果请求参数是XML格式,则XML的参数会被保存在请求体中。



5.4、响应请求

在处理完用户的请求后,通常会返回HTML代码,然后浏览器就可以显示HTML内容。除返回HTML外,在API接口开发中,还可以返回JSON、XML、JSONP格式的数据。

如果使用Beego开发API,则需要在app.conf中设置AutoRender=false,以禁止自动渲染模板,否则Beego每次处理请求都会尝试渲染模板,如果模板不存在则会报错。



5.4.1、返回JSON数据

// JSON结构体
type UserJson struct {
	//忽略掉Id字段
	Id int `json:"-"`
	//JSON字段名为name
	Name  string `json:"name"`
	Phone string `json:"phone"`
}

func (this *UserController) Get() {
	//返回JSON数据
	user := models.UserJson{1, "tom", "123456"}
	//讲需要返回的数据赋值给json字段
	this.Data["json"] = &user
	//将数据序列化成json字符串,然后返回给客户端
	this.ServeJSON()
}

在这里插入图片描述



5.4.2、返回XML数据

// XML结构体
type UserXml struct {
	//忽略掉Id字段
	Id int `xml:"-"`
	//JSON字段名为name
	Name  string `xml:"name"`
	Phone string `xml:"phone"`
}

func (this *UserController) Get() {
	//返回XML数据
	user := models.UserXml{1, "tom", "123456"}
	//将需要返回的数据赋值给XML字段
	this.Data["xml"] = &user
	//序列化并返回
	this.ServeXML()
}

在这里插入图片描述



5.4.3、返回JSONP数据

func (this *UserController) Get() {
	//返回JSONP数据
	user := models.UserJson{1, "tom", "123456"}
	//将需要返回的数据赋值给JSONP字段
	this.Data["jsonp"] = &user
	//序列化
	this.ServeJSONP()
}



5.4.4、返回HTML代码

如果开发的是网页,则通常需要返回HTML代码。在Beego项目中,是模板引擎技术渲染HTML代码,然后将结果返给浏览器。示例如下:

func (c *MainController) Get() {
	// 设置模板参数
	c.Data["Website"] = "beego.vip"
	c.Data["Email"] = "astaxie@gmail.com"
	// 需要渲染的模板,Beego会渲染这个模板然后返回结果
	c.TplName = "index.tpl"
}



5.4.5、添加响应头

//通过this.Ctx.Output.Header设置响应头
this.Ctx.Output.Header("Cache-Control", "no-cache, no-store, must-revalidate")



6、Beego模型

在Beego中,模型默认使用Beego ORM对进行数据库相关操作。


Beego ORM



7、Beego模板

Beego的视图(View)模板引擎是基于Go原生的模板库(html/template)进行开发的。Beego的模板默认支持“tpl”和“html”

后缀名。



7.1、模板基础示例

新建一个名为index.html的模板文件,其代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户个人信心:</h1>
    <p>
        用户名:{{.user.Name}}<br/>
        注册时间:{{.user.Phone}}
    </p>
</body>
</html>

控制器:

func (this *UserController) Get() {
	//渲染视图
	user := models.UserForm{1, "tom", "123456"}
	this.Data["user"] = user
	//设置要渲染的模板路径,即views目录下面的相对路径
	//如果不设置TplName,则beego默认按照 "<控制器名字>/<方法名>.tpl"  格式去查找模板文件
	this.TplName = "user/index.html"
	//如果关闭了自动渲染,则需要手动调用渲染函数。默认开启自动渲染
	this.Render()
}

在这里插入图片描述



7.2、模板标签冲突

默认情况下,模板引擎使用“{

{模板表达式}}”作为模板标签。假如前端开发使用的是React、Angular之类的框架,则会因为这些前端框架也使用“{

{模板表达式}}”作为模板标签而造成冲突。可以通过修改Go模板引擎的默认标签,来解决模板标签冲突问题。示例如下:

//修改Go的模板标签
beego.TemplateLeft = "<<<"
beego.TemplateRight = ">>>"

修改后的模板表达式:

<<<.user.phone>>>



8、Beego处理session

Beego内置的session模块,在Beego的设计中可以自由配置。目前session模块支持Memory、cookie、File、MySQL、Redis等常用的存储引擎。



8.1、session基本配置

在app.conf配置文件中加入如下配置,然后重启Beego程序即可生效。

首先打开session,这一步是必须的,否则Beego默认不会开启session:

sessionon = true

设置session id的名字,这个通常都是保存在客户端cookie里面:

sessionname = "beegosessionID"

设置Session的过期时间,默认3600s:

sessiongcmaxlifetime = 3600

设置session id的过期时间,因为session id是保存在cookie中的:

SessionCookieLifeTime = 3600

app.conf:

appname = beego
httpport = 8080
runmode = dev

# 处理JSON请求参数
copyrequestbody = true

# 禁止自动渲染模板
autorender = false
#包含MySQL配置文件
include "mysql.conf"

sessionon = true # 开启session
sessionname = "beegosessionID" # beegosessionID
sessiongcmaxlifetime = 3600 # session过期时间
SessionCookieLifeTime = 3600 # session id 的过期时间,因为其保存在cookie中



8.2、session读写示例

下面是一个在控制器函数中操作session的示例:

func (c *MainController) Get() {
	// 设置模板参数
	c.Data["Website"] = "beego.vip"
	c.Data["Email"] = "astaxie@gmail.com"
	//读取session数据
	v := c.GetSession("count")
	if v == nil {
		//写入session数据
		c.SetSession("count", int(1))
		c.Data["num"] = 0
	} else {
		c.SetSession("count", v.(int) + 1)
		c.Data["num"] = v.(int)
	}
	// 需要渲染的模板,Beego会渲染这个模板然后返回结果
	c.TplName = "index.tpl"
}

在Beego的session包中,数据的读写函数如下。

  • SetSession(name string,value interface{}):设置session值;
  • GetSession(name string)interface{}:读取session值;
  • DelSession(name string):删除指定的session值;
  • SessionRegeneratelD():生成新的session id;
  • DestroySession():销毁session;



8.3、配置session的存储引擎

session的存储引擎默认是Memory,即session数据默认保存在运行Beego程序的机器内存中。下面分别介绍常用session存储引擎的配置方式。



8.3.1、将session数据保存到文件中

#设置session,保存到文件中
sessionprovider = "file"
#设置session数据的保存目录
sessionproviderconfig = "./data/session"



8.3.2、将session数据保存到Redis中

安装Beego的Redis驱动程序:

go get github.com/astaxie/beego/session/redis

通过import语句导入Redis驱动程序:

import "github.com/astaxie/beego/session/redis"

修改conf/app.conf配置如下:

#设置session的存储引擎
sessionprovider = "redis"
#Redis存储引擎配置
#Redis配置格式:Redis地址,Redis连接池最大连接数,Redis密码
#Redis.连接池和Redis密码配置,没有保持为空
sessionproviderconfig = "127.0.0.1:6379,1000,123456"



9、Beego项目部署



9.1、项目打包

之前介绍过bee工具,在项目根目录执行下面命令即可完成项目打包:

$ bee pack

在打包完成后,在当前目录下会生成一个“.gz”后缀的压缩包。



9.2、独立部署

独立部署是指直接将上面得到的压缩包上传到服务器,解压缩后直接运行Go程序。

进入项目目录下,打开命令行终端输入如下命令即可:

nohup ./beepkg &



9.3、Beego热更新

热更新是指,在不中断服务的情况下完成程序升级。

Beego项目默认已经实现了热更新。下面介绍Beego如何实现热更新。

首先在app.conf配置文件中打开热更新配置:

Graceful = true

假设目前老版本的程序正在运行,进程ID是2367。现在将新版本的Beego程序压缩包上传到服务器中,解压缩,直接覆盖老的文件。

然后触发Beego程序热更新,具体命令如下:

kill -HUP 进程ID

上面这个命令的意思是给指定进程发送一个HUB信号,Beego程序在接收到这个信号后就开始处理热更新操作。如果老版本的进程ID是8689,则命令如下:

kill -HUP 8689

执行命令后就完成了热更新操作。



版权声明:本文为cold___play原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。