文章

Beego

Beego

Beego介绍

beego是一个快速发开Go应用的HTTP框架

可以用来快速开发API、Web及后端服务等各种应用

GitHub地址:https://github.com/beego/beego

中文文档地址:https://beego.gocn.vip/beego/zh/developing/

安装bee工具

  1. 下载bee工具(Mac)(解决zsh: command not found: bee问题)
go get -u github.com/beego/bee/v2@master
  1. 安装完之后,bee可执行文件默认存放在$GOPATH/bin里面,需要把$GOPATH/bin添加到环境变量中,才可以进行下一步
  2. 终端执行go env, 找到对应的GOMODCACHE=所在的路径(/Users/yama/go/pkg/mod/github.com/beego/bee/v2@v2.0.4)然后执行go build,会生成一个bee的可执行文件,然后复制到/usr/local/bin目录下,再次执行bee version就完成了

image-20230129220916312

查看命令:bee

创建web项目-单体

new命令是新建一个Web项目,在命令行下执行bee new <项目名>就可以创建一个新的项目

new这个命令生成的一般是前后端没分离的项目

命令:

go mod tidy 整理现有的依赖,使用此命令来下载特定的模块,并删除已经不用的模块

go mod download 下载go.mod文件中指明的所有依赖,使用此命令来下载指定的模块

go run xxx.go 启动项目,访问项目

image-20230129222953708如果提示golang.org/x/sys/unix....//go:linkname must refer to declared function or variable报错,在对应的项目下使用go get -u golang.org/x/sys

创建api项目-接口服务

上面的new命令是用来新建web项目,不过很多用户使用beego来开发API应用

所以这个bee api命令就是用来创建API应用的

和web项目相比,少了static和views目录

api命令一般用于生成前后端分离的项目

go mod tidy 整理现有的依赖,使用此命令来下载特定的模块,并删除已经不用的模块

go mod download 下载go.mod文件中指明的所有依赖,使用此命令来下载指定的模块

go run xxx.go 启动项目,访问项目

generate命令

这个命令是用来自动化的生成代码的,包含了从数据库一键生成model,还包含了脚手架的,通过这个命令,让大家开发代码不再慢

例如:bee generate docs

bee generate docs
次命令含义:generate swagger doc file生产swagger文档文件

项目初始构建

构建项目

bee api quickstart
go mod tidy
bee generate docs

运行项目

在项目目录下使用bee run -gendoc=true -downdoc=true运行项目。第一次运行时会自动下载调试工具swagger。

-gendoc=true表示每次自动化的build文档。当项目文件中controller或者routers目录下有变动时,就需要添加这一句

-downdoc=true会自动的下载swagger文档查看器。仅需要在第一次运行时使用,他会自动下载调试工具swagger

访问http://localhost:8080/swagger可以看到调试界面

image-20230129231711323

MVC架构

什么是MVC:Model view Controller模型 视图 控制器

早期很多代码是混合在页面里面开发的, 比如php、java的jsp等,开发维护之分麻烦

架构:没有什么是加一层解决不了的

但是为了易于维护和使用作出以下规定:

  • 控制层专注于处理请求以及控制试图跳转
  • 视图专注于显示数据
  • 模型,实体类与数据库一一映射处理底层逻辑

用户只访问视图,访问一个页面 点击跳转…跳到控制层

再加一层service,登录业务,注销业务,这些业务加到中间业务层返回数据给控制器,视图跳转到视图层,显示数据

Dao:操作数据库,Model:控制业务操作,保存数据修改数据查询数据

Model

  • 业务处理:业务逻辑(Service)
  • 数据持久层:CRUD(Dao)

View

  • 展示数据

Controller

  • 接受用户的请求(req:请求参数、Session信息)
  • 交给业务层处理对应的代码
  • 控制视图的跳转
  • 登录-》接受用户的登录请求-》处理用户的请求(获取用户登录的参数,username,password)-》交给业务层处理登录业务(判断用户名密码是否正确)-》Dao层查询用户名和密码是否正确-》数据

路由

普通路由

RestFul 路由

自动注册路由

  1. 编写Controller

    • struct必须是大写
    • 方法也必须大写,不然访问不了
    package controllers
    
    import "github.com/beego/beego/v2/server/web"
    
    // 定义好UserController
    // 结构和下面所有的方法都需要大写字母开头
    //
    //localhost:8080/user
    type UserController struct {
       web.Controller
    }
    
    func (u *UserController) Hello() {
       u.Ctx.WriteString("user/hello")
    }
    func (u *UserController) Lgoin() {
       u.Ctx.WriteString("user/login")
    }
    
  2. 自动注册路由

    package routers
    
    import (
       beego "github.com/beego/beego/v2/server/web"
       "web-demo/controllers"
    )
    
    func init() {
       //自动注册路由
       beego.AutoRouter(&controllers.UserController{})
       //首页路由
       beego.Router("/", &controllers.MainController{})
    }
    

手动路由

//手动路由
//beego.Get("/index", func(ctx *context.Context) {
// 
//})
//beego.Post()

RestFul风格路由

//路由 /?:var
//Controller
//请求方式:请求的具体的方式;
beego.Router("/user/info/?:id", &controllers.UserController{}, "get:GetUserInfo")

处理请求参数

user.go

//localhost:8080/Register/username=yama&password=123456
func (u *UserController) Register() {
   //1。获取前端请求参数
   username := u.GetString("username")
   password := u.GetString("password")
   //2。调用具体的业务逻辑
   if username == "" || password == "" {
      u.Ctx.WriteString("注册失败")
   }
   u.Ctx.WriteString("注册成功。username=" + username)
}

表单对象传参

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<form action="/user/login" method="post">
    <p> 用户名:<input type="text" name="Username"></p>
    <p> 密码:<input type="password" name="Password"></p>
    <p><input type="submit" value="登录"></p>
</form>

</body>
</html>

router.go

beego.Router("/user/login", &controllers.UserController{}, "post:Login")

user.go

// 跳转到登录页
func (c *UserController) ToLogin() {
   c.TplName = "login.html"
}
func (u *UserController) Login() {
   type User struct {
      Username string `form:"Username"`
      Password string `form:"Username"`
   }
   postUser := User{}
   u.BindForm(&postUser)
   fmt.Println(postUser)
   u.Ctx.WriteString(postUser.Username + ",登录成功")
}

错误处理

在做web开发的时候,经常需要页面跳转和错误处理

比如登录失败跳转到首页或者登录页

  1. 重定向

user.go

if postUser.Username != "admin" {
   u.Redirect("/", 302)
}
  1. 404

router.go

//beego.ErrorHandler("404", func(writer http.ResponseWriter, request *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(writer, data)
//})
  1. controller

error.go

package controllers

import (
   "github.com/beego/beego/v2/server/web"
)

type ErrorController struct {
   web.Controller
}

func (c *ErrorController) Error404() {
   c.Data["content"] = "page not found"
   c.TplName = "404.html"
}

func (c *ErrorController) Error501() {
   c.Data["content"] = "server error"
   c.TplName = "501.html"
}

func (c *ErrorController) ErrorDb() {
   c.Data["content"] = "database is now down"
   c.TplName = "dberror.html"
}

router.go

beego.ErrorController(&controllers.ErrorController{})

Admin监控后台

默认Admin是关闭的,可以通过配置开启监控:

EnableAdmin = true

可以进行修改监听到地址和端口:

AdminAddr = "localhost"
AdminPort = 8088

session&cookie

会话

会话:用户打开一个浏览器,点击了很多超链接,访问多个web资源,关闭浏览器,这个过程可以称之为会话

有状态会话:一个通过来过教室,下次再来教室,我们就会知道这个同学,曾经来过,称之为有状态会话

保存会话的两种技术

cookie

  • 客户端技术(响应,请求)

session

  • 服务器技术,利用这个技术,可以保存用户的会话信息,我们可以把信息或者数据放在session中

user.go

// 统计页面访问次数
func (this *UserController) UserSession() {
   //往服务器存放一个cookie,并且设置过期时间
   //this.Ctx.SetCookie("name", "web cookie", 10)
   //设置一个加密cookie
   this.Ctx.SetSecureCookie("my-secret", "name", "web cookie")
   this.Data["name"], _ = this.Ctx.GetSecureCookie("my-secret", "name")

   v := this.GetSession("asta")
   if v == nil {
      this.SetSession("asta", int(1))
      this.Data["num"] = 0
   } else {
      this.SetSession("asta", v.(int)+1)
      this.Data["num"] = v.(int)
   }
   this.TplName = "index.tpl"
}

beegoORM

分层开发

model层 控制结构体与表映射关系,编写增删改查逻辑

service层调用model层查询数据,处理具体的业务逻辑

comtroller层接收用户请求,调用具体的service层处理,并响应回客户端

  1. 创建数据库
  2. Orm init 初始化数据库连接
  3. 结构体 - ORM - 数据库
  4. 执行同步
  5. CRUD

model/orm.go

package models

import (
   // don't forget this
   "github.com/beego/beego/v2/client/orm"
   _ "github.com/go-sql-driver/mysql"
)

func init() {

   //开启调试模式
   orm.Debug = true
   //同步结构体到表中
   // need to register models in init
   orm.RegisterModel(new(User))

   //连接数据库
   orm.RegisterDataBase("default", "mysql", "root:123456@tcp(127.0.0.1:3312)/beego?charset=utf8")

   // automatically build table
   orm.RunSyncdb("default", false, true)
}

model/user.go

package models

import (
   "fmt"
   "github.com/beego/beego/v2/client/orm"
   "time"
)

type User struct {
   // O 对象 R 关系 M 映射

   ID         int       `orm:"column(id);auto"`
   Name       string    `orm:"column(name)"`
   Email      string    `orm:"column(email)"`
   CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)"`
   UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)"`
}

// ORM CRUD
func UserInsert(user *User) int64 {
   //创建orm对象
   o := orm.NewOrm()
   //插入
   n, _ := o.Insert(user)
   if n > 0 {
      fmt.Println("数据插入成功!")
      return n
   }
   return 0
}

controllers/user.go

func (this *UserController) AddUser() {
   //模拟一个user数据
   user := new(models.User)
   user.Name = "yama"
   user.Email = "231092380@qq.com"

   //调用业务层来处理
   n := models.UserInsert(user)
   if n == 0 {
      this.Ctx.WriteString("插入失败!")
   } else {
      this.Ctx.WriteString("插入成功!")
   }

}

访问:http://localhost:8080/user/adduser 就会添加成功

定时任务

//创建定时任务 任务名字 定时 执行函数
tk1 := task.NewTask("tk1", "0/2 * * * * *", func(ctx context.Context) error {
   fmt.Println("定时任务执行了")
   return nil
})
//添加到任务列表中
task.AddTask("tk1", tk1)
//开始执行任务
task.StartTask()
defer task.StopTask()
License:  CC BY 4.0 test