概述
設計一個 web 小應用,展示靜態文件服務、js 請求支持、模板輸出、表單處理、Filter 中間件設計等方面的能力。(不需要數據庫支持)
任務要求
編程 web 應用程序 cloudgo-io。 請在項目 README.MD 給出完成任務的證據!
實現內容
1) 支持靜態文件服務
2) 支持簡單 js 訪問
3) 提交表單,並輸出一個表格
4) 對 /unknown 給出開發中的提示,返回碼 5xx
這次我實現的是一個基於Gin框架開發的Web服務程序,基礎的網頁前端是之前上Web 2.0課程中登陸界面的作業代碼。具體來說是一個支持用戶注冊和信息查看的網頁。用戶可以登錄並查看他們的信息,然后可以通過網址欄跳轉到相應網頁進行查看。做了一些關於用戶信息的重復判斷和一些魯棒性方面的東西。
首先上一張預覽圖,讓大家看看效果:

Gin框架簡介
Gin是一個golang的微框架,封裝比較優雅,API友好,源碼注釋比較明確,已經發布了1.0版本。具有快速靈活,容錯方便等特點。其實對於golang而言,web框架的依賴要遠比Python,Java之類的要小。自身的net/http足夠簡單,性能也非常不錯。框架更像是一些常用函數或者工具的集合。借助框架開發,不僅可以省去很多常用的封裝帶來的時間,也有助於團隊的編碼風格和形成規范
下面為了讓大家能夠對Gin有更好的認識和基本的上手,這里介紹一下使用Gin實現的Hello,World。
import (
"gopkg.in/gin-gonic/gin.v1"
"net/http"
)
func main(){
router := gin.Default()
router.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "Hello World")
})
router.Run(":8000")
}
簡單幾行代碼,就能實現一個web服務。使用gin的Default方法創建一個路由handler。然后通過HTTP方法綁定路由規則和路由函數。不同於net/http庫的路由函數,gin進行了封裝,把request和response都封裝到gin.Context的上下文環境。最后是啟動路由的Run方法監聽端口。麻雀雖小,五臟俱全。當然,除了GET方法,gin也支持POST,PUT,DELETE,OPTION等常用的restful方法。
靜態文件服務
在Gin中,搭建靜態文件服務是比較容易的一件事情,下面貼一段代碼:
func main() {
router := gin.Default()
router.Static("/assets", "./assets")
// Listen and server on 0.0.0.0:8080
router.Run(":8080")
}
上面這段代碼,為路由器指定了一個Static Route,所有指向assets的訪問,都會去./assets這個目錄下面進行查找
簡單js訪問以及對於表單的處理
當客戶端試圖通過用POST方法向服務端發送請求的時候,它實際上是向服務端發送了一個POST方法的表單數據。因為,我們處理POST方法實際上是處理了一個表單數據,gin框架在這方面有也完備的做法:
// 這里創建的這個type是用來綁定數據並傳送去服務端的
type registerJSON struct {
Username string `form:"username" binding:"required"`
Stuid string `form:"stuid" binding:"required"`
Tel string `form:"tel" binding:"required"`
Email string `form:"email" binding:"required"`
}
// 創建一個type的實例用於綁定數據
var user registerJSON
// 試圖綁定由客戶端發送的數據
if err := c.Bind(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"code": "BAD_REQUEST",
"message": "Something wrong with the server",
})
fmt.Println(err.Error())
return
}
在上面的示例代碼中,我們為其分配了表單中的字段,從而使它可以去解析一個 POST 表單。進而進行進一步的邏輯處理。通過 Bind 方法,我們就能將請求中的數據悉數傳入到給定的綁定實例上,而如果有任何問題發生,一個 err 將會被返回給你。
/unknown與404的實現
/unknown實現也不是一個很難實現的東西,用一些基本的語法就可以實現了:
router.GET("/unknown", func(c *gin.Context) {
c.JSON(http.StatusNotImplemented, gin.H{
"code": "NOT_IMPLEMENTED",
"message": "This page has not been implemented.",
})
})
所謂的404問題,也就是找不到對應的page嘛,Gin框架里面有一個NoRoute方法,它可以捕獲到所有未能通過Route方法指定處理函數的請求,並且為這些未處理的請求統一分配函數。
router.NoRoute(func(c *gin.Context) {
c.JSON(http.StatusNotFound, gin.H{
"code": "PAGE_NOT_FOUND",
"message": "Target page not found.",
})
})
