概述
设计一个 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.",
})
})