[beego新手入門]基於web框架-beego的RESTful API的構建之旅

前言

beego是一個快速開發GO應用的http框架,做者是go語言方向的大牛,astaxie。beego能夠用來快速開發API、web、後端服務等應用,是一個RESTFul風格的框架,主要的設計靈感來自於Python web開發框架tornado、flask、sinstra,很好的結合了Go語言自己的一些特性(interface,struct繼承等)。html

​ beego是基於八大獨立模塊來實現的,很好的實現了模塊間的解耦,即便用戶不使用http的邏輯,也能夠很好的使用其中的各個模塊。做者本身說,他的這種思想來自於樂高積木,設計beego的時候,這些模塊就是積木,而最終搭建好的機器人就是beego。mysql

​ 這篇博文經過使用beego來構建API,講解實現過程當中的細節以及遇到的一些坑,讓咱們立刻開始beego的API構建之旅吧!git

項目建立

進入到你的$GOPATH/src 安裝beego開發包本身快速開發工具beegithub

go get github.com/astaxie/beego
go get github.com/astaxie/beego/orm
go get github.com/beego/bee
複製代碼

使用快速開發工具bee,建立咱們的API項目web

bee new firstAPI
複製代碼

咱們獲得的項目結構以下圖所示:sql

能夠看出這是一個典型的MVC架構的應用,beego把咱們項目所須要的一些都準備好了,例如配置文件conf,測試文件tests等,咱們只須要專一於API代碼的編寫便可。shell

運行項目並得到API自動化文檔數據庫

bee run -gendoc=true -downdoc=true
複製代碼

運行上述代碼輸出以下圖所示:json

咱們在瀏覽器中訪問:本機IP:8080/swagger,就會看到swagger的API文檔,咱們代碼更新後,該文檔就會自動更新,很是方便。flask

models設計

對 數據庫object 操做有四個方法Read / Insert / Update / Delete 示例代碼:

o := orm.NewOrm()
user := new(User)
user.Name = "slene"

fmt.Println(o.Insert(user))

user.Name = "Your"
fmt.Println(o.Update(user))
fmt.Println(o.Read(user))
fmt.Println(o.Delete(user))
複製代碼

還有其餘的方法能夠參閱beego官方文檔,裏面對orm操做有着詳細的介紹。

建立一個數據庫並設計一張數據庫表

CREATE TABLE IF NOT EXISTS `student` (
`Id` int(11),
`Name` varchar(255),
`Birthdate` varchar(255),
`Gender` bool,
`Score` int(11)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
複製代碼

在models文件夾下新建一個文件Student.go,並實現如下代碼,代碼中關鍵點都有註釋 package models

import (
	"fmt"
	"github.com/astaxie/beego/orm"
)
複製代碼

//在models模塊中建立一個struct,目的是使用beego的orm框架,使struct與數據庫中的字段產生對應關係

type Student struct {
	Id int`orm:"column(Id)"` //column()括號中的字段就是在定義數據庫時的相應字段,這一段必須嚴格填寫,否則在API讀寫數據時就會出現讀不到或者寫不進去的問題
	Name string  `orm:"column(Name)"`
	BirthDate string `orm:"column(Birthdate)"`
	Gender bool `orm:"column(Gender)"`
	Score int `orm:"column(Score)"`
}


//該函數得到數據庫中全部student的信息,返回值是一個結構體數組指針
func GetAllStudents() []*Student {
	o := orm.NewOrm() //產生一個orm對象
	o.Using("default") //這句話的意思是使用定義的默認數據庫,與main.go中的orm.RegisterDataBase()對應
	var students []*Student //定義指向結構體數組的指針
	q := o.QueryTable("student")//得到一個數據庫表的請求
	q.All(&students)//取到這個表中的全部數據

	return students

}


//該函數根據student中的Id,返回該學生的信息
func GetStudentById(id int) Student {
	u := Student{Id:id}//根據所傳入的Id獲得對應student的對象
	o := orm.NewOrm()//new 一個orm對象
	o.Using("default")//使用最開始定義的default數據庫
	err := o.Read(&u)//讀取Id=id的student的信息

	if err == orm.ErrNoRows {
		fmt.Println("查詢不到")//對應操做,不必定是print
	} else if err == orm.ErrMissPK {
		fmt.Println("沒有主鍵")
	}

	return u
}


//添加一個學生的信息到數據庫中,參數是指向student結構題的指針
func AddStudent(student *Student) Student {
	o := orm.NewOrm()
	o.Using("default")
	o.Insert(student)//插入數據庫

	return *student
}

func UpdateStudent(student *Student) {
	o := orm.NewOrm()
	o.Using("default")
	o.Update(student)//更新該student的信息
}

func DeleteStudent(id int) {
	o := orm.NewOrm()
	o.Using("default")
	o.Delete(&Student{Id:id})//刪除對應id的student的信息
}

func init()  {
	orm.RegisterModel(new(Student))//將數據庫註冊到orm
}
複製代碼

model這一層主要是定義struct,併爲上層編寫讀寫數據庫。處理數據的代碼。

controller層實現

基於 beego 的 Controller 設計,只須要匿名組合 beego.Controller 就能夠了,以下所示:

type xxxController struct {
    beego.Controller
}
beego.Controller 實現了接口 beego.ControllerInterface,beego.ControllerInterface 定義了以下函數:

Init(ct *context.Context, childName string, app interface{})
複製代碼

這個函數主要初始化了 Context、相應的 Controller 名稱,模板名,初始化模板參數的容器 Data,app 即爲當前執行的 Controller 的 reflecttype,這個 app 能夠用來執行子類的方法。

  • Prepare()

這個函數主要是爲了用戶擴展用的,這個函數會在下面定義的這些 Method 方法以前執行,用戶能夠重寫這個函數實現相似用戶驗證之類。

  • Get()

若是用戶請求的 HTTP Method 是 GET,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Get 請求。

  • Post()

若是用戶請求的 HTTP Method 是 POST,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Post 請求。

  • Delete()

若是用戶請求的 HTTP Method 是 DELETE,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Delete 請求。

  • Put()

若是用戶請求的 HTTP Method 是 PUT,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Put 請求.

  • Head()

若是用戶請求的 HTTP Method 是 HEAD,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Head 請求。

  • Patch()

若是用戶請求的 HTTP Method 是 PATCH,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Patch 請求.

  • Options()

若是用戶請求的HTTP Method是OPTIONS,那麼就執行該函數,默認是 405,用戶繼承的子 struct 中能夠實現了該方法以處理 Options 請求。

  • Finish()

這個函數是在執行完相應的 HTTP Method 方法以後執行的,默認是空,用戶能夠在子 struct 中重寫這個函數,執行例如數據庫關閉,清理數據之類的工做。

  • Render() error

這個函數主要用來實現渲染模板,若是 beego.AutoRender 爲 true 的狀況下才會執行。

因此經過子 struct 的方法重寫,用戶就能夠實現本身的邏輯。

routers層實現 什麼是路由設置呢?前面介紹的 MVC 結構執行時,介紹過 beego 存在三種方式的路由:固定路由、正則路由、自動路由,與RESTFul API相關的就是固定路由和正則路由。

下面就是固定路由的例子

beego.Router("/", &controllers.MainController{})
beego.Router("/admin", &admin.UserController{})
beego.Router("/admin/index", &admin.ArticleController{})
beego.Router("/admin/addpkg", &admin.AddController{})
複製代碼

下面是正則路由的例子:

beego.Router(「/api/?:id」, &controllers.RController{})
複製代碼

默認匹配 //例如對於URL」/api/123」能夠匹配成功,此時變量」:id」值爲」123」

beego.Router(「/api/:id」, &controllers.RController{})
複製代碼

默認匹配 //例如對於URL」/api/123」能夠匹配成功,此時變量」:id」值爲」123」,但URL」/api/「匹配失敗

beego.Router(「/api/:id([0-9]+)「, &controllers.RController{})
複製代碼

自定義正則匹配 //例如對於URL」/api/123」能夠匹配成功,此時變量」:id」值爲」123」

beego.Router(「/user/:username([\w]+)「, &controllers.RController{})

正則字符串匹配 //例如對於URL」/user/astaxie」能夠匹配成功,此時變量」:username」值爲」astaxie」
複製代碼

beego.Router(「/download/.」, &controllers.RController{})

*匹配方式 //例如對於URL」/download/file/api.xml」能夠匹配成功,此時變量」:path」值爲」file/api」, 「:ext」值爲」xml」

beego.Router(「/download/ceshi/*「, &controllers.RController{})
複製代碼

*全匹配方式 //例如對於URL」/download/ceshi/file/api.json」能夠匹配成功,此時變量」:splat」值爲」file/api.json」

beego.Router(「/:id:int」, &controllers.RController{})
複製代碼

int 類型設置方式,匹配 :id爲int 類型,框架幫你實現了正則 ([0-9]+)

beego.Router(「/:hi:string」, &controllers.RController{})
複製代碼

string 類型設置方式,匹配 :hi 爲 string 類型。框架幫你實現了正則 ([\w]+)

beego.Router(「/cms_:id([0-9]+).html」, &controllers.CmsController{})
複製代碼

帶有前綴的自定義正則 //匹配 :id 爲正則類型。匹配 cms_123.html 這樣的 url :id = 123

我的以爲,最方便的仍是相似於Python框架flask的註解路由,也是在這個項目中使用的:

在routers/routers.go裏面添加你所但願的API

package routers

import (
	"firstAPI/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.NSNamespace("/student",
			beego.NSInclude(
				&controllers.StudentController{},
			),
		),
	)
	beego.AddNamespace(ns)
}
複製代碼

以上代碼實現了以下的API:

/v1/object

/v1/user

/v1/student
複製代碼

很是清晰明瞭。

main.go的數據庫配置

package main

import (
	_ "firstAPI/routers"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	_ "github.com/go-sql-driver/mysql"
)
func init() {
	orm.RegisterDriver("mysql", orm.DRMySQL)//註冊MySQL的driver
	orm.RegisterDataBase("default", "mysql", "root:test@tcp(127.0.0.1:3306)/restapi_test?charset=utf8")//本地數據庫的帳號。密碼等
	orm.RunSyncdb("default", false, true)

}
func main() {

	if beego.BConfig.RunMode == "dev" {
		beego.BConfig.WebConfig.DirectoryIndex = true
		beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"//靜態文檔
	}

	beego.Run()
}
複製代碼

關鍵點都在代碼中以註釋的形式展示。

postman測試

bee run 運行代碼後,咱們使用postman測試一下咱們所構建的API效果如何。

這裏節省篇幅,只測試一個接口。

到此爲止,咱們基於beego就實現了簡單API接口的構建,是否是既清晰又簡單呢?趕快本身動手試試吧!

代碼已上傳到GitHub,能夠bee run一下,Happy Coding!

相關文章
相關標籤/搜索