Beego框架

Beego介绍与安装

Beego是一个使用Go语言来开发Web应用额GoWeb框架,诞生于2012年。可以快速开发API、Web、后端服务等各种应用。
主要特点:

  • 简单化:使用MVC模型,支持RESTful;可以使用bee工具来提高开发效率,如果监控代码修改进行热编译、自动化测试代码、自动化打包部署。
    -智能化:封装了路由、支持智能路由、智能监控、监控内存消耗、CPU使用以及Goroutine的运行状况。
  • 模块化:对代码解耦封装、形成了session、cache、log、配置解析、性能监控、上下文操作、ORM等;
  • 高性能: Beego采用原生的Go原生的HTTP请求,Goroutine的并发效率应付大流量Web应用和API应用。

Beego安装

  1. mkdir beego
  2. cd beego
  3. go mod init beego
  4. go install github.com/beego/bee/v2@latest //先安装bee工具
  5. 安装完之后,bee 可执行文件默认存放在 $GOPATH/bin 里面,所以你需要把 $GOPATH/bin 添加到你的环境变量中,才可以进行下一步。
    如果你本机设置了 GOBIN,那么上面的bee命令就会安装到 GOBIN 目录下,所以我们需要在环境变量中添加相关的配置信息
#go语言安装主根目录
export GOROOT=/usr/local/go #替换你的目录
#GOPATH 是自己的go项目路径,自定义设置
export GOPATH=/Users/Lee/www/golang #替换你的目录
#GOBIN 当我们使用go install命令编译后并且安装的二进制程序目录
export GOBIN=$GOPATH/bin
# 启用 Go Modules 功能
export GO111MODULE=on
# 配置 GOPROXY 环境变量。你可以换成你喜欢的 proxy
export GOPROXY=https://goproxy.cn,direct
# 加入环境变量中
export PATH=$PATH:$GOROOT/bin:$GOBIN

安装完成之后 使用 bee version

______
| ___ \
| |_/ /  ___   ___
| ___ \ / _ \ / _ \
| |_/ /|  __/|  __/
\____/  \___| \___| v2.1.0

出现如此字样即安装ok,执行命令 bee new beego 即创建一个 beego项目。如果只是用来做api项目,可以用bee api beego,这样就不会有静态资源和view文件夹,多一个test文件夹。

bee run 命令可以启动并监控项目(热更新)
bee pack 目录用来发布应用的时候打包,会把项目打包成 zip 包,这样我们部署的时候直接把打包之后的项目上传,解压就可以部署了。

开发的时候最喜欢的命令:generate
可以一个命令生成 bee generate controller、model、view等方便快捷。

管理SQL的命令 migrate:
bee migrate: run all outstanding migrations
bee migrate rollback:rollback the last migration operation
bee migrate reset :rollback all migrations
bee migrate refresh:rollback all migrations and run them all again

配置模块

Beego 目前支持 INI、XML、JSON、YAML 格式的配置文件解析,也支持以 etcd 作为远程配置中心。
在conf/app.conf

路由

查看已经注册的所有路由:

    tree := web.PrintTree()
    methods := tree["Data"].(web.M)
    for k, v := range methods {
        fmt.Printf("%s => %v\n", k, v)
    }

控制器风格的路由:
web.CtrlGet("api/user/:id", UserController.GetUserById)

注册函数式风格路由注册:
该风格比较接近 Go 本身的语法特性,使用该风格,非常简单,可以直接采用函数式的写法:

func main() {
    web.Get("/hello", func(ctx *context.Context) {
        ctx.WriteString("hello, world")
    })

    web.Run()
}

增加前缀:
ctrl := &UserController{}
web.AutoPrefix("api", ctrl)

获取路由参数

/api/order/:id/detail
id := ctrl.Ctx.Input.Param(":splat")

如果是多段的,例如/api/*/name/*/detail,那么:splat只能获得最后一段的数据

/api/:username/profile
username := ctrl.Ctx.Input.Param(":username")

Get类 方法:
name := ctrl.GetString("name","jack") //默认值是jack

把输入转换为结构体:

type MainController struct {
    web.Controller
}

func (ctrl *MainController) Post() {
    user := User{}
    err := ctrl.BindJSON(&user)
    if err != nil {
        ctrl.Ctx.WriteString(err.Error())
        return
    }
    ctrl.Ctx.WriteString(fmt.Sprintf("%v", user))
}

type User struct {
    Age  int    `json:"age"`
    Name string `json:"name"`
}

web 上传和下载

文件上传之后一般是放在系统的内存里面,如果文件的 size 大于设置的缓存内存大小,那么就放在临时文件中,默认的缓存内存是 64M,你可以通过如下来调整这个缓存内存大小:

web.MaxMemory = 1<<22
或者在配置文件中通过如下设置:

maxmemory = 1<<22
与此同时,Beego 提供了另外一个参数,MaxUploadSize来限制最大上传文件大小——如果你一次长传多个文件,那么它限制的就是这些所有文件合并在一起的大小。

默认情况下,MaxMemory应该设置得比MaxUploadSize小,这种情况下两个参数合并在一起的效果则是:

如果文件大小小于MaxMemory,则直接在内存中处理;
如果文件大小介于MaxMemory和MaxUploadSize之间,那么比MaxMemory大的部分将会放在临时目录;
文件大小超出MaxUploadSize,直接拒绝请求,返回响应码 413

GetFile()该方法主要用于用户读取表单中的文件名 the_file,然后返回相应的信息,用户根据这些变量来处理文件上传、过滤、保存文件等。

SaveToFile(fromfile, tofile string) error:该方法是在 GetFile 的基础上实现了快速保存的功能。fromfile是提交时候表单中的name。

下载:
ctrl.Ctx.Output.Download("LICENSE", "license.txt")

Download方法的第一个参数文件路径,第二个参数是用户保存到本地时候的文件名。
如果第一个参数使用的是相对路径,那么它代表的是从当前工作目录开始计算的相对路径

XSRF跨站请求伪造

跨站请求伪造(Cross-site request forgery) (opens new window), 简称为 XSRF,是 Web 应用中常见的一个安全问题。
当前防范 XSRF 的一种通用的方法,是对每一个用户都记录一个无法预知的 cookie 数据,然后要求所有提交的请求(POST/PUT/DELETE)中都必须带有这个 cookie 数据。如果此数据不匹配 ,那么这个请求就可能是被伪造的。
直接在 main 入口处这样设置:
web.EnableXSRF = true
web.XSRFKEY = "61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o"
web.XSRFExpire = 3600
这样就需要前端传递给你的时候每次都要传递xsrf信息

两种方式:
在表单里面携带一个叫做 _xsrf 的字段,里面是 XSRF 的 Token;
在提交的请求的 HTTP HEADER 里面设置 X-Xsrftoken 或 X-Csrftoken,值就是 Token;

烦死了去跑步去。5km之后再来写。5.7km 跑完了接着写~

Orm的增删改查:

//单行插入

Insert(md interface{}) (int64, error)
InsertWithCtx(ctx context.Context, md interface{}) (int64, error)

InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error)
InsertOrUpdateWithCtx(ctx context.Context, md interface{}, colConflitAndArgs ...string)

批量插入
InsertMulti(bulk int, mds interface{}) (int64, error)
InsertMultiWithCtx(ctx context.Context, bulk int, mds interface{}) (int64, error)

更新
Update(md interface{}, cols ...string) (int64, error) //会主动寻找主键
UpdateWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)

使用主键来删除数据,定义:

Delete(md interface{}, cols ...string) (int64, error)
DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)

读取
Read(md interface{}, cols ...string) error
ReadWithCtx(ctx context.Context, md interface{}, cols ...string) error

事务

    // Beego will manage the transaction's lifecycle
    // if the @param task return error, the transaction will be rollback
    // or the transaction will be committed
    err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
        // data
        user := new(User)
        user.Name = "test_transaction"

        // insert data
        // Using txOrm to execute SQL
        _, e := txOrm.Insert(user)
        // if e != nil the transaction will be rollback
        // or it will be committed
        return e
    })

QuerySeter
// 获取 QuerySeter 对象,user 为表名
qs := o.QueryTable("user")
qs.Filter("profileage", 18) // WHERE profile.age = 18
qs.Filter("Profile
Age", 18) // 使用字段名和 Field 名都是允许的
qs.Filter("profileagegt", 18) // WHERE profile.age > 18

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

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

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

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

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

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

缓存模式

Read Through
Read Through 缓存模式本质上就是帮助你在缓存没有的情况下去数据库加载数据,并且回写缓存
Random Expire
这个模式主要用于解决缓存雪崩问题,即大量的 key 在同一时间过期,那么就可以考虑在设置 key-value 的时候,给过期时间加上一个随机偏移量

Singleflight
在 key 不存在,或者查询缓存失败的情况下,会有多个 goroutine 尝试去加载数据,那么使用该模式可以确保,一个 key 在当前进程里面只有一个 goroutine 去加载数据

Bloom Filter
该模式用于高并发环境下快速判断 key 对应的数据是否存在,比较适合解决缓存穿透问题。

日志模块

log := logs.NewLogger()
logs.EnableFuncCallDepth(true) 日志默认不输出调用的文件名和文件行号,如果你期望输出调用的文件名和文件行号 设置为true

数据校验

go get github.com/beego/beego/v2/core/validation
u := User{"man", 40}
valid := validation.Validation{}
valid.Required(u.Name, "name")
valid.MaxSize(u.Name, 15, "nameMax")
valid.Range(u.Age, 0, 18, "age")

type user struct {
Id     int
Name   string valid:"Required;Match(/^Bee.*/)" // Name 不能为空并且以 Bee 开头
Age    int    valid:"Range(1, 140)" // 1 <= Age <= 140,超出此范围即为不合法
Email  string valid:"Email; MaxSize(100)" // Email 字段需要符合邮箱格式,并且最大长度不能大于 100 个字符
Mobile string valid:"Mobile" // Mobile 必须为正确的手机号
IP     string valid:"IP" // IP 必须为一个正确的 IPv4 地址

}

定时任务

tk1 := task.NewTask("tk1", "0 12 ", func(ctx context.Context) error { fmt.Println("tk1"); return nil })

NewTask(tname string, spec string, f TaskFunc) *Task

tname: 任务名称
spec: 定时任务格式,请参考下面的详细介绍
f: 执行的函数

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注