一、Bee工具的使用

1、Bee 工具的安装:go get github/beego/bee​

2、Bee工具命令

Beego博文目录_sql

new命令:​​new​​​ 命令是新建一个 Web 项目,我们在命令行下执行 ​​bee new <项目名>​​​ 就可以创建一个新的项目。但是注意该命令必须在 ​​$GOPATH/src​​​ 下执行。最后会在 ​​$GOPATH/src​​ 相应目录下生成如下目录结构的项目:

myproject
├── conf
│ └── app.conf
├── controllers
│ └── default.go
├── main.go
├── models
├── routers
│ └── router.go
├── static
│ ├── css
│ ├── img
│ └── js
├── tests
│ └── default_test.go
└── views
└── index.tpl

Beego博文目录_json_02

创建API项目:bee  api  项目名称,目录结构如下:

apiproject
├── conf
│ └── app.conf
├── controllers
│ └── object.go
│ └── user.go
├── docs
│ └── doc.go
├── main.go
├── models
│ └── object.go
│ └── user.go
├── routers
│ └── router.go
└── tests
└── default_test.go

 Beego博文目录_sql_03

打开到项目目录运行:bee run

 Beego博文目录_sql_04

把项目打包成 zip 包: bee pack

Beego博文目录_json_05

 二、controller设计

1、配置文件设置:

# 项目名称
appname = hello

httpport = 8000
# 运行模式
runmode = dev

# 数据库配置
db.host = 127.0.0.1:3306
db.username = root
db.password = root
db.database = test
db.prefix = db_
db.charset = utf8
db.timezone = Asia/Shanghai


# 开启表单令牌
enablexsrf = true
xsrfkey = 61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o
xsrfexpire = 3600

# 开启session
sessionon = true
# session存储引擎
SessionProvider = file
# session存储位置
SessionProviderConfig = "./tmp"
# 存在客户端的 cookie 名称
SessionName = "beegosessionID"
# session 默认存在客户端的 cookie 的时间,默认值是 3600 秒
SessionCookieLifeTime = 3600
# 是否开启SetCookie, 默认值 true 开启
SessionAutoSetCookie = true
# session cookie 存储域名, 默认空
SessionDomain = ""

获取配置文件数据:

//获取数据库配置
host := beego.AppConfig.String("db.host")
username := beego.AppConfig.String("db.username")
password := beego.AppConfig.String("db.password")
database := beego.AppConfig.String("db.database")
charset := beego.AppConfig.String("db.charset")
timezone := beego.AppConfig.String("db.timezone")

2、路由设置:

//固定路由
beego.Router("/", &controllers.MainController{})

//自定义方法
beego.Router("/logout", &controllers.MainController{}, "get:Logout")
beego.Router("/register", &controllers.RegisterController{}, "get:DoGet;post:DoPost")
//默认请求Get方法
beego.Router("/login", &controllers.LoginController{})

//自动加载请求url
beego.AutoRouter(&controllers.ArticleController{})

3、控制器函数

​beego.Controller​​​ 实现了接口 ​​beego.ControllerInterface​​​,​​beego.ControllerInterface​​ 定义了如下函数:

  • Init(ct *context.Context, childName string, app interface{})
    这个函数主要初始化了 Context、相应的 Controller 名称,模板名,初始化模板参数的容器 Data,app 即为当前执行的 Controller 的 reflecttype,这个 app 可以用来执行子类的方法。
  • Prepare()
    这个函数主要是为了用户扩展用的,这个函数会在下面定义的这些 Method 方法之前执行,用户可以重写这个函数实现类似用户验证之类。
  • Get()
    如果用户请求的 HTTP Method 是 GET,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Get 请求。
  • Post()
    如果用户请求的 HTTP Method 是 POST,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Post 请求。
  • Delete()
    如果用户请求的 HTTP Method 是 DELETE,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Delete 请求。
  • Put()
    如果用户请求的 HTTP Method 是 PUT,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Put 请求.
  • Head()
    如果用户请求的 HTTP Method 是 HEAD,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Head 请求。
  • Patch()
    如果用户请求的 HTTP Method 是 PATCH,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Patch 请求.
  • Options()
    如果用户请求的HTTP Method是OPTIONS,那么就执行该函数,默认是 405,用户继承的子 struct 中可以实现了该方法以处理 Options 请求。
  • Finish()
    这个函数是在执行完相应的 HTTP Method 方法之后执行的,默认是空,用户可以在子 struct 中重写这个函数,执行例如数据库关闭,清理数据之类的工作。
  • Render() error
    这个函数主要用来实现渲染模板,如果 beego.AutoRender 为 true 的情况下才会执行。

4、xsrf跨站请求伪造

在配置文件中配置如下:

# 开启表单令牌
enablexsrf = true
xsrfkey = 61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o
# 过期时间
xsrfexpire = 3600

控制器中配置:

this.Data["xsrfdata"] = template.HTML(this.XSRFFormHTML())

html中配置:

<form action="/new_message" method="post">
{{ .xsrfdata }}
<input type="text" name="message"/>
<input type="submit" value="Post"/>
</form>

在JavaScript中配置:

jQuery.postJSON = function(url, args, callback) {
var xsrf, xsrflist;
xsrf = $.cookie("_xsrf");
xsrflist = xsrf.split("|");
args._xsrf = base64_decode(xsrflist[0]);
$.ajax({url: url, data: $.param(args), dataType: "text", type: "POST",
success: function(response) {
callback(eval("(" + response + ")"));
}});
};

5、请求数据处理

  a、获取表单参数

  • GetString(key string) string
  • GetStrings(key string) []string
  • GetInt(key string) (int64, error)
  • GetBool(key string) (bool, error)
  • GetFloat(key string) (float64, error)

  b、直接解析到struct中

func (this *MainController) Post() {
u := user{}
if err := this.ParseForm(&u); err != nil {
//handle error
}
}

  c、文件上传

//文件上传
func (this *BaseController) Upload() string {
f, h, err := this.GetFile("uploadName")
if err != nil {
fmt.Println(err)
return ""
}
if h.Filename == "" {
return ""
}

defer f.Close()
//文件后缀
ext := path.Ext(h.Filename)
//创建目录
dir := "static/upload/" + time.Now().Format("2006-01-02")
os.MkdirAll(dir, 777)

//文件名称
rand.Seed(time.Now().UnixNano())
randNum := rand.Intn(1000)
hashName := md5.Sum([]byte(time.Now().Format("2006_01_02_15_04_05") + string(randNum)))
fileName := fmt.Sprintf("%x", hashName) + ext
fpath := dir + "/" + fileName
this.SaveToFile("uploadName", fpath)
return fpath
}

5、session控制

  a、session操作函数

  • SetSession(name string, value interface{})
  • GetSession(name string) interface{}
  • DelSession(name string)
  • SessionRegenerateID()
  • DestroySession()

  b、session配置

# 开启session
sessionon = true
# session存储引擎
SessionProvider = file
# session存储位置
SessionProviderConfig = "./tmp"
# 存在客户端的 cookie 名称
SessionName = "beegosessionID"
# session 默认存在客户端的 cookie 的时间,默认值是 3600 秒
SessionCookieLifeTime = 3600
# 是否开启SetCookie, 默认值 true 开启
SessionAutoSetCookie = true
# session cookie 存储域名, 默认空
SessionDomain = ""

6、过滤器

//添加过滤器判断用户是否登录
var FilterUser = func(ctx * context . Context){
_, ok := ctx . Input . Session("id") . (int)
//构建url
url := beego . URLFor("LoginController.Get")
if !ok && ctx . Request . RequestURI != url {
ctx . Redirect(302, url)
}
}
beego . InsertFilter("/*", beego . BeforeRouter, FilterUser)

7、flash数据

它主要用于在两个逻辑间传递临时数据,flash 中存放的所有数据会在紧接着的下一个逻辑中调用后清除。一般用于传递提示和错误消息。它适合 ​​Post/Redirect/Get​​ 模式。

func (c *MainController) Post() {
flash:=beego.NewFlash()
setting:=Settings{}
valid := Validation{}
c.ParseForm(&setting)
if b, err := valid.Valid(setting);err!=nil {
flash.Error("Settings invalid!")
flash.Store(&c.Controller)
c.Redirect("/setting",302)
return
}else if b!=nil{
flash.Error("validation err!")
flash.Store(&c.Controller)
c.Redirect("/setting",302)
return
}
saveSetting(setting)
flash.Notice("Settings saved!")
flash.Store(&c.Controller)
c.Redirect("/setting",302)
}

8、URL构建

控制器中使用:

//控制器+方法名称
this.Redirect(beego.URLFor("ArticleController.List"), 302)

模板中使用:

{{urlfor "TestController.List"}}

 9、多种数据格式输出(xml、json、jsonp)

func (this *AddController) Get() {
mystruct := { ... }
this.Data["json"] = &mystruct
// 生成json数据
this.ServeJSON()
// xml数据
this.ServeXML()
// jsonp数据
this.ServeJSONP()
}

10、表单数据验证

待续。。。

11、错误处理

  a、抛出异常

  this.Abort("404")

  b、自定义404页面

func page_not_found(rw http.ResponseWriter, r *http.Request){
t,_:= template.New("404.html").ParseFiles(beego.BConfig.WebConfig.ViewsPath+"/404.html")
data :=make(map[string]interface{})
data["content"] = "page not found"
t.Execute(rw, data)
}

func main() {
beego.ErrorHandler("404",page_not_found)
beego.Router("/", &controllers.MainController{})
beego.Run()
}

12、日志处理

 一般在程序中我们使用如下的方式进行输出:

beego.Emergency("this is emergency")
beego.Alert("this is alert")
beego.Critical("this is critical")
beego.Error("this is error")
beego.Warning("this is warning")
beego.Notice("this is notice")
beego.Informational("this is informational")
beego.Debug("this is debug")

设置输出到文件:

beego.SetLogger("file", `{"filename":"logs/test.log"}`)

设置日志级别:

LevelEmergency
LevelAlert
LevelCritical
LevelError
LevelWarning
LevelNotice
LevelInformational
LevelDebug

beego.SetLevel(beego.LevelInformational)

设置输出调用的文件名和文件行号:

beego.SetLogFuncCall(true)

三、Model设计

 1、orm安装:

go get github.com/astaxie/beego/orm

2、连接数据库:

# 数据库配置
db.host = 127.0.0.1:3306
db.username = root
db.password = root
db.database = test
db.prefix = db_
db.charset = utf8
db.timezone = Asia/Shanghai


//获取数据库配置
host := beego.AppConfig.String("db.host")
username := beego.AppConfig.String("db.username")
password := beego.AppConfig.String("db.password")
database := beego.AppConfig.String("db.database")
charset := beego.AppConfig.String("db.charset")
timezone := beego.AppConfig.String("db.timezone")
dns := username + ":" + password + "@(" + host + ")/" + database + "?charset=" + charset + "&loc=" + url.QueryEscape(timezone)
fmt.Println(dns)
//连接数据库
// orm.RegisterDataBase("default", "mysql", "root:root@(127.0.0.1:3306)/test?charset=utf8")
orm.RegisterDataBase("default", "mysql", dns)
//生成表结构
orm.RunSyncdb("default", false, true)

3、CURD操作

o := orm.NewOrm()
user := new(User)
user.Name = "slene"

//添加
fmt.Println(o.Insert(user))

user.Name = "Your"
//修改
fmt.Println(o.Update(user))
//查询
fmt.Println(o.Read(user))
//删除
fmt.Println(o.Delete(user))

4、高级查询

a、exact、iexact

qs.Filter("name", "slene") // WHERE name = 'slene'
qs.Filter("name__exact", "slene") // WHERE name = 'slene'
// 使用 = 匹配,大小写是否敏感取决于数据表使用的 collation
qs.Filter("profile_id", nil) // WHERE profile_id IS NULL

qs.Filter("name__iexact", "slene")
// WHERE name LIKE 'slene'
// 大小写不敏感,匹配任意 'Slene' 'sLENE'

b、contains、icontains

qs.Filter("name__contains", "slene")
// WHERE name LIKE BINARY '%slene%'
// 大小写敏感, 匹配包含 slene 的字符


qs.Filter("name__icontains", "slene")
// WHERE name LIKE '%slene%'
// 大小写不敏感, 匹配任意 'im Slene', 'im sLENE'

c、in

qs.Filter("age__in", 17, 18, 19, 20)
// WHERE age IN (17, 18, 19, 20)


ids:=[]int{17,18,19,20}
qs.Filter("age__in", ids)
// WHERE age IN (17, 18, 19, 20)

d、gt、gte

qs.Filter("profile__age__gt", 17)
// WHERE profile.age > 17

qs.Filter("profile__age__gte", 18)
// WHERE profile.age >= 18

e、lt、lte

qs.Filter("profile__age__lt", 17)
// WHERE profile.age < 17

qs.Filter("profile__age__lte", 18)
// WHERE profile.age <= 18

f、startswith、istartswith

qs.Filter("name__startswith", "slene")
// WHERE name LIKE BINARY 'slene%'
// 大小写敏感, 匹配以 'slene' 起始的字符串

qs.Filter("name__istartswith", "slene")
// WHERE name LIKE 'slene%'
// 大小写不敏感, 匹配任意以 'slene', 'Slene' 起始的字符串

g、endswith、iendswith

qs.Filter("name__endswith", "slene")
// WHERE name LIKE BINARY '%slene'
// 大小写敏感, 匹配以 'slene' 结束的字符串


qs.Filter("name__iendswithi", "slene")
// WHERE name LIKE '%slene'
// 大小写不敏感, 匹配任意以 'slene', 'Slene' 结束的字符串

h、isnull

qs.Filter("profile__isnull", true)
qs.Filter("profile_id__isnull", true)
// WHERE profile_id IS NULL

qs.Filter("profile__isnull", false)
// WHERE profile_id IS NOT NULL

5、高级查询接口

  • type QuerySeter interface {
  • }
  • 每个返回 QuerySeter 的 api 调用时都会新建一个 QuerySeter,不影响之前创建的。
  • 高级查询使用 Filter 和 Exclude 来做常用的条件查询。囊括两种清晰的过滤规则:包含, 排除

6、原生SQL查询

  • type RawSeter interface {
  • }

  a、Exec

res, err := o.Raw("UPDATE user SET name = ?", "your").Exec()
if err == nil {
num, _ := res.RowsAffected()
fmt.Println("mysql row affected nums: ", num)
}

  b、QueryRow

  QueryRow 和 QueryRows 提供高级 sql mapper 功能,支持 struct

type User struct {
Id int
UserName string
}

var user User
err := o.Raw("SELECT id, user_name FROM user WHERE id = ?", 1).QueryRow(&user)

  c、QueryRows

type User struct {
Id int
UserName string
}

var users []User
num, err := o.Raw("SELECT id, user_name FROM user WHERE id = ?", 1).QueryRows(&users)
if err == nil {
fmt.Println("user nums: ", num)
}

  d、SetArgs

  改变 Raw(sql, args…) 中的 args 参数,返回一个新的 RawSeter,用于单条 sql 语句,重复利用,替换参数然后执行。

res, err := r.SetArgs("arg1", "arg2").Exec()
res, err := r.SetArgs("arg1", "arg2").Exec()

  e、Values

  返回结果集的 key => value 值

var maps []orm.Params
num, err := o.Raw("SELECT user_name FROM user WHERE status = ?", 1).Values(&maps)
if err == nil && num > 0 {
fmt.Println(maps[0]["user_name"]) // slene
}

7、构造查询

// User 包装了下面的查询结果
type User struct {
Name string
Age int
}
var users []User

// 获取 QueryBuilder 对象. 需要指定数据库驱动参数。
// 第二个返回值是错误对象,在这里略过
qb, _ := orm.NewQueryBuilder("mysql")

// 构建查询对象
qb.Select("user.name",
"profile.age").
From("user").
InnerJoin("profile").On("user.id_user = profile.fk_user").
Where("age > ?").
OrderBy("name").Desc().
Limit(10).Offset(0)

// 导出 SQL 语句
sql := qb.String()

// 执行 SQL 语句
o := orm.NewOrm()
o.Raw(sql, 20).QueryRows(&users)
type QueryBuilder interface {
Select(fields ...string) QueryBuilder
From(tables ...string) QueryBuilder
InnerJoin(table string) QueryBuilder
LeftJoin(table string) QueryBuilder
RightJoin(table string) QueryBuilder
On(cond string) QueryBuilder
Where(cond string) QueryBuilder
And(cond string) QueryBuilder
Or(cond string) QueryBuilder
In(vals ...string) QueryBuilder
OrderBy(fields ...string) QueryBuilder
Asc() QueryBuilder
Desc() QueryBuilder
Limit(limit int) QueryBuilder
Offset(offset int) QueryBuilder
GroupBy(fields ...string) QueryBuilder
Having(cond string) QueryBuilder
Subquery(sub string, alias string) string
String() string
}

8、事务处理

o := NewOrm()
err := o.Begin()
// 事务处理过程
...
...
// 此过程中的所有使用 o Ormer 对象的查询都在事务处理范围内
if SomeError {
err = o.Rollback()
} else {
err = o.Commit()
}

9、模型定义

除了开头的大写字母以外,遇到大写会增加 ​​_​​,原名称中的下划线保留