beego web框架学习

栏目: Go · 发布时间: 6年前

内容简介:虽然接触go有一段时间了,但web框架一直没有接触。为了方便做CURD,所以这两天简单学了一下beego框架,为以后使用做准备。

虽然接触 go 有一段时间了,但web框架一直没有接触。

为了方便做CURD,所以这两天简单学了一下beego框架,为以后使用做准备。

点击下载文档

正文

Beego Web框架调研

ORM Object风格的INSERT操作 13

Orm Object风格的Read操作 14

QuerySelector风格的CURD 15

QueryBuilder风格的CURD 16

参考文档: https://beego.me/quickstart

下载依赖

$ go get -u github.com/astaxie/beego

$ go get -u github.com/beego/bee

生成框架

比如我最终要把项目上传到 https://github.com/owenliang/beego-demo ,那么就这样生成项目:

bin/bee new github.com/owenliang/beego-demo

框架会生成在$GOPATH/src/github.com/owenliang/beego-demo下面:

-rw-r–r– 1 liangdong staff 25 1 16 10:10 README.md

drwxr-xr-x 3 liangdong staff 96 1 16 10:05 conf

drwxr-xr-x 3 liangdong staff 96 1 16 10:05 controllers

-rw-r–r– 1 liangdong staff 129 1 16 10:05 main.go

drwxr-xr-x 2 liangdong staff 64 1 16 10:05 models

drwxr-xr-x 3 liangdong staff 96 1 16 10:05 routers

drwxr-xr-x 5 liangdong staff 160 1 16 10:05 static

drwxr-xr-x 3 liangdong staff 96 1 16 10:05 tests

drwxr-xr-x 3 liangdong staff 96 1 16 10:05 views

验证框架

需要配置IDE修改程序的工作目录,因为beego会根据工作目录相对路径查找模板和配置文件。

beego web框架学习

然后就可以运行main.go了:

beego web框架学习

代码很简单,引入了routers模块,启动了beego:

beego web框架学习

Routers模块会在init回调中注册路由到beego:

beego web框架学习

MainController渲染了一下views/index.tpl模板:

beego web框架学习

访问localhost:8080,页面正常:

beego web框架学习

参考文档: https://beego.me/docs/intro/

Bee工具

bee new创建web项目,bee api创建纯api项目。

bee run运行项目可以监听开发阶段的代码变化,实时自动编译,达到脚本语言的开发效率。

Bee run需要进入项目根目录执行:

beego web框架学习

bee generate用于生成mvc代码,后面遇到再说。

Controller

Conf/app.conf目录下,详细文档:

https://beego.me/docs/mvc/controller/config.md

runmode可以切换不同环境的多份配置,而runmode自身可以通过环境变量传递,从而实现不同环境不同配置的需要。

详细参考: https://beego.me/docs/mvc/controller/router.md

一共3种模式:固定路由、正则路由、自动路由

固定路由,要求URI完全匹配:

beego.Router( “/” , &controllers.MainController{})

正则路由,长相有点奇怪,举个栗子:

beego.Router(“/api/:id([0-9]+)“, &controllers.RController{})

controller取参的时候:

this.Ctx.Input.Param(“:id”)

自动路由,需要把你的controller对象注册上去:

beego.AutoRouter(&controllers.ObjectController{})

beego会反射这个controller对象的方法,生成路由表,比如:

/object/login 调用 ObjectController 中的 Login 方法

/object/logout 调用 ObjectController 中的 Logout 方法

还支持namespace,说白了就是具备某个URI前缀的路由表,我把原先的router改成这样:

funcinit() {

ns := beego.NewNamespace( “/v1” ,

beego.NSRouter( “/” , &controllers.MainController{}),

)

beego.AddNamespace(ns)

}

就可以访问localhost:8080/v1了。

我们的controller继承beego基类,有各种操作方法,controller里的数据已经被beego框架填充好了:

typeMainController struct {

beego.Controller

}

根据HTTP request的action的不同,会回调MainController的POST/GET/DELETE等方法,这些方法在beego.Controller中都有留空了实现,我们可以覆写。

func(c *MainController) Get() {

c.Data[ “Website” ] =

“beego.me”

c.Data[ “Email” ] =

“astaxie@gmail.com”

c.TplName =

“index.tpl”

}

另外prepare和finish方法是留给我们覆写的,在执行action之前和之后做一些自定义操作,例如:

func(c *MainController) Prepare() {

c.Data[ “Website” ] =

“beego.me”

c.Data[ “Email” ] =

“astaxie@gmail.com”

}

func(c *MainController) Get() {

c.TplName =

“index.tpl”

}

如果想防止跨站提交表单,看一下beego提供的API即可: https://beego.me/docs/mvc/controller/xsrf.md

获取参数

获取Get/Post参数: https://beego.me/docs/mvc/controller/params.md

比如请求: http://localhost:8080/v1/?arg=xxx ,可以这样获取参数:

func(c *MainController) Get() {

v := c.Input().Get( “arg” )

fmt.Println(v)

c.TplName =

“index.tpl”

}

也可以这样:

func(c *MainController) Get() {

v := c.GetString( “arg” )

fmt.Println(v)

c.TplName =

“index.tpl”

}

区别就是前者是取原始解析出来的字符串,后者是支持强类型转换到int之类的。

Beego也支持文件表单上传,就不说明了。

Session

beego支持session存储到redis/mysql之类的。

但是session的k-v最好别用struct作为value,否则序列化和反序列化很麻烦,就用普通int/string就行。

通常我们用redis,需要经历如下操作:

  1. 安装beego的providor:

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

然后在main.go中引入:

import _ “github.com/astaxie/beego/session/redis”

  1. 安装 redis 的driver:

go get github.com/gomodule/redigo

然后在main.go中引入:

_ “github.com/gomodule/redigo/redis”

  1. 启动redis:redis-server
  2. 配置beego使用redis session:

appname = beego-demo

httpport = 8080

runmode = dev

sessionon = true
sessionprovider = redis
sessionproviderconfig=127.0.0.1:6379

  1. 在beego中访问session,统计用户浏览次数:

func(c *MainController) Get() {

visit_times := 0

times := c.GetSession( “visit_times” )

iftimes != nil {

visit_times = times.(int)

}

visit_times += 1

c.SetSession( “visit_times” , visit_times)

c.Ctx.WriteString( “visit_times=” + strconv.Itoa(visit_times))

// c.TplName = “index.tpl”

}

beego.InsertFilter(pattern string, position int, filter FilterFunc, params …bool)

即在URI满足某个pattern规则的时候,会在某个生命期position插入该过滤回调filterFunc。

试了一下,某些position没有回调,用时候再追原因吧。

输出json

把结构体赋值给Data的json字段,然后调用ServeJSON就可以返回了:

typeResp struct {

Name string

Age int

}

func(c *MainController) Get() {

c.Data[ “json” ] = &Resp{Name: “owen” , Age: 20}

c.ServeJSON()

}

输入验证

MVC框架大多提供validator这种东西或者model,用来快速校验提交的表单数据是否合法。

Beego提供了一个库来简化验证工作,免得我们一个参数一个参数的去check: https://beego.me/docs/mvc/controller/validation.md ,这是需要安装的,等有需要再看。

错误处理

MVC框架一般支持运行出错的时候进入通用的error handler/error controller,beego也支持: https://beego.me/docs/mvc/controller/errors.md ,用error controller方式更简单合理。

日志管理

Beego封装了日志库,我们需要手动配置一波:

funcinit() {

// 配置日志

// 打印行号

beego.SetLogFuncCall( true )

// 配置文件日志(保存到beego.log, 日志最多保留1天, 最高级输出INFO日志)

beego.SetLogger(logs. AdapterFile , {"filename": "./beego.log", "maxdays": 1, "maxlines": 1, "level": 6} )

// 删除命令行日志

beego.BeeLogger.DelLogger(logs. AdapterConsole )

}

funcmain() {

beego.Run()

}

logger库支持多路输出,默认是输出到AdapterConsole,但是我把这一路删了,然后加了一路adpterFile输出到日志文件 。 日志支持按行数/大小/天滚动文件,上面我设置了maxliens:1,所以每打印1行日志,文件就被滚动换掉了:

-r–r—– 1 liangdong staff 1058 1 16 14:18 beego.2019-01-16.001.log

-r–r—– 1 liangdong staff 84 1 16 14:19 beego.2019-01-16.002.log

-rw-rw—- 1 liangdong staff 84 1 16 14:19 beego.log

Maxdays配置那些被归档的日志多久被删除,我设置的1天。

Beego框架本身就会打一些日志,我们程序也可以打:

func(c *MainController) Get() {

beego.Info( “heihei” )

c.Data[ “json” ] = &Resp{Name: “owen” , Age: 20}

c.ServeJSON()

}

更多细节参考:

https://beego.me/docs/mvc/controller/logs.md

https://beego.me/docs/module/logs.md

Beego提供了ORM库,以 mysql 为例。

先安装mysql的driver:

Go get github.com/go-sql-driver/mysql

再安装beego orm:

go get github.com/astaxie/beego/orm

数据库设置

在本地建好数据库:create database beego;

在main.go中做注册:

funcinit() {

// 注册driver

orm.RegisterDriver( “mysql” , orm. DRMySQL )

// 注册数据库( 最后2个数字是最大空闲连接和最大数据库连接数量)

orm.RegisterDataBase( “default” , “mysql” , “root:baidu@123@tcp(127.0.0.1:3306)/beego?charset=utf8&loc=Asia%2fShanghai” , 1, 10)

}

funcmain() {

beego.Run()

}

具体的mysql schema参考driver文档: https://github.com/go-sql-driver/mysql

注册model

在models目录下定义model:

packagemodels

typeUser struct {

Id int64

Name string orm:"size(64);unique"

// varchar(64), 唯一索引

}

可以用orm标签,指定各种属性告诉beego每个字段的约束,这个用途主要有2个:

  1. 保存model到数据库的时候,可以供beego检查
  2. 根据Model初始化table的时候,生成 sql 语句。

对于2)来说,我们通常会发现golang的web程序会自动创建table,这是通过model->table同步实现的:

funcinit() {

// 注册driver

orm.RegisterDriver( “mysql” , orm. DRMySQL )

// 注册数据库( 最后2个数字是最大空闲连接和最大数据库连接数量)

orm.RegisterDataBase( “default” , “mysql” , “root:baidu@123@tcp(127.0.0.1:3306)/beego?charset=utf8&loc=Asia%2fShanghai” , 1, 10)

// 注册model

orm.RegisterModel(&models.User{})

// 初始化table

orm.RunSyncdb( “default” , false , false )

}

在registerModel后,可以通过runsyncdb做一次建表,底层执行的就是create if not exists,所以model的标签这时候就发挥了作用。

比如size(64)其实就会导致name字段的类型是varchar(64),因为name是string类型。

查看数据库,user表已经建立:

| user | CREATE TABLE user (

id bigint(20) NOT NULL AUTO_INCREMENT,

name varchar(64) NOT NULL DEFAULT ”,

PRIMARY KEY ( id ),

UNIQUE KEY name ( name )

) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

更多细节参考: https://beego.me/docs/mvc/model/models.md

ORM Object风格的INSERT操作

插入:

funcInsertUser(user *User) (err error) {

// 每次请求的ormer需要新建, 不能并发使用

orm := orm.NewOrm()

// 插入

user.Id, err = orm.Insert(user)

return

}

创建user对象,完成插入:

func(c *MainController) Get() {

user := models.User{Name: “owen” }

iferr := models.InsertUser(&user); err == nil {

beego.Info( “插入用户:” , user)

c.Ctx.WriteString( “ok” )

} else {

c.Ctx.WriteString(err.Error())

}

}

执行1次插入了记录:

mysql> select * from user;

+—-+——+

| id | name |

+—-+——+

| 1 | owen |

+—-+——+

再执行报错:

Error 1062: Duplicate entry ‘owen’ for key ‘name’

说明name字段根据struct标签定义为unique了。

Orm Object风格的Read操作

定义方法:

funcFindUser(user *User) (err error) {

// 每次请求的ormer需要新建, 不能并发使用

orm := orm.NewOrm()

err = orm.Read(user)

return

}

然后查找:

func(c *MainController) Get() {

// 查找Id=1的记录

user := models.User{Id: 1}

iferr := models.FindUser(&user); err == nil {

c.Ctx.WriteString( “找到:” + user.Name)

} else {

c.Ctx.WriteString( “不存在” )

}

}

得到结果:

找到:owen

Delete和Update就不演示了,都是ORM对象风格,文档: https://beego.me/docs/mvc/model/object.md

QuerySelector风格的CURD

上述纯ORM object的底层基于query selector构建SQL,这套API风格类似于django,不建议深入了解,文档: https://beego.me/docs/mvc/model/query.md

原生SQL风格的CURD

类似于这样的:

var users []User

num, err := o.Raw(“SELECT id, user_name FROM user WHERE id = ?”, 1).QueryRows(&users)

仍旧支持struct的自动反序列化,我觉得这种就够用,不需要用ORM那些。

QueryBuilder风格的CURD

避免手写SQL的尴尬,给我们提供链式构造SQL的能力:

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)

比ORM灵活,比裸写SQL清晰,我喜欢这种。

很简单,围绕一个ORM()对象展开begin/rollback/commit:

https://beego.me/docs/mvc/model/transaction.md

详细文档: https://beego.me/docs/mvc/view/tutorial.md ,底层用的是Go标准库template,额外做了一些扩展。

下面举一个简单例子:

使用的时候,首先是准备模板数据放到controller的Data里,然后赋值TplName为相对于views目录的路径:

func(c *MainController) Get() {

// 查找Id=1的记录

user := models.User{Id: 1}

// 找到记录

if err := models.FindUser(&user); err == nil {

// 设置模板数据

c.Data[ “user” ] = &user

}

// 设置模板文件

c.TplName =

“main.html”

}

然后编写main.html:

{{ template “header.html” .}}

{{ if .user}}

欢迎你,{{.user.Name | htmlquote}}

{{ else }}

您没有登录!

{{ end }}

{{ template “footer.html” .}}

这里引入了另外2个模板,并且把当前的上下文参数通过.带给了2个嵌套模板。

Go语言动态的部分都要放在{{}}内,具体语法参考文档。

Header.html和footer.html不需要{{define}}也能用,比go template方便点。

Header.html:

<!DOCTYPE html >

< html lang=”en” >

< head >

< meta charset=”UTF-8″ >

< title >beego</ title >

</ head >

< body >

Footer.html:

< script ></ script >

</ body >

</ html >

博主无私的分享着知识,你愿意送他一顿热腾腾的早餐吗?

beego web框架学习

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Realm of Racket

Realm of Racket

Matthias Felleisen、Conrad Barski M.D.、David Van Horn、Eight Students Northeastern University of / No Starch Press / 2013-6-25 / USD 39.95

Racket is the noble descendant of Lisp, a programming language renowned for its elegance and power. But while Racket retains the functional goodness of Lisp that makes programming purists drool, it wa......一起来看看 《Realm of Racket》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器