zoukankan      html  css  js  c++  java
  • 基于beego构建Restful API服务

    听闻Go号称“21世纪的C语言”,又比较适合做Web后端的应用,加之本人对C/C++比较熟悉,计划通过构建一个提供Restful API的服务来达到学习的目的。

    github上浏览了一下相关的框架挺多,如:hugo、gin、beego、echo、iris等,还有mux(A powerful URL router and dispatcher)看上去也颇为合适。由于本人Web开发(java/php/node.js什么的都不会)小白,打算先从beego入手。

    一、创建API项目并运行

    1. beego的项目可以通过bee工具来创建,RESTful的项目通过api参数来创建。创建imc项目命令:

    bee api imc
    

    如此会在$GOPATH/src目录下生成一个imc目录。

    2. 运行imc项目,启动swagger便于测试。

    先进入到$GOPATH/src/imc目录下,执行以下命令:

    bee run -gendoc=true -downdoc=true
    

    如此便启动了API自动化文档,以及会自动下载swagger。浏览器直接访问http://localhost:8080/swagger/即可进行测试。

    -gendoc=true表示每次会自动化的build文档,-downdoc=true表示会自动下载swagger文档查看器。

     二、自动生成文件(代码)分析

    1. imc/conf/app.conf

    app.conf是beego的默认配置文件。

    appname = imc
    httpport = 8080
    runmode = dev
    autorender = false
    copyrequestbody = true
    EnableDocs = true
    

    appname: 应用名称,默认是beego。通过bee new或bee api创建,则是项目名称。beego.BConfig.AppName = "imc"。

    httpport:应用监听端口,默认是8080。beego.BConfig.Listen.HTTPPort = 8080。

    runmode:应用的运行模式,可选值为prod、dev或test。默认是dev开发模式。beego.BConfig.RunMode = "dev"。

    autorender:是否模板自动渲染,默认值为true,对于API类型的应用,需要把该项设为false。beego.BConfig.WebConfig.AutoRender = true。

    copyrequestbody:是否允许在HTTP请求时,返回原始请求体数据字节,默认为false(GET or HEAD or 上传文件请求除外)。beego.BConfig.CopyRequestBody = false。

    EnableDocs:是否开启文档内置功能,默认为false。beego.BConfig.WebConfig.EnableDocs = true。

    2. main.go

    package main
    
    import (
    	_ "deepspirit/imc/routers"
    	"github.com/astaxie/beego"
    )
    
    func main() {
    	if beego.BConfig.RunMode == "dev" {
    		beego.BConfig.WebConfig.DirectoryIndex = true
    		beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
    	}
    	beego.Run()
    }

    程序入口,通过beego.Run()将beego的框架运行起来。当以dev开发者模式启动时,设置一些参数。(暂时不用关注)

    import中的_ "deepspirit/imc/routers"语句目的是执行routers包中的init函数。Go允许一个package中多个文件包含init函数,执行顺序为文件名字母顺序。

    Go语言的代码执行过程如下图:

    3. imc/routers/*.go

    commentsRouter_controller.go:根据router.go和controllers/*.go自动生成。从beego 1.3版本开始支持注解路由功能,用户无需在router中注册路由,只需要Include相应的controller,然后在controller的method方法上面写上router注释(// @router)即可。

    router.go:

    package routers
    
    import (
    	"deepspirit/imc/controllers"
    	"github.com/astaxie/beego"
    )
    
    func init() {
    	ns := beego.NewNamespace("/v1",
    		beego.NSNamespace("/object",
    			beego.NSInclude(
    				&controllers.ObjectController{},
    			),
    		),
    		beego.NSNamespace("/user",
    			beego.NSInclude(
    				&controllers.UserController{},
    			),
    		),
    	)
    	beego.AddNamespace(ns)
    }
    

    添加/v1/object/对应ObjectController中的注解路由。

    添加/v1/user/对应UserControoler中的注解路由。

    4. imc/controllers/*.go

    object.go:

    package controllers
    
    import (
    	"deepspirit/imc/models"
    	"encoding/json"
    
    	"github.com/astaxie/beego"
    )
    
    // Operations about object
    type ObjectController struct {
    	beego.Controller
    }
    
    // @Title Create
    // @Description create object
    // @Param	body		body 	models.Object	true		"The object content"
    // @Success 200 {string} models.Object.Id
    // @Failure 403 body is empty
    // @router / [post]
    func (o *ObjectController) Post() {
    	var ob models.Object
    	json.Unmarshal(o.Ctx.Input.RequestBody, &ob)
    	objectid := models.AddOne(ob)
    	o.Data["json"] = map[string]string{"ObjectId": objectid}
    	o.ServeJSON()
    }
    
    // @Title Get
    // @Description find object by objectid
    // @Param	objectId		path 	string	true		"the objectid you want to get"
    // @Success 200 {object} models.Object
    // @Failure 403 :objectId is empty
    // @router /:objectId [get]
    func (o *ObjectController) Get() {
    	objectId := o.Ctx.Input.Param(":objectId")
    	if objectId != "" {
    		ob, err := models.GetOne(objectId)
    		if err != nil {
    			o.Data["json"] = err.Error()
    		} else {
    			o.Data["json"] = ob
    		}
    	}
    	o.ServeJSON()
    }
    
    // @Title GetAll
    // @Description get all objects
    // @Success 200 {object} models.Object
    // @Failure 403 :objectId is empty
    // @router / [get]
    func (o *ObjectController) GetAll() {
    	obs := models.GetAll()
    	o.Data["json"] = obs
    	o.ServeJSON()
    }
    
    // @Title Update
    // @Description update the object
    // @Param	objectId		path 	string	true		"The objectid you want to update"
    // @Param	body		body 	models.Object	true		"The body"
    // @Success 200 {object} models.Object
    // @Failure 403 :objectId is empty
    // @router /:objectId [put]
    func (o *ObjectController) Put() {
    	objectId := o.Ctx.Input.Param(":objectId")
    	var ob models.Object
    	json.Unmarshal(o.Ctx.Input.RequestBody, &ob)
    
    	err := models.Update(objectId, ob.Score)
    	if err != nil {
    		o.Data["json"] = err.Error()
    	} else {
    		o.Data["json"] = "update success!"
    	}
    	o.ServeJSON()
    }
    
    // @Title Delete
    // @Description delete the object
    // @Param	objectId		path 	string	true		"The objectId you want to delete"
    // @Success 200 {string} delete success!
    // @Failure 403 objectId is empty
    // @router /:objectId [delete]
    func (o *ObjectController) Delete() {
    	objectId := o.Ctx.Input.Param(":objectId")
    	models.Delete(objectId)
    	o.Data["json"] = "delete success!"
    	o.ServeJSON()
    }
    

    // @router / [post]

    该注解路由表示支持/v1/object/的POST方法(此处url为/,结合router.go中的/v1/object)

    // @router /:objectId [get]  

    该注解路由表示支持/v1/object/{objectId}的GET方法

    // @router / [get]

    该注解路由表示支持/v1/object的GET方法

    // @router /:objectId [put]

    该注解路由表示支持/v1/object/{objectId}的PUT方法

    // @router /:objectId [delete]

    该注解路由表示支持/v1/object/{objectId}的DELETE方法

     user.go:

    package controllers
    
    import (
    	"deepspirit/imc/models"
    	"encoding/json"
    	"github.com/astaxie/beego"
    )
    
    // Operations about Users
    type UserController struct {
    	beego.Controller
    }
    
    // @Title CreateUser
    // @Description create users
    // @Param	body		body 	models.User	true		"body for user content"
    // @Success 200 {int} models.User.Id
    // @Failure 403 body is empty
    // @router / [post]
    func (u *UserController) Post() {
    	var user models.User
    	json.Unmarshal(u.Ctx.Input.RequestBody, &user)
    	uid := models.AddUser(user)
    	u.Data["json"] = map[string]string{"uid": uid}
    	u.ServeJSON()
    }
    
    // @Title GetAll
    // @Description get all Users
    // @Success 200 {object} models.User
    // @router / [get]
    func (u *UserController) GetAll() {
    	users := models.GetAllUsers()
    	u.Data["json"] = users
    	u.ServeJSON()
    }
    
    // @Title Get
    // @Description get user by uid
    // @Param	uid		path 	string	true		"The key for staticblock"
    // @Success 200 {object} models.User
    // @Failure 403 :uid is empty
    // @router /:uid [get]
    func (u *UserController) Get() {
    	uid := u.GetString(":uid")
    	if uid != "" {
    		user, err := models.GetUser(uid)
    		if err != nil {
    			u.Data["json"] = err.Error()
    		} else {
    			u.Data["json"] = user
    		}
    	}
    	u.ServeJSON()
    }
    
    // @Title Update
    // @Description update the user
    // @Param	uid		path 	string	true		"The uid you want to update"
    // @Param	body		body 	models.User	true		"body for user content"
    // @Success 200 {object} models.User
    // @Failure 403 :uid is not int
    // @router /:uid [put]
    func (u *UserController) Put() {
    	uid := u.GetString(":uid")
    	if uid != "" {
    		var user models.User
    		json.Unmarshal(u.Ctx.Input.RequestBody, &user)
    		uu, err := models.UpdateUser(uid, &user)
    		if err != nil {
    			u.Data["json"] = err.Error()
    		} else {
    			u.Data["json"] = uu
    		}
    	}
    	u.ServeJSON()
    }
    
    // @Title Delete
    // @Description delete the user
    // @Param	uid		path 	string	true		"The uid you want to delete"
    // @Success 200 {string} delete success!
    // @Failure 403 uid is empty
    // @router /:uid [delete]
    func (u *UserController) Delete() {
    	uid := u.GetString(":uid")
    	models.DeleteUser(uid)
    	u.Data["json"] = "delete success!"
    	u.ServeJSON()
    }
    
    // @Title Login
    // @Description Logs user into the system
    // @Param	username		query 	string	true		"The username for login"
    // @Param	password		query 	string	true		"The password for login"
    // @Success 200 {string} login success
    // @Failure 403 user not exist
    // @router /login [get]
    func (u *UserController) Login() {
    	username := u.GetString("username")
    	password := u.GetString("password")
    	if models.Login(username, password) {
    		u.Data["json"] = "login success"
    	} else {
    		u.Data["json"] = "user not exist"
    	}
    	u.ServeJSON()
    }
    
    // @Title logout
    // @Description Logs out current logged in user session
    // @Success 200 {string} logout success
    // @router /logout [get]
    func (u *UserController) Logout() {
    	u.Data["json"] = "logout success"
    	u.ServeJSON()
    }
    

    // @router / [post]

    该注解路由表示支持/v1/user/的POST方法

    // @router / [get]

    该注解路由表示支持/v1/user/的GET方法

    // @router /:uid [get]

    该注解路由表示支持/v1/user/{uid}的GET方法

    // @router /:uid [put]

    该注解路由表示支持/v1/user/{uid}的PUT方法

    // @router /:uid [delete]

    该注解路由表示支持/v1/user/{uid}的DELETE方法

    // @router /login [get]

    该注解路由表示支持/v1/user/login的GET方法

    // @router /logout [get]

    该注解路由表示支持/v1/user/logout的GET方法

    5. imc/models/*.go

    object.go和user.go,代码不再罗列。model层主要数据与数据库相关的操作,自动生成的例子不含数据库操作,后续ORM的部分放在该目录下。

    三、ORM使用

    1. 安装MySQL 8

    2. 下载Go语言的驱动

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

    3. 使用orm访问数据库

    func init() {
        // set default database
        orm.RegisterDataBase("default", "mysql", "username:password@tcp(127.0.0.1:3306)/db_name?charset=utf8", 30)
    
        // register model
        orm.RegisterModel(new(models.Role))
    
        // create table
        orm.RunSyncdb("default", false, true)
    }
    

    注册模型之后,调用RunSyncdb,若对应模型的表不存在会自动创建。以上代码考虑放在main.go中。

    向models目录中添加role.go,代码如下:

  • 相关阅读:
    2019 SDN上机第7次作业
    第01组 Beta冲刺(4/5)
    第01组 Beta冲刺(3/5)
    第01组 Beta冲刺(2/5)
    第01组 Beta冲刺(1/5)
    2019 SDN上机第6次作业
    2019 SDN上机第5次作业
    SDN课程阅读作业(2)
    第01组 Alpha事后诸葛亮
    第01组 Alpha冲刺(6/6)
  • 原文地址:https://www.cnblogs.com/xiaochuizi/p/9257521.html
Copyright © 2011-2022 走看看