• beego入门笔记


    Beego Learn Note

    示例环境在Deepin系统下。

    deepin 15.9.3
    ├── Beego     : 1.11.2
    ├── GoVersion : go1.12.4
    ├── GOOS      : linux
    ├── GOARCH    : amd64
    ├── NumCPU    : 1
    ├── GOPATH    : /home/jehorn/workspace/go
    ├── GOROOT    : /usr/local/go
    ├── Compiler  : gc
    └── Date      : Saturday, 27 Apr 2019
    

    Linux下配置Go开发环境

    首先从Go官网下载对应的压缩包。
    下载完毕后解压,然后移动至/usr/local下:

    sudo mv go /usr/local/
    

    然后配置环境变量:

    sudo vim /etc/profile
    

    在结尾添加(其中GOPATH请替换自己的路径):

    export GOROOT=/usr/local/go
    export GOARCH=amd64
    export GOOS=linux
    export GOPATH=/home/jehorn/workspace/go
    export GOBIN=$GOROOT/bin
    export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
    export PATH=$GOPATH/bin:$PATH
    

    然后执行

    source /etc/profile
    

    控制台输出go version有版本号输出即配置完成。


    安装beego:

    GOPATH目录下,执行:

    go get github.com/astaxie/beego
    go get github.com/beego/bee
    

    执行bee version看到版本号即安装成功。


    执行bee new demo,即可新建一个项目:

    jehorn@jehorn-PC:~/workspace/go/src/demo$ tree
    .
    ├── conf
    │   └── app.conf
    ├── controllers
    │   └── default.go
    ├── main.go
    ├── models
    ├── routers
    │   └── router.go
    ├── static
    │   ├── css
    │   ├── img
    │   └── js
    │       └── reload.min.js
    ├── tests
    │   └── default_test.go
    └── views
        └── index.tpl
    
    10 directories, 7 files
    

    Linux下IDE配置

    安装VSCode

    然后安装go插件。

    然后打开File-preferences-settings,在右上角点开扩展菜单,选择Open settings.json,然后在右侧的USER SETTINGS中输入:

        "go.buildOnSave": "workspace",
        "go.lintOnSave": "package",
        "go.vetOnSave": "package",
        "go.buildTags": "",
        "go.buildFlags": [],
        "go.lintFlags": [],
        "go.vetFlags": [],
        "go.coverOnSave": false,
        "go.useCodeSnippetsOnFunctionSuggest": false,
        "go.formatOnSave": true,
        "go.formatTool": "goreturns",
        "go.goroot": "/usr/local/go",
        "go.gopath": "/home/jehorn/workspace/go"
    

    保存,然后就可以打开项目。
    项目打开以后,可能会有一些包提示你安装,直接点击install即可。

    beego项目运行原理

    $GOPATH/src/demo/目录下,命令行运行bee run,然后打开浏览器localhost:8080可以看到运行的beego项目。

    sequenceDiagram Browser->>Server: http:localhost:8080 Server->>Server: Main.go Server->>Server: router.Init() Server->>Server: Controller.Get() Server->>Server: View Server-->>Browser: index.tpl

    ORM

    ORM创建

    Object Relation Mapping(对象关系映射)。

    通过结构体对象来操作对应的数据库表。
    可以生成结构体相对应的数据库表。

    安装:

    go get github.com/astaxie/beego/orm
    

    安装完成之后,在models文件夹新建一个实体 user.go

    package models
    
    import (
        "github.com/astaxie/beego/orm"
        _ "github.com/go-sql-driver/mysql"
    )
    
    type User struct {
        Id int
        Name string
        Pwd string
    }
    
    func init() {
        // 链接数据库
        orm.RegisterDataBase("default", "mysql", "root:123456@tcp(127.0.0.1:3306)/demo?charset=utf8")
        // 映射model数据(new(Type)...)
        orm.RegisterModel(new(User))
        // 生成表(别名, 是否强制更新, 是否可见)
        orm.RunSyncdb("default", false, true)
    }
    

    然后在main.go中调用init()方法:

    package main
    
    import (
        _ "demo/models"
        ...
    )
    
    ...
    

    最后在执行bee run之前,先在mysql中创建一个数据库:

    create database demo;
    -- Query OK, 1 row affected (0.02 sec)
    

    执行bee run:

    C:UsersJehornWorkprojectsGosrcdemo>bee run
    ______
    | ___ 
    | |_/ /  ___   ___
    | ___  / _  / _ 
    | |_/ /|  __/|  __/
    \____/  \___| \___| v1.10.0
    2019/05/05 15:49:24 INFO     ▶ 0001 Using 'demo' as 'appname'
    2019/05/05 15:49:24 INFO     ▶ 0002 Initializing watcher...
    2019/05/05 15:49:27 SUCCESS  ▶ 0003 Built Successfully!
    2019/05/05 15:49:27 INFO     ▶ 0004 Restarting 'demo.exe'...
    2019/05/05 15:49:27 SUCCESS  ▶ 0005 './demo.exe' is running...
    create table `user`
        -- --------------------------------------------------
        --  Table Structure for `demo/models.User`
        -- --------------------------------------------------
        CREATE TABLE IF NOT EXISTS `user` (
            `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
            `name` varchar(255) NOT NULL DEFAULT '' ,
            `pwd` varchar(255) NOT NULL DEFAULT ''
        ) ENGINE=InnoDB;
    
    2019/05/05 15:49:28.353 [I] [asm_amd64.s:1333]  http server Running on http://:8080
    

    到数据库中查看创建结果:

    use demo;
    desc user;
    

    注:“civ”为数据库名称。

    ORM增

    核心代码:

    o := orm.NewOrm()
    u := User{}
    
    _, err := o.Insert(&u)
    

    改造项目:

    1. 为了方便前后端分离,首先我们需要配置CORS来实现跨域:
      main.go中引入github.com/astaxie/beego/plugins/cors包:
    package main
    
    import (
    	_ "civ/models"
    	_ "civ/routers"
    	"github.com/astaxie/beego"
    	"github.com/astaxie/beego/plugins/cors"
    )
    
    func main() {
    	beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
    		//允许访问所有源
    		AllowAllOrigins: true,
    		//可选参数"GET", "POST", "PUT", "DELETE", "OPTIONS" (*为所有)
    		//其中Options跨域复杂请求预检
    		AllowMethods:   []string{"*"},
    		//指的是允许的Header的种类
    		AllowHeaders: 	[]string{"*"},
    		//公开的HTTP标头列表
    		ExposeHeaders:	[]string{"Content-Length"},
    	}))
    	beego.Run()
    }
    
    1. 为了方便查看API,我们使用API自动化文档

    首先在routers/router.go文件最顶端添加注释:

    // @APIVersion 1.0.0
    // @Title DEMO API
    // @Description Demo APIs.
    // @Contact xxx@gmail.com
    package routers
    
    ...
    

    然后在controllers/user.go中,给UserController增加注释:

    package controllers
    
    import ...
    
    // User APIs
    type UserController struct {
    	beego.Controller
    }
    

    然后修改conf/app.conf文件,添加:

    EnableDocs = true
    

    然后在具体的接口上填写注释。到时见下一步的具体的接口实现。

    最后,运行bee run的时候添加几个参数:

    bee run -gendoc=true -downdoc=true
    

    编译完成后会在当前项目文件夹下生成swagger目录,部署这个目录,然后在浏览器打开即可看到生成的swagger api 文档。

    1. 按照MVC代码设计,首先我们在models/user.goUser新增一个Add方法:
    package models
    
    import (
        "errors"
        "github.com/astaxie/beego/orm"
        "strings"
    )
    
    type User struct {
        Id int
        Name string
        Pwd string
    }
    
    func (u User) Add(item User) error {
        u.Name = strings.Trim(item.Name, " ")
        u.Pwd = strings.Trim(item.Pwd, " ")
    
        if u.Name == "" {
            return errors.New("请输入姓名")
        }
        
        if u.Pwd == "" || len(u.Pwd) < 3 {
            return errors.New("请输入长度大于等于3的密码")
        }
        
        o := orm.NewOrm()
        _, err := o.Insert(&u)
        
        return err
    }
    

    然后在models新增一个公共返回结构result.go

    package models
    
    type Code int32
    
    const (
    	SUCCESS Code = iota // value --> 0
    	ERR_BIZ                       // value --> 1
    	ERR_DATA                   // value --> 2
    	ERR_AUTH                  // value --> 3
    	ERR_LOST                  // value --> 4
    	ERR_UNKNOW          // value --> 5
    )
    
    func (c Code) String() string {
        switch c {
    	case SUCCESS:
    		return "操作成功"
    	case ERR_BIZ:
    		return "业务操作失败"
    	case ERR_DATA:
    		return "数据操作失败"
    	case ERR_AUTH:
    		return "权限操作失败"
    	case ERR_LOST:
    		return "操作不存在"
    	case ERR_UNKNOW:
    		return "未知错误200"
    	default:
    		return "未知错误"
    	}
    }
    
    type Result struct {
    	Code Code
    	Msg string
    	Data interface{}
    }
    

    然后在controllers新增一个user.go,同时在这里添加api注释,以生成api文档:

    package controllers
    
    import (
    	"civ/models"
    	"encoding/json"
    	"github.com/astaxie/beego"
    )
    
    type UserController struct {
    	beego.Controller
    }
    
    // @Title AddUser
    // @Description Add users
    // @Param   user     formData    models.UserAddObj        "The user list for add"
    // @router /add [post]
    func (c *UserController) Post() {
    	r := models.Result{}
    
    	usr := models.User{}
    
    	var err error
    	var arr []models.User
    	var errs []error
    	if err = json.Unmarshal(c.Ctx.Input.RequestBody, &arr); err == nil {
    
    		for _, item := range arr {
    			err := usr.Add(item)
    
    			if err != nil {
    				errs = append(errs, err)
    			}
    		}
    
    		r.Data = nil
    		r.Msg = "新增用户成功"
    		r.Code = models.SUCCESS
    
    		if len(errs) > 0 {
    			r.Data = nil
    			r.Msg = errs[0].Error()
    			r.Code = models.ERR_DATA
    		}
    
    	} else {
    		r.Data = nil
    		r.Msg = err.Error()
    		r.Code = models.ERR_BIZ
    	}
    
    	c.Data["json"] = r
    	c.ServeJSON()
    }
    

    然后在routers/router.go中,添加/user路由:

    // @APIVersion 1.0.0
    // @Title DEMO API
    // @Description Demo APIs.
    // @Contact xxx@gmail.com
    package routers
    
    import (
    	"civ/controllers"
    	"github.com/astaxie/beego"
    )
    
    func init() {
    	ns := beego.NewNamespace("/v1",
    		beego.NSNamespace("/",
    			beego.NSInclude(
    				&controllers.MainController{},
    			),
    		),
    		beego.NSNamespace("/user",
    			beego.NSInclude(
    				&controllers.UserController{},
    			),
    		),
    	)
    
    	beego.AddNamespace(ns)
    }
    

    由于我们要在UserController中访问Request Body,需要在conf/app.conf中添加:

    copyrequestbody = true
    

    至此服务端就算是完成,然后是前端提交表单代码,这里使用ajax提交:

    ...
    <body>
    <div>
        姓名:<input type="text" name="r2name">
        密码:<input type="password" name="r2pwd">
        <button type="button" id="r2b">请求user接口并插入上面的数据</button>
    </div>
    
    
    <script src="./node_modules/jquery/dist/jquery.js"></script>
    <script type="text/javascript">
        $(document).ready(() => {
            $('#r2b').on('click', function () {
                new BeegoRequests().r2();
            });
    
        });
    
        // ajax请求简单封装
        class Request {
            constructor() {
                this.DEFAULT = {
                    host: 'http://localhost:8080/v1',
                    url: '/',
                    type: 'POST',
                    data: ''
                };
            }
    
            DEFAULT;
    
            r(option = {}) {
                const opt = Object.assign(this.DEFAULT, option);
                return new Promise((resolve, reject) => {
                    let data = opt.data;
                    if (opt.type.toUpperCase() === 'POST')
                        data = JSON.stringify(data);
                    $.ajax({
                        url: opt.host + opt.url,
                        type: opt.type,
                        data: data,
                        success(res) {
                            resolve(res);
                        },
                        error(err) {
                            reject(err);
                        }
                    });
                });
            }
        }
    
        class BeegoRequests extends Request {
            constructor() {
                super();
            }
    
            r2() {
                const name = $('input[name="r2name"]').val();
                const pwd = $('input[name="r2pwd"]').val();
                const data = [{ name: name, pwd: pwd }];
    
                this.r({
                    url: '/user/add',
                    data: data
                }).then(res => {
                    console.log(res);
                }).catch(err => {
    
                });
            }
        }
    
    </script>
    </body>
    

    ORM查

    核心代码:

    o := orm.NewOrm()
    qs := o.QueryTable("user")
    _, err := qs.Filter("name__icontains", strings.Trim(name, " ")).All(&list)
    

    实现过程:

    简单实现一个根据name模糊查询的接口:

    首先在models/user.go中新增一个List方法:

    func (u User) List(name string) ([]User, error) {
    	var list []User
    	o := orm.NewOrm()
    	qs := o.QueryTable("user")
    	_, err := qs.Filter("name__icontains", strings.Trim(name, " ")).All(&list)
    
    	return list, err
    }
    

    然后在controllers/user.go里新增一个List方法:

    // @Title GetUserList
    // @Description Get user list
    // @Param  name query string "The filter key of Name"
    // @router /list [get]
    func (c *UserController) List() {
    	r := models.Result{}
    	usr := models.User{}
    	name := c.GetString("name")
    
    	userList, err := usr.List(name)
    
    	r.Data = userList
    	r.Code = models.SUCCESS
    	r.Msg = "查询成功"
    
    	if err != nil {
    		r.Data = nil
    		r.Code = models.ERR_DATA
    		r.Msg = "查询用户不存在"
    	}
    
    	c.Data["json"] = r
    	c.ServeJSON()
    }
    

    至此服务端完成,然后前端:

    <html>
    ...
    <body>
    
    <div>
        查询姓名:<input type="text" name="r3name">
        <button type="button" id="r3b">根据姓名获取用户列表</button>
    </div>
    
    
    <script src="./node_modules/jquery/dist/jquery.js"></script>
    <script type="text/javascript">
        $(document).ready(() => {
            $('#r3b').on('click', function () {
                new BeegoRequests().r3();
            });
        });
    
        class Request {
            ...
        }
    
        class BeegoRequests extends Request {
            ...
    
            r3() {
                const name = $('input[name="r3name"]').val();
                this.r({
                    type: 'GET',
                    url: '/user/list',
                    data: {
                        name: name
                    }
                }).then(res => {
                    console.log(res);
                }).catch(err => {
    
                });
            }
        }
    
    </script>
    </body>
    </html>
    

    这里只是个人入门过程,更多内容参阅beego官方文档
    源码地址参见Github

  • 相关阅读:
    Spring MVC入门——day01
    Spring5学习笔记——day05
    [BJDCTF2020]The mystery of ip
    [网鼎杯 2020 青龙组]AreUSerialz
    [网鼎杯 2018]Fakebook
    文件上传绕过学习
    [极客大挑战 2019]PHP
    无参数RCE总结及文件读取学习
    java中多线程执行时,为何调用的是start()方法而不是run()方法
    minconda安装配置
  • 原文地址:https://www.cnblogs.com/jehorn/p/10821506.html
Copyright © 2020-2023  润新知