在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ GO/ 13.3 controller設(shè)計(jì)
7 文本處理
3 Web基礎(chǔ)
14 擴(kuò)展Web框架
10.4 小結(jié)
2.2 Go基礎(chǔ)
2.8 總結(jié)
6.1 session和cookie
5.5 使用beedb庫進(jìn)行ORM開發(fā)
8.3 REST
13.6 小結(jié)
5.4 使用PostgreSQL數(shù)據(jù)庫
14.6 pprof支持
14.1 靜態(tài)文件支持
11.2 使用GDB調(diào)試
7.7 小結(jié)
1 GO環(huán)境配置
14.5 多語言支持
7.1 XML處理
1.5 總結(jié)
13 如何設(shè)計(jì)一個(gè)Web框架
14.3 表單及驗(yàn)證支持
12 部署與維護(hù)
10 國(guó)際化和本地化
1.1 Go 安裝
6.2 Go如何使用session
5.6 NOSQL數(shù)據(jù)庫操作
6.5 小結(jié)
9.4 避免SQL注入
12.1 應(yīng)用日志
4.2 驗(yàn)證表單的輸入
10.1 設(shè)置默認(rèn)地區(qū)
1.3 Go 命令
9.6 加密和解密數(shù)據(jù)
4.1 處理表單的輸入
4.4 防止多次遞交表單
11.3 Go怎么寫測(cè)試用例
8 Web服務(wù)
12.3 應(yīng)用部署
5.7 小結(jié)
12.5 小結(jié)
11 錯(cuò)誤處理,調(diào)試和測(cè)試
9.2 確保輸入過濾
14.2 Session支持
6.4 預(yù)防session劫持
12.4 備份和恢復(fù)
8.1 Socket編程
13.1 項(xiàng)目規(guī)劃
13.4 日志和配置設(shè)計(jì)
7.6 字符串處理
13.2 自定義路由器設(shè)計(jì)
6.3 session存儲(chǔ)
3.4 Go的http包詳解
8.2 WebSocket
10.3 國(guó)際化站點(diǎn)
7.5 文件操作
7.4 模板處理
9.1 預(yù)防CSRF攻擊
13.3 controller設(shè)計(jì)
2.6 interface
14.4 用戶認(rèn)證
2.3 流程和函數(shù)
附錄A 參考資料
11.1 錯(cuò)誤處理
9.5 存儲(chǔ)密碼
9.3 避免XSS攻擊
12.2 網(wǎng)站錯(cuò)誤處理
6 session和數(shù)據(jù)存儲(chǔ)
2.4 struct類型
3.3 Go如何使得Web工作
2.5 面向?qū)ο?/span>
3.1 Web工作方式
1.2 GOPATH與工作空間
2.1 你好,Go
9.7 小結(jié)
13.5 實(shí)現(xiàn)博客的增刪改
7.2 JSON處理
10.2 本地化資源
7.3 正則處理
2 Go語言基礎(chǔ)
5.1 database/sql接口
4.5 處理文件上傳
8.5 小結(jié)
4.3 預(yù)防跨站腳本
5.3 使用SQLite數(shù)據(jù)庫
14.7 小結(jié)
3.2 Go搭建一個(gè)Web服務(wù)器
2.7 并發(fā)
5 訪問數(shù)據(jù)庫
4 表單
3.5 小結(jié)
1.4 Go開發(fā)工具
11.4 小結(jié)
9 安全與加密
5.2 使用MySQL數(shù)據(jù)庫
4.6 小結(jié)
8.4 RPC

13.3 controller設(shè)計(jì)

傳統(tǒng)的MVC框架大多數(shù)是基于Action設(shè)計(jì)的后綴式映射,然而,現(xiàn)在Web流行REST風(fēng)格的架構(gòu)。盡管使用Filter或者rewrite能夠通過URL重寫實(shí)現(xiàn)REST風(fēng)格的URL,但是為什么不直接設(shè)計(jì)一個(gè)全新的REST風(fēng)格的 MVC框架呢?本小節(jié)就是基于這種思路來講述如何從頭設(shè)計(jì)一個(gè)基于REST風(fēng)格的MVC框架中的controller,最大限度地簡(jiǎn)化Web應(yīng)用的開發(fā),甚至編寫一行代碼就可以實(shí)現(xiàn)“Hello, world”。

controller作用

MVC設(shè)計(jì)模式是目前Web應(yīng)用開發(fā)中最常見的架構(gòu)模式,通過分離 Model(模型)、View(視圖)和 Controller(控制器),可以更容易實(shí)現(xiàn)易于擴(kuò)展的用戶界面(UI)。Model指后臺(tái)返回的數(shù)據(jù);View指需要渲染的頁面,通常是模板頁面,渲染后的內(nèi)容通常是HTML;Controller指Web開發(fā)人員編寫的處理不同URL的控制器,如前面小節(jié)講述的路由就是URL請(qǐng)求轉(zhuǎn)發(fā)到控制器的過程,controller在整個(gè)的MVC框架中起到了一個(gè)核心的作用,負(fù)責(zé)處理業(yè)務(wù)邏輯,因此控制器是整個(gè)框架中必不可少的一部分,Model和View對(duì)于有些業(yè)務(wù)需求是可以不寫的,例如沒有數(shù)據(jù)處理的邏輯處理,沒有頁面輸出的302調(diào)整之類的就不需要Model和View,但是controller這一環(huán)節(jié)是必不可少的。

beego的REST設(shè)計(jì)

前面小節(jié)介紹了路由實(shí)現(xiàn)了注冊(cè)struct的功能,而struct中實(shí)現(xiàn)了REST方式,因此我們需要設(shè)計(jì)一個(gè)用于邏輯處理controller的基類,這里主要設(shè)計(jì)了兩個(gè)類型,一個(gè)struct、一個(gè)interface

type Controller struct {
    Ct        *Context
    Tpl       *template.Template
    Data      map[interface{}]interface{}
    ChildName string
    TplNames  string
    Layout    []string
    TplExt    string
}

type ControllerInterface interface {
    Init(ct *Context, cn string)    //初始化上下文和子類名稱
    Prepare()                       //開始執(zhí)行之前的一些處理
    Get()                           //method=GET的處理
    Post()                          //method=POST的處理
    Delete()                        //method=DELETE的處理
    Put()                           //method=PUT的處理
    Head()                          //method=HEAD的處理
    Patch()                         //method=PATCH的處理
    Options()                       //method=OPTIONS的處理
    Finish()                        //執(zhí)行完成之后的處理     
    Render() error                  //執(zhí)行完method對(duì)應(yīng)的方法之后渲染頁面
}

那么前面介紹的路由add函數(shù)的時(shí)候是定義了ControllerInterface類型,因此,只要我們實(shí)現(xiàn)這個(gè)接口就可以,所以我們的基類Controller實(shí)現(xiàn)如下的方法:

func (c *Controller) Init(ct *Context, cn string) {
    c.Data = make(map[interface{}]interface{})
    c.Layout = make([]string, 0)
    c.TplNames = ""
    c.ChildName = cn
    c.Ct = ct
    c.TplExt = "tpl"
}

func (c *Controller) Prepare() {

}

func (c *Controller) Finish() {

}

func (c *Controller) Get() {
    http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
}

func (c *Controller) Post() {
    http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
}

func (c *Controller) Delete() {
    http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
}

func (c *Controller) Put() {
    http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
}

func (c *Controller) Head() {
    http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
}

func (c *Controller) Patch() {
    http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
}

func (c *Controller) Options() {
    http.Error(c.Ct.ResponseWriter, "Method Not Allowed", 405)
}

func (c *Controller) Render() error {
    if len(c.Layout) > 0 {
        var filenames []string
        for _, file := range c.Layout {
            filenames = append(filenames, path.Join(ViewsPath, file))
        }
        t, err := template.ParseFiles(filenames...)
        if err != nil {
            Trace("template ParseFiles err:", err)
        }
        err = t.ExecuteTemplate(c.Ct.ResponseWriter, c.TplNames, c.Data)
        if err != nil {
            Trace("template Execute err:", err)
        }
    } else {
        if c.TplNames == "" {
            c.TplNames = c.ChildName + "/" + c.Ct.Request.Method + "." + c.TplExt
        }
        t, err := template.ParseFiles(path.Join(ViewsPath, c.TplNames))
        if err != nil {
            Trace("template ParseFiles err:", err)
        }
        err = t.Execute(c.Ct.ResponseWriter, c.Data)
        if err != nil {
            Trace("template Execute err:", err)
        }
    }
    return nil
}

func (c *Controller) Redirect(url string, code int) {
    c.Ct.Redirect(code, url)
}   

上面的controller基類已經(jīng)實(shí)現(xiàn)了接口定義的函數(shù),通過路由根據(jù)url執(zhí)行相應(yīng)的controller的原則,會(huì)依次執(zhí)行如下:

Init()      初始化
Prepare()   執(zhí)行之前的初始化,每個(gè)繼承的子類可以來實(shí)現(xiàn)該函數(shù)
method()    根據(jù)不同的method執(zhí)行不同的函數(shù):GET、POST、PUT、HEAD等,子類來實(shí)現(xiàn)這些函數(shù),如果沒實(shí)現(xiàn),那么默認(rèn)都是403
Render()    可選,根據(jù)全局變量AutoRender來判斷是否執(zhí)行
Finish()    執(zhí)行完之后執(zhí)行的操作,每個(gè)繼承的子類可以來實(shí)現(xiàn)該函數(shù)

應(yīng)用指南

上面beego框架中完成了controller基類的設(shè)計(jì),那么我們?cè)谖覀兊膽?yīng)用中可以這樣來設(shè)計(jì)我們的方法:

package controllers

import (
    "github.com/astaxie/beego"
)

type MainController struct {
    beego.Controller
}

func (this *MainController) Get() {
    this.Data["Username"] = "astaxie"
    this.Data["Email"] = "astaxie@gmail.com"
    this.TplNames = "index.tpl"
}

上面的方式我們實(shí)現(xiàn)了子類MainController,實(shí)現(xiàn)了Get方法,那么如果用戶通過其他的方式(POST/HEAD等)來訪問該資源都將返回403,而如果是Get來訪問,因?yàn)槲覀冊(cè)O(shè)置了AutoRender=true,那么在執(zhí)行完Get方法之后會(huì)自動(dòng)執(zhí)行Render函數(shù),就會(huì)顯示如下界面:

http://wiki.jikexueyuan.com/project/go-web-programming/images/13.4.beego.png" alt="" />

index.tpl的代碼如下所示,我們可以看到數(shù)據(jù)的設(shè)置和顯示都是相當(dāng)?shù)暮?jiǎn)單方便:

<!DOCTYPE html>
<html>
  <head>
    <title>beego welcome template</title>
  </head>
  <body>
    <h1>Hello, world!{{.Username}},{{.Email}}</h1>
  </body>
</html>