這裡要介紹好是revel框架的表單post提交的列子,主要是用於入門學習,和一些知識點的講解;
首先:
來了解一個問題那就是重複提交表單,做過form表單提交的同學都知道,如果表單提交後不做處理,那麼直接在瀏覽器按下F5,會再次提交表單內容到伺服器,這就是重複提交,當然要防止這個有多種方法,這裡簡單描述一種常見的:
一種是加入token失效驗證,這個token其實就是一個值,驗證的原理是第一次客戶開啟頁面時候獲取到一個分配的值,每次使用者重新整理頁面的時候這個分配的值都需要變動,並且這個值在使用者提交表單時候會進行驗證,驗證頁面傳遞到後端程式儲存的值是否一致,如果提交表單成功後,這個值會失效或者來說被清空。
其次:上程式碼+分析
package controllers import "github.com/revel/revel" import "fmt" //import "io/ioutil" import "encoding/json" import "os" import "io" import "time" import "net/http" type Concate struct { Name string Link string Concat string Tel string Email string } func WriteFileAppend(filename string, data []byte) error { fl, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE, 0644) if err != nil { return err } defer fl.Close() n, err := fl.Write(data) if err == nil && n < len(data) { err = io.ErrShortWrite } return err } func (c App) Add() revel.Result { method := c.Request.Method fmt.Printf(method) ck_name := "add_token" if method == "POST" { name := c.Params.Get("txtName") link := c.Params.Get("txtLink") concat := c.Params.Get("txtHeader") tel := c.Params.Get("txtTel") email := c.Params.Get("txtEmail") token := c.Params.Get("add_token") fmt.Printf("學校加入引數:name=%v;link=%v;concat=%v;tel=%v;email=%v;token=%V", name, link, concat, tel, email, token) c.Validation.Required(token).Message("token驗證失敗,請重新開啟頁面") c.Validation.Required(name).Message("學校名稱,必須填寫") c.Validation.Required(concat).Message("申請人名,必須填寫") c.Validation.Required(tel).Message("聯絡電話,必須填寫") c.Validation.Required(email).Message("聯絡郵箱,必須填寫") if c.Validation.HasErrors() { // 在flash上下文中儲存驗證錯誤並重定向 c.Validation.Keep() c.FlashParams() return c.Render() } result := "加入園子-失敗" ck_Token, ck_err := c.Request.Cookie(ck_name) if ck_err != nil { return c.Render(result) } if ck_Token.Value != token { return c.Render(result) } concate := Concate{Name: name, Link: link, Concat: concat, Tel: tel, Email: email} bb, err := json.Marshal(concate) if err != nil { return c.Render(result) } bstr := string(bb) + "," bbNew := []byte(bstr) err = WriteFileAppend(`./WiKiApp/public/js/add.json`, bbNew) if err == nil { result = " 加入園子-成功,稍後會有郵件或客服人員聯絡您" } return c.Render(result) } //建立token,防止重複提交 token := time.Now().Format("2006-01-02 15:04:05") ck := http.Cookie{Name: ck_name, Value: token} c.SetCookie(&ck) return c.Render(token) }
第一次進來路由指向這個頁面的時候是get請求,此時使用cookie儲存一下生成的token,revel框架是mvc模式,可以通過c.Render(token)把引數輸出到頁面上,在使用模板直接繫結到hidden元素上面
<input type="hidden" name="add_token" value="{{.token}}"/>這裡把token輸出到了影藏域裡面,
下面就是填寫表單內容,再執行儲存提交按鈕,post到後臺的地址,這裡的程式碼知識點有
1.c.Request.Method:獲取請求的http方式;
2.c.Params.Get("txtName"):獲取頁面元素name為txtName名字的引數值;
3.fmt.Printf("%v","我愛祖國"):這裡的print就是列印資訊在後臺,%v是佔位符,類似於C#{0}效果;
4.c.Validation.Required(token).Message("token驗證失敗,請重新開啟頁面"):c.Validation.Required是revel框架封裝的驗證方法,Message("xxxx")是不符合驗證格式了,就返回的提示資訊;
5.c.FlashParams():revel框架的驗證錯誤資訊是一次性的,類似於.net mvc中的tempdata效果,只能被讀取一次;
6.ck_Token, ck_err := c.Request.Cookie(ck_name):Request.Cookie是獲取對應名稱的cookie資訊,這裡看到的:=是go語言的語法,此語法的作用很大,具體請去了解go基礎;
7.bbNew := []byte(bstr):這裡[]byte()直接吧字串資訊轉化成了byte[]看起來是不是很方便
8.WriteFileAppend:是自定義的記錄文字資訊的方法,裡面最重要的是defer fl.Close(),這個defer意思就是等待方法執行完後,在呼叫這個close釋放資源,這裡有點像finally的感覺
再發下html模板程式碼
{{set . "title" "搜-學校-加入圈子"}} {{template "header.html" .}} <form action="/app/add" method="post" style="margin-bottom:20px"> <div class="form-group"> <label for="txtName">學校-名稱(<font style="color:#337ab7">必填</font>)</label> <input type="text" class="form-control" maxlength="50" id="txtName" name="txtName" required placeholder="學校名稱"> </div> <div class="form-group"> <label for="txtLink">學校-網站地址</label> <input type="text" class="form-control" maxlength="200" id="txtLink" name="txtLink" placeholder="http://xxx"> </div> <div class="form-group"> <label for="txtHeader">學校-申請人(<font style="color:#337ab7">必填</font>)</label> <input type="text" class="form-control" maxlength="10" id="txtHeader" name="txtHeader" required placeholder="申請人名字"> </div> <div class="form-group"> <label for="txtTel">申請-電話(<font style="color:#337ab7">必填</font>)</label> <input type="text" class="form-control" maxlength="20" id="txtTel" name="txtTel" required placeholder="申請人聯絡電話號碼"> </div> <div class="form-group"> <label for="txtEmail">申請-郵箱(<font style="color:#337ab7">必填</font>)</label> <input type="Email" class="form-control" maxlength="50" id="txtEmail" name="txtEmail" required placeholder="申請人郵箱如:8123@qq.com"> </div> <!--<div class="form-group"> <label for="exampleInputFile">File input</label> <input type="file" id="exampleInputFile"> <p class="help-block">Example block-level help text here.</p> </div>--> <!--<div class="checkbox"> <label> <input type="checkbox"> Check me out </label> </div>--> <button type="submit" class="btn btn-success">保 存</button> <input type="hidden" name="add_token" value="{{.token}}"/> <span>{{.result}}</span> </form> <div class="container"> <div class="row"> <div class="span6"> {{template "flash.html" .}} </div> </div> </div> {{template "footer.html" .}}
最後,以上是一些知識點的個人認識和描述,有疑問或者有錯誤地方,歡迎來稿。