Beego 使用

发布时间: 更新时间: 总字数:3787 阅读时间:8m 作者: IP上海 分享 网址

Beego是一个Go开发的,开源的、高性能的web框架,常用于Web和Restfull API开发。

介绍

beego 是基于MVC的框架

什么是MVC

MVC基于分层原则实现:

  • M(Model) 模型,DB
  • V(View) 视图,Template
  • C(Controller) 控制器,Controller

处理过程:

  • Client发起请求: HTTP Protocol -> url/method/params
  • Server: url -router-> handler -> params -> db -> template -> html
    • 根据 URL 找到对应的 handler
    • 处理/解析数据(如参数等)
    • 调用数据库进行增、删、改、查
    • 渲染页面
    • 响应客户端

beego 使用

工具安装

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

创建项目

bee new demo

目录结构

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

10 directories, 8 files

配置

  • 服务端口

启动时指定:

web.Run(":8888")

配置文件指定 conf/app.conf(ini格式)

HTTPPort=8888
HTTPAddr=127.0.0.1
  • 应用配置 conf/app.conf
# 注释
# 项目名 html 模板中获取方式 {{ config "String" "AppName" "Name" }}
AppName=<name>
# dev(自动加载页面模板) or prod(default,缓存页面模板到内存)
#RunMode=prod
# 从环境变量获取配置,若获取不到,采用默认模式
#RunMode=${BEEGO_RUNMODE}
# 指定默认值
RunMode=${BEEGO_RUNMODE||dev}

# 拷贝body数据
CopyRequestBody=true

# 文件上传的缓冲内存大小,默认  64M
Maxmemory=1*1024*1024

# 服务名称,Response Server header
ServerName=xianbin

# Web 配置,自动寻找 tpl 渲染文件
AutoRender=true
ViewsPath=views
StaticDir=static

# 指定不同环境的配置
[dev]
HTTPPort=8080

[prod]
HTTPPort=80

# 自定义配置
# 获取 db section, err := web.AppConfig.GetSection("db")
# web.AppConfig.Int("StaticDir")
# web.AppConfig.Int("db::MySQLPort")
# 默认值:web.AppConfig.DefaultInt("MySQLPort", 3306)
[db]
MySQLHost=127.0.0.1
MySQLPort=3306
  • 配置拆分,创建 mysql.conf,并在 app.conf 中添加 include mysql.conf

代码自动生成

  • help generate
bee help generate
USAGE
  bee generate [command]

OPTIONS
  -conn
      Connection string used by the SQLDriver to connect to a database instance.

  -ddl
      Generate DDL Migration

  -driver
      Database SQLDriver. Either mysql, postgres or sqlite.

  -fields
      List of table Fields.

  -level
      Either 1, 2 or 3. i.e. 1=models; 2=models and controllers; 3=models, controllers and routers.

  -tables
      List of table names separated by a comma.

DESCRIPTION
  ▶ To scaffold out your entire application:

     $ bee generate scaffold [scaffoldname] [-fields="title:string,body:text"] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"]

  ▶ To generate a Model based on fields:

     $ bee generate model [modelname] [-fields="name:type"]

  ▶ To generate a controller:

     $ bee generate controller [controllerfile]

  ▶ To generate a CRUD view:

     $ bee generate view [viewpath]

  ▶ To generate a migration file for making database schema updates:

     $ bee generate migration [migrationfile] [-fields="name:type"]

  ▶ To generate swagger doc file:

     $ bee generate docs

  ▶ To generate a test case:

     $ bee generate test [routerfile]

  ▶ To generate appcode based on an existing database:

     $ bee generate appcode [-tables=""] [-driver=mysql] [-conn="root:@tcp(127.0.0.1:3306)/test"] [-level=3]

代码生成示例

# User
$ bee generate scaffold user -fields="uuid:string,username:string,email:string,display_name:string,status:string,role:string,email_verified:bool,email_verified_at:string,phone:string,phone_verified:bool,phone_verified_at:string,age:int,avatar_url:string,gender:string,location:string,address:string,blog:string,bio:string,company:string,created_at:string,updated_at:string" -driver=sqlite

# Application
$ bee generate scaffold application -fields="uuid:string,owner:string,name:string,display_name:string,organization:string,logo_url:string,default_avatar_url:string,website_url:string,description:string,enable_password:bool,password_type:string,password_salt:string,enable_signup:bool,enable_signin:bool,client_id:string,client_secret:string,redirect_uris:string,created_at:string,updated_at:string" -driver=sqlite

# Organization
$ bee generate scaffold organization -fields="uuid:string,owner:string,name:string,display_name:string,site_url:string,default_avatar_url:string,created_at:string,updated_at:string" -driver=sqlite

# Provider
$ bee generate scaffold provider -fields="uuid:string,owner:string,name:string,display_name:string,application:string,type:string,client_id:string,client_secret:string,logo_url:string,description:string,redirect_uris:string,created_at:string,updated_at:string" -driver=sqlite

$ bee generate controller news
  • router.go 中添加:
func init() {
    beego.Include(&controllers.ApplicationController{}) // 注意此行必须加
    beego.Include(&controllers.OrganizationController{})
    beego.Include(&controllers.ProviderController{})
    beego.Include(&controllers.UserController{})
}

路由

Beego 支持多种路由方式

简单路由示例

package main

import (
	"fmt"

	"github.com/beego/beego/v2/server/web"
	"github.com/beego/beego/v2/server/web/context"
)

func main() {
	// 静态路由
	// 绑定函数,以 GET 方式请求 / 时,通过该匿名函数处理
	web.Get("/", func(ctx *context.Context) {
		// 用户数据获取
		name := ctx.Input.Query("name")
		ctx.Output.Context.WriteString(fmt.Sprint("get your name is ", name))
	})

	// Post 请求
	web.Post("/", func(ctx *context.Context) {
		name := ctx.Input.Query("name")
		ctx.Output.Context.WriteString(fmt.Sprint("post your name is ", name))
	})

	// 任意请求,相同方式时,是否生效与代码的顺序有关
	web.Any("/any/", func(ctx *context.Context) {
		ctx.Output.Context.WriteString(fmt.Sprintf("you actions is %s", ctx.Request.Method))
	})

	// 正则路由,URL中定义正则字符串匹配,示例匹配 /number/ 格式路由,并放入 :id 参数中
	//web.Get("/:id(^\\d+$)/", func(ctx *context.Context) {
	// ? 表示没有 id 也匹配
	web.Get("/?:id(^\\d+$)/", func(ctx *context.Context) {
		// 用户数据获取
		//id := ctx.Input.Query(":id")
		id := ctx.Input.Param(":id")
		ctx.Output.Context.WriteString(fmt.Sprint("number url id is ", id))
	})
	// 不区分类型
	web.Get("/any/:any/", func(ctx *context.Context) {
		// 用户数据获取
		any := ctx.Input.Query(":any")
		ctx.Output.Context.WriteString(fmt.Sprint("any url id is ", any))
	})
	// 类型获取 /file/abc /file/a/b/c
	web.Get("/file/*", func(ctx *context.Context) {
		// 通过 splat 获取没有名字的参数
		splat := ctx.Input.Param(":splat")
		ctx.Output.Context.WriteString(fmt.Sprintf("file %s", splat))
	})
	// /ext/a.txt
	web.Get("/ext/*.*", func(ctx *context.Context) {
		path := ctx.Input.Param(":path") // a
		ext := ctx.Input.Param(":ext")   // txt
		ctx.Output.Context.WriteString(fmt.Sprintf("file path %s, ext %s", path, ext))
	})
	web.Run()
}

控制器

控制器路由示例

package main

import (
	"fmt"

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

// 定义 Controller
type CityController struct {
	web.Controller
}

// Restfull API
func (c *CityController) Get() {
	c.Ctx.WriteString(`{"data": 123}`)
}

func (c *CityController) Create() {
	c.Ctx.WriteString(c.Ctx.Request.Method)
}

func (c *CityController) Put() {

}

func (c *CityController) Delete() {

}

type RegexpController struct {
	web.Controller
}

func (c *RegexpController) Get() {
	c.Ctx.WriteString(c.Ctx.Input.Param(":id"))
}

type AutoController struct {
	web.Controller
}

func (c *AutoController) Test() {
	c.Ctx.WriteString(fmt.Sprintf("%s method: %s", "test", c.Ctx.Request.Method))
}

func main() {
	// url 和控制器绑定,默认匹配Get/Post/Put等方法
	//web.Router("/city/", &CityController{})
	// 自定义路由和函数Map
	web.Router("/city/", &CityController{}, "GET:Get;post:Create")
	// 正则路由
	web.Router("/regexp/?:id/", &RegexpController{})
	// 自动路由,自动将路由绑定到 "/auto/",/auto/test 自动将所有请求类型绑定到 Test 方法上
	web.AutoRouter(&AutoController{})

	web.Run()
}

控制器内置方法

package main

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

type CityController struct {
	web.Controller
}

func (c *CityController) Init(ctx *context.Context, controllerName, actionName string, app interface{}) {
	c.Controller.Init(ctx, controllerName, actionName, app)
	logs.Info("run Init func, controllerName: %s, actionName: %s", controllerName, actionName)
}

func (c *CityController) Prepare() {
	logs.Info("run Prepare func")
}

func (c *CityController) Get() {
	logs.Info("Get method")
	c.Ctx.WriteString(c.Ctx.Request.Method)
}

func (c *CityController) Render() error {
	logs.Info("run Render func")
	return c.Controller.Render()
}

func (c *CityController) Finish() {
	logs.Info("run Finish func")
}

func main() {
	web.Router("/city/", &CityController{})

	web.Run()
}

日志:

run Init func, controllerName: CityController, actionName: GET
run Prepare func
Get method
run Finish func

说明:

  • Prepare() 函数可以做认证拦截和信息注入
  • Render() 函数只有配置 c.TplName 时才执行
  • Render() 函数也可以执行其他批量的动作,如 c.ServeJSON()

过滤器

https://beego.vip/docs/mvc/controller/filter.md

请求数据

url 和 body 数据

package main

import (
	"encoding/json"
	"fmt"
	"strconv"

	"github.com/beego/beego/v2/core/logs"
	"github.com/beego/beego/v2/server/web"
)

// 定义 Controller
type CityController struct {
	web.Controller
}

type CityForm struct {
	X int `form:"x"`
	Y int // URL 必须是大写的 Y 才能匹配到
}

// Get 获取URL参数和Form(application/x-www-form-urlencoded)中数据示例
func (c *CityController) Get() {
	// http://127.0.0.1:8080/city/?x=1&y=2
	// 方法一
	c.Ctx.WriteString(c.Ctx.Input.Query("x"))
	c.Ctx.WriteString(c.Ctx.Input.Query("y"))
	c.Ctx.WriteString("\n")

	// 方法二
	var x string
	c.Ctx.Input.Bind(&x, "x")
	c.Ctx.WriteString(x)
	c.Ctx.WriteString("\n")

	// 方式三
	c.Ctx.WriteString(c.GetString("x"))
	xi, _ := c.GetInt("x")
	c.Ctx.WriteString(strconv.Itoa(xi))
	c.Ctx.WriteString("\n")

	// 方式四
	c.Ctx.Request.ParseForm()
	c.Ctx.WriteString(c.Ctx.Request.Form.Encode())
	c.Ctx.WriteString("\n")

	// 方式五
	var form CityForm
	c.ParseForm(&form)
	c.Ctx.WriteString(fmt.Sprintf("%#v", form))
	c.Ctx.WriteString("\n")

	// 获取 url router 参数
	c.Ctx.WriteString(fmt.Sprintf("%#v", c.Ctx.Input.Params()))
	c.Ctx.WriteString(c.Ctx.Input.Param("x"))
	c.Ctx.WriteString(c.Ctx.Input.Param("y"))
	c.Ctx.WriteString("\n")
}

// Post request body 参数获取示例
func (c *CityController) Post() {
	// 获取 form 数据
	//c.Ctx.Request.ParseForm()
	c.Ctx.WriteString(c.Ctx.Request.Method)
	c.Ctx.WriteString(c.Ctx.Request.Form.Encode())
	c.Ctx.WriteString("\n")

	// 方式二:仅获取 Post Form 数据
	c.Ctx.WriteString(c.Ctx.Request.PostForm.Encode())
	c.Ctx.WriteString("\n")

	//方式三,使用较多
	c.Ctx.WriteString(c.GetString("name"))
	c.Ctx.WriteString("\n")

	// 方式四,使用较多
	var form CityForm
	c.ParseForm(&form)
	c.Ctx.WriteString(fmt.Sprintf("%#v", form))
	c.Ctx.WriteString("\n")
}

type FileController struct {
	web.Controller
}

// Post 处理 form-data 文件上传
func (c *FileController) Post() {
	// 方式一
	//c.Ctx.Request.FormFile("abc")
	files := c.Ctx.Request.MultipartForm.File
	logs.Info("%#v", files)

	// 方式二
	//file := c.GetFile("abc")
	//defer file.Close()

	// 方式三
	c.SaveToFile("abc", "abc.json")

	//c.SaveToFileWithBuffer(fromFile string, toFile string, buf []byte) error {

	c.Ctx.WriteString(fmt.Sprintf("%#v", files))
}

type JsonController struct {
	web.Controller
}

// Post 处理 application/json 文件上传
func (c *JsonController) Post() {
	c.Ctx.Input.CopyBody(1 * 1024 * 1024) // 1Mb,必须加该行,或app.conf中配置,否则拿不到数据
	m := make(map[string]interface{})
	err := json.Unmarshal(c.Ctx.Input.RequestBody, &m)
	if err != nil {
		c.Ctx.WriteString(err.Error())
	} else {
		c.Ctx.WriteString(fmt.Sprintf("%#v\n", m))
	}
}

func main() {
	web.Router("/city/", &CityController{})
	web.Router("/file/", &FileController{})
	web.Router("/json/", &JsonController{})

	web.Run()
}

Header 数据

package main

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

type HeaderController struct {
	web.Controller
}

func (c *HeaderController) Get() {
	// 获取 header
	logs.Info("c.Ctx.Request.Header", c.Ctx.Request.Header)
	logs.Info("c.Ctx.Input.Header", c.Ctx.Input.Header("Path"))

	// 设置 header
	c.Ctx.ResponseWriter.Header().Add("h1", "v1")
	c.Ctx.Output.Header("h2", "v2")

	c.Ctx.WriteString("ok")
}

func main() {
	web.Router("/header/", &HeaderController{})

	web.Run()
}

读取和设置 Cookie 数据示例

package main

import (
	"net/http"

	"github.com/beego/beego/v2/core/logs"
	"github.com/beego/beego/v2/server/web"
)

// 定义 Controller
type CookieController struct {
	web.Controller
}

// Get curl -H "Cookie:name=value; name2=value2; name3=value3"
func (c *CookieController) Get() {
	// 获取 cookies
	// 方法一
	//c.Ctx.Request.Cookie(name)
	for _, cookie := range c.Ctx.Request.Cookies() {
		logs.Info("cookie: %s", cookie)
	}

	// 方法二
	c.Ctx.WriteString(c.Ctx.Input.Cookie("name"))
	c.Ctx.WriteString("\n")

	// 方式三
	c.Ctx.WriteString(c.Ctx.GetCookie("name"))

	cookie := http.Cookie{
		Name:  "namebeego1",
		Value: "value1",
	}
	http.SetCookie(c.Ctx.ResponseWriter, &cookie)
	c.Ctx.SetCookie("namebeego2", "valuebeego") // Get 方法没有生效?
	c.Ctx.WriteString("")
}

func (c *CookieController) Post() {
	// 设置 cookie
	// 方式一:
	cookie := http.Cookie{
		Name:  "namebeego1",
		Value: "v1",
	}
	http.SetCookie(c.Ctx.ResponseWriter, &cookie)
	c.Ctx.SetCookie("namebeego2", "v2")

	// SecureCookie 加密 cookie
	//c.SetSecureCookie()
	secret := "abcd"
	v3, result := c.GetSecureCookie(secret, "namebeego3")
	logs.Info("sc", v3, result)
	c.Ctx.SetSecureCookie(secret, "namebeego3", "v3")
	c.Ctx.WriteString("")
}

func main() {
	web.Router("/cookie/", &CookieController{})

	web.Run()
}

响应数据

模板

模板的基本使用

# 根据 Controller 查找 url
<form action="{{ urlfor `AuthController.Login` }}">
...
</form>

# form 定义
$ cat forms/auth.go
package auth

type LoginForm struct {
   Name string `form:"name"`
   Password string `form:"password"`
}

# 解析 form
c.ParseForm(&authForm)

# 数据库定义,ID 一般全大写

# 数据库初始化
$ cat models/db.go
package models

import (
   "database/sql"
)

var db *sql.DB

func init() {
   dns := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&local=PRC&parseTime=true",
      "user", "password", "host", "port", "db")
   db, err = sql.Open("mysql", dns)
   if err != nil {
      log.Fatal(err)
   }
   if err != db.Ping(); err != nil {
      log.Fatal(err)
   }
}

$ cat modules/user.go
package models

type User struct {
   Name string
   Password string
   CreateAd *time.Time // 时间一般使用指针
}

func GetUserByName(name string) *User {
}

$ cat utils/sql.go
package utils

import (
  "fmt"
  "strings"
)

func Like(q string) string {
  q = strings.TrimSpace(q)
  if q == "" {
    return q
  }

  // select ... where name like ? ESCAPE '/'
  strings.Replace(q, "/", "//", -1)
  strings.Replace(q, "%", "/%", -1)
  strings.Replace(q, "_", "/_", -1)

  return fmt.Sprintf("%%%s%%", q)
}
$ cat views/home.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home</title>
</head>
<body>
Name:
{{ .Name }}<br><br>
判断:<br>
{{ if eq .show true }}
show<br>
{{ else }}
not show
{{ end }}
<br>
遍历切片:
{{ range .city }}
{{ . }}<br>
{{ end }}
<br>
{{ range $index, $c := .city }}
{{ $index }}-{{ $c }}<br>
{{ end }}
<br>
遍历map:<br>
{{ range .region }}
{{ . }}<br>
{{ end }}
<br>
{{ range $key, $value := .region }}
{{ $key}} : {{ $value }}<br>
{{ end }}
<br>
自定义函数:{{ lower .UpperInfo }} - {{ .UpperInfo | lower }}<br>
<br>

模板定义:实现代码的复用<br>
{{ define "toLower" }}
{{ . }} : {{ . | lower }}
{{ end }}

{{ template "toLower" .UpperInfo }}
{{ template "toLower" .UpperInfo }}
{{ template "toLower" .UpperInfo }}
{{ template "toLower" .UpperInfo }}
<br><br>
{{ template "tpla.html" .UpperInfo }} {{ template "tpla.html" .UpperInfo }} <br>
</body>
</html>
$ cat views/tpla.html
{{ . | lower }}%
  • go 代码
package main

import (
	"strings"

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

type HomeController struct {
	web.Controller
}

func (c *HomeController) Get() {
	// 后缀只支持 *.html/*.tpl
	// 需要放到 path:views/
	// 默认加载控制器名称/action名.tpl模板文件
	// 传数据
	c.Data["Name"] = "xianbin"
	c.Data["show"] = true
	c.Data["city"] = []string{"shanghai", "shangqiu", "zhengzhou"}
	c.Data["region"] = map[string]string{"shanghai": "021", "shangqiu": "0370"}
	c.Data["UpperInfo"] = "XIEXIANBIN"
	// 指定模板
	c.TplName = "home.html"
}

func main() {
	// 自定义函数
	web.AddFuncMap("lower", func(str string) string {
		return strings.ToLower(str)
	})

	web.Router("/home/", &HomeController{})

	web.Run()
}

json/xml/yaml等格式

包括raw/json/xml/yaml等

package main

import (
	"encoding/xml"

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

// 定义 Controller
type RespController struct {
	web.Controller
}

func (c *RespController) Get() {
	c.Ctx.WriteString("c.Ctx.WriteString")
	c.Ctx.WriteString("\n")

	c.Ctx.Output.Body([]byte("c.Ctx.Output.Body"))
	c.Ctx.WriteString("\n")

	// 返回 json 数据
	// 方式一
	m := map[string]interface{}{"a": 1, "b": 2}
	c.Ctx.Output.JSON(m, true, true)
	c.Ctx.WriteString("\n")

	// 方式二
	c.Data["json"] = m
	c.ServeJSON()

	// 返回 yaml 数据
	c.Ctx.Output.YAML(m)
	c.Data["yaml"] = m
	c.ServeYAML()

	// 返回 xml 数据
	//x := struct {
	//	XMLName xml.Name
	//	Name    string `xml:"name"`
	//	Age     int    `xml:"age"`
	//}{XMLName: xml.Name{Space: "xiexianbin.cn", Local: "root"}, Name: "xianbin", Age: 18}
	x := struct {
		XMLName xml.Name `xml:"root"`
		Name    string   `xml:"name"`
		Age     int      `xml:"age"`
	}{Name: "xianbin", Age: 18}
	c.Ctx.Output.XML(x, true)

	c.Data["xml"] = x
	c.ServeXML()

	// 返回 html 模板
	//c.TplName = "xxx.html"  // 在 views 目录下

	// 重定向
	//c.Redirect("https://www.xiexianbin.cn", 302)

	// 停止执行
	//c.StopRun()

	// 抛出错误
	//c.Abort("404")
}

func (c *RespController) Post() {
	c.Ctx.WriteString("")
}

func main() {
	web.Router("/response/", &RespController{})

	web.Run()
}

Session

参考:

Session 的存储介质:

  • 内存,重启消失
  • 文件,单机部署使用
  • 数据库,如redis、memcache

配置信息

Session 在 beego 的配置文件中指定

# 是否开启
SessionOn=[truefalse]

# 存储位置
SessionProvider=[memory|file|mysql|redis]

# 存储的地址
SessionProviderConfig=[file文件路径|mysql datasourcename|redis host:port password]

# cookie 中 sessionid 的名字,用来屏蔽服务器信息
SessionName=sid

# 生命周期
SessionGCMaxLifetime = 3600s

Session 的操作

  • 存储
    • func (c *Controller) SetSession(name interface{}, value interface{}) error {}
    • key/value 可以是任意类型
    • 持久化编码方式 gob
  • 获取
    • func (c *Controller) GetSession(name interface{}) interface{} {}
  • 销毁
    • func (c *Controller) DelSession(name interface{}) error {}
    • c.DestorySession()
package main

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

type CityController struct {
	web.Controller
}

func (c *CityController) Get() {
	city := c.GetSession("city")
	if city == nil {
		logs.Info("get session city is nil")
		//c.Redirect("login", 302)
		err := c.SetSession("city", "shanghai")
		if err != nil {
			logs.Error(err)
		}
	} else {
		logs.Info("get session city is", city)
	}

	// 销毁session
	//c.DelSession(name)
	//c.DestroySession()

	c.Ctx.WriteString(`{"data": 123}`)
}

func main() {
	web.BConfig.RunMode = "dev"
	web.BConfig.WebConfig.Session.SessionOn = true
	web.BConfig.WebConfig.Session.SessionName = "sid"
	web.BConfig.WebConfig.Session.SessionProvider = "file"
	web.BConfig.WebConfig.Session.SessionProviderConfig = "./session"
	web.Router("/city/", &CityController{})

	web.Run()
}

Session 拦截一般使用 filter 过滤

认证拦截

用户认证拦截可以放置的位置:

  • controller.Prepare(),可以使用 c.StopRun() 终止继续执行,缺点:所有的控制器均需写重复的代码
  • 定义一个认证controller,在 Prepare() 中实现权限认证,如通过 c.GetControllerAndAction() 和用户的菜单权限对比等
    • xxxController
    • AuthorizationController | UnAuthController like LoginController
    • BaseController
    • web.Controller
type AuthorizationController struct {
  web.Controller
  SigInUser *models.User
}

type (c *AuthorizationController) Prepare() {
  // auth: 通过从Session中获取登录信息
  // 1. nil,跳转登录
  // 2. 获取成功时,将User信息添加到 c.Data["user"] 中,断言获取值信息
  // id := sessionValue.(string)
  // c.SigInUser = user

  // 针对该controller关闭xsrf认证
  // c.EnableXSRF = false
}

Flash

使用 cookie 存储消息,并可以在页面获取对应的值后删除 使用场景:

  • 使用后端页面模板
  • 从当前Controller跳转到另一个URL
f := web.NewFlash

f.Set("key1", "val1)
f.Store(&c.Controller)

// 另一个Controller获取
f:= web.ReadFromRequest(&c.Controller)
f.Data["key1]

// 页面获取
{{ .flash.key1 }}

CSRF

CSRF 跨站请求伪造,是常见的攻击手段。配置 conf/app.conf

EnableXSRF=true
XSRFKey=abcd..
XSRFExpire=3600

使用:

c.Data["xsrf_token"] = c.XSRFtoken()
<input type="hidden" name="_xfst" value="{{ .xsrf_token }}" />

Layout

$ cat layout.html
<html>
.LayoutContent
...
.scriptStyle

$ cat base/controllers/layout.go
func (c *LayoutController) Prepare() {
  c.Controller.Prepare()
  c.Layout = "layouts/layout.html"
  c.Data["title"] = web.AppConf...

  c.LayoutSections=make(map[string]string)
  c.LayoutSection["scriptStyle"] = "...html"
  c.LayoutSection["css"] = "...css"
}

Cache 缓存

package main

import (
	"encoding/gob"
	"os"
	"time"

	"github.com/beego/beego/v2/client/cache"
	"github.com/beego/beego/v2/core/logs"
)

type City struct {
	Name string
}

func main() {
	//cache, _ := cache.NewCache("memory", `{"interval": 60}`)
	cache, err := cache.NewCache("file", `{"CachePath": "cache", "FileSuffix": ".cache", "EmbedExpiry": "60", "DirectoryLevel": "5"}`)
	if err != nil {
		logs.Error(err)
		os.Exit(-1)
	}
	logs.Info(cache.Get(nil, "name"))
	timeout := 5 * time.Second
	cache.Put(nil, "name", "xianbin", timeout)
	logs.Info(cache.Get(nil, "name"))
	time.Sleep(6 * time.Second)
	logs.Info(cache.Get(nil, "name"))

	cache.Delete(nil, "name")
	logs.Info(cache.IsExist(nil, "name"))

	gob.Register(new(City))
	c := &City{
		Name: "shanghai",
	}
	cache.Put(nil, "city", c, 5*time.Second)
	logs.Info(cache.Get(nil, "city"))
}

Filter

  • BeforeExec
  • AfterExec

部署

使用linux service打包部署

https

EnableHTTP=true
EnableHTTPs=true
HTTPSCertFile=
HTTPSKeyFile=

项目架构

  • controller
  • services Server
type userService struct{}

func (s *userService) GetByPk (){

}

var UserService = new(userService)
  • forms 存放表单
  • models

FaQ

beego2.0打包文件执行错误:

$ ./main
panic: err: go command required, not found: exec: "go": executable file not found in $PATH: stderr:

goroutine 1 [running]:
github.com/beego/beego/v2/server/web.initBeforeHTTPRun.func1()
        /go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/beego.go:83 +0x225
sync.(*Once).Do(0x16ef2e0, 0xdcc288)
        /usr/local/go/src/sync/once.go:44 +0xb3
github.com/beego/beego/v2/server/web.initBeforeHTTPRun()
        /go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/beego.go:69 +0x39
github.com/beego/beego/v2/server/web.(*HttpServer).Run(0xc000185a40, 0x0, 0x0, 0x0, 0x0, 0x0)
        /go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/server.go:85 +0x34
github.com/beego/beego/v2/server/web.Run(0x0, 0x0, 0x0)
        /go/pkg/mod/github.com/beego/beego/v2@v2.0.1/server/web/beego.go:57 +0x62
main.main()
        /tmp/code/main.go:21 +0x32
  • 解决方式,将 app.conf 中设置为生产环境:
runmode = prod

参考

  1. https://github.com/beego/beego
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数