[Toc]
web小应用之cloudgo-io
1、概述
1.1 功能
这是一个简单的web小应用,有以下几个功能:
- 支持静态文件服务
- 支持简单的js访问
- 提交表单,并输出一个表格
- 对/unknow给出开发中的提示,返回码501
1.2 运行
- 转到main.go所在目录,执行以下命令
go run main.go # 不指定端口默认8080
or
go run main.go -p 9090 # 指定监听9090端口
or
go install && cloudgo-io [-p ...] # 先安装之后可以直接使用cloudgo-io或cloudgo-io -p ...命令启动
- 在浏览器地址栏输入
# 登录界面
http://localhost:yourport/login
# 静态资源文件服务
http://localhost:yourport/public
# 未开发
http://localhost:yourport/unknown
1.3 效果
- 主界面(背景来自我的github page)
- 支持静态文件服务
- 支持简单的js访问(可跳转到静态资源界面)
- 提交表单,并输出一个表格
- 对/unknow给出开发中的提示,返回码501
2、挑选框架
综合比较了最常见的六种框架后,我选择了iris,毕竟年份最新、功能最全、速度最快。
这是2017年的统计数据。虽然star数暂时没有beego那么多,但是iris比beego慢了四年诞生,发展得很快。
当然我选择iris最大的原因,还是因为下图,功能这么全,早进坑早享受。不过现在iris网上的教程比较稀缺,多数需要先跟着官方example一步一步摸索。
以上两幅图片引用自:
https://blog.csdn.net/dev_csdn/article/details/78740990
关于速度,见iris最新官方数据。
3、文件结构
没有硬性规定,但是最好把负责不同模块或功能的文件分到不同的文件夹,便于维护。我的文件结构如下:
cloudgo-io/
configs/
main.tml
static/
css/
js/
img/
services/
GetPages.go
ServicesManager.go
templates/
login.html
info.html
- configs中的main.tml文件可交由服务器管理员配置服务器后台。虽然也可以放在代码中配置,但是这样比较方便,不用每次都重新编译代码。
- static存放静态文件。
- services存放服务器提供服务的一系列代码,最后可以为这一系列服务安排一个manger统一管理,也方便统一调用。
- templates存放网页的模板,在模板中需要留一些待注入的标记,有了这些预设的标记便可以在代码中找到对应的标记进行填充,比直接找element方便许多。
<table border="1">
<tr>
<th>username</th>
<td>{{.username}}</td>
</tr>
<tr>
<th>password</th>
<td>{{.password}}</td>
</tr>
</table>
以下介绍一些我的一些关于iris的探索成果和使用心得
4、iris的简单使用
4.1 获取iris
go get -u github.com/kataras/iris
4.2 使用的套路
- 最简单版(官方例子)
package main
import "github.com/kataras/iris"
func main() {
app := iris.Default()
app.Get("/ping", func(ctx iris.Context) {
ctx.JSON(iris.Map{
"message": "pong",
})
})
// listen and serve on http://0.0.0.0:8080.
app.Run(iris.Addr(":8080"))
}
- 一般步骤:
- 1.先获取到iris的app。可以通过iris.New方式获取后自己配置一些参数,也可以通过iris.Default直接获取它的一个默认的app,app的类型是iris.Application。
- 2.可选步骤(如下面我的main.go)
- 2.1 允许用户自己设置监听的端口——如使用pflag实现用户指定端口。
- 2.2 设置日志等级。默认为info等级,debug等级会输出更多的信息,方便调试。
- 2.3 启动你提供的服务。
- 2.4 其他
- 3.app.Run运行app(顺便进行服务器配置,推荐)
package main
import (
"os"
"github.com/gitgiter/ServiceComputing/cloudgo-io/services"
"github.com/kataras/iris"
"github.com/spf13/pflag"
)
const (
// PORT 8080 (default)
PORT string = "8080"
)
func main() {
// get and set server listening port
port := os.Getenv("PORT")
if len(port) == 0 {
port = PORT
}
pPort := pflag.StringP("port", "p", PORT, "http listening port")
pflag.Parse()
if len(*pPort) != 0 {
port = *pPort
}
// get iris http server app
app := iris.Default()
// set logger level
app.Logger().SetLevel("debug")
services.StartServices(app)
// listen and serve on http://localhost:port
// configuring by file is more convenient
app.Run(iris.Addr(":"+port), iris.WithConfiguration(iris.TOML("./configs/main.tml")))
}
4.3 配置
服务器配置有三种方式:
- 第一种是直接在app.Run的时候显式配置
app.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.Configuration{
DisableInterruptHandler: false,
DisablePathCorrection: false,
EnablePathEscape: false,
FireMethodNotAllowed: false,
DisableBodyConsumptionOnUnmarshal: false,
DisableAutoFireStatusCode: false,
TimeFormat: "Mon, 02 Jan 2006 15:04:05 GMT",
Charset: "UTF-8",
}))
- 第二种比较推荐,便是通过配置文件的形式,这样便可以在修改配置的时候不需要重新编译。如configs目录下的main.tml是我当前的配置,读取配置的方法就是4.2中的例子。
DisablePathCorrection = false
EnablePathEscape = false
FireMethodNotAllowed = true
DisableBodyConsumptionOnUnmarshal = false
TimeFormat = "Mon, 01 Jan 2006 15:04:05 GMT"
Charset = "UTF-8"
MyServerName = "gitgiter's iris"
- 第三种则是直接在app.Run前调用app.Configure方法进行设置,这种比较不推荐,效果和第一种差不多而且可读性还没有第一种好。
5、使用iris实现上述四种服务
5.1 静态文件服务
第一个参数是一个虚拟路径,第二个参数才是真正的系统路径。
// load static files
// first parameter is the href request url, second is the real system path
app.StaticWeb("/public", "./static")
虚拟路径是給用户访问用的,如此时如果用户要访问我的静态文件目录,只需要在浏览器输入类似 ip:port/public/css/main.css 即可访问我的静态文件。可以避免系统路径改变导致用户的访问路径也要改变的麻烦。
为了进一步避免这种麻烦,可以在 /public 下所有的跳转链接,避免用户需要记住具体的静态文件路径。Context的HTML方法可以直接向页面写入html,这种适合写少量HTML的时候使用,要写大量HTML的最好的做法还是通过文件,否则会影响代码可读性且增大耦合性。
app.Get("/public", func(ctx iris.Context) {
ctx.HTML(`<a href='/public/css/main.css'>/public/css/main.css</a><br/><br/>
<a href='/public/img/bg.jpg'>/public/img/bg.jpg</a><br/><br/>
<a href='/public/img/favicon.ico'>/public/img/favicon.ico</a><br/><br/>
<a href='/public/js/showStatic.js'>/public/js/showStatic.js</a>`)
})
5.2 js请求
这里只写了一个很简单的js请求作为示例,比如点击登录界面中的Response按钮可以触发js的页面跳转事件。
js文件:
function myfunction()
{
window.open("/public")
}
设置按钮点击事件:
js test: <input type="button" onclick="myfunction()" value="response">
处理请求,就是5.1写的那个。app.Get可以用来处理Get方式的请求,第一个参数为请求的url,第二个参数可以用一个函数指定请求的处理方式。
app.Get("/public", func(ctx iris.Context) {
...
})
5.3 表单提交,填充模板
- 表单——form。表单提交一般采用POST模式,尤其是带有敏感信息的表单,这样表单的参数不会显示在url中。action用来指定表单提交后的动作,这里是跳转到/info页面。
<form method="POST" action="/info">
username: <input type="text" name="Username"><br/><br/>
password: <input type="password" name="Password"><br/><br/>
<input type="submit" value="login"><br/><br/>
js test: <input type="button" onclick="myfunction()" value="response">
</form>
- 通过文件设置HTML视图时需要提前注册视图才可以加载视图。第一个参数指定你要加载的视图文件所在的文件夹,第二个参数指定要加载的文件后缀是html。Reload设置为true可以避免每次改动模板时需要重启app,对开发者比较友好,对用户来说没太大区别。
// register views from ./templates folder
app.RegisterView(iris.HTML("./templates", ".html").Reload(true))
- ReadForm读取POST过来的表单,并绑定模板对视图进行填充。注意读取表单时要先定义一个结构体,这个结构体的每个字段名称需要和表单一致,且首字母必须大写,表示exported。ViewData填充数据使用键值对即可,key就是info.html里面定义的模板,value就是要替换的值。View加载指定文件的视图。
type User struct {
Username string
Password string
}
// GetInfoPage load html and static web
func GetInfoPage(app *iris.Application) {
app.Post("/info", func(ctx iris.Context) {
// get the form data
form := User{}
err := ctx.ReadForm(&form)
if err != nil {
ctx.StatusCode(iris.StatusInternalServerError)
ctx.WriteString(err.Error())
}
// bind data by passing key-value pair
username := form.Username
password := form.Password
ctx.ViewData("username", username)
ctx.ViewData("password", password)
ctx.View("info.html")
})
}
5.4 /unknown报错
这个和前面的网页请求同理,不过需要通过app.StatusCode设置一个返回码以让用户知道是什么原因导致的页面无效,默认是返回200即正常访问。
// NotImplement returns 501 error to client
func NotImplement(app *iris.Application) {
app.Get("/unknown", func(ctx iris.Context) {
ctx.StatusCode(501)
ctx.JSON(iris.Map{
"error": "501 not implement error",
})
})
}
6、其他
- 项目地址:gitgiter/ServiceComputing/cloudgo-io
- github page:gitgiter.github.io
- csdn blog:wonderful_sky