bee
使用beego创建新项目
beego 的项目基本都是通过 bee 命令来创建的,所以在创建项目之前确保你已经安装了 bee 工具和 beego。如果你还没有安装,那么请查阅 beego 的安装 和 bee 工具的安装。
现在一切就绪我们就可以开始创建项目了,打开终端,进入 $GOPATH/src 所在的目录:
创建一个项目名为20180118_loongc_beego的基于beego 的新项目,执行如下命令:
bee new 20180118_loongc_beego
依次执行如下命令:进入目录,运行该项目,在localhost:8080里查看,如下图
cd 20180118_loongc_beego
bee run
安装beego orm, 降低复杂的ORM(Object-Relational MAPPing,对象关系映射)学习曲线,执行如下命令:
go get github.com/astaxie/beego
go get github.com/lib/pq
func init(){
orm.RegisterDriver(“postgres”. orm.DRPostgres)
orm.RegisterDataBase(“default”, “postgres”, “user=postgres password=nasadmin dbname=20180111_loongc_test host=127.0.0.1 port=5432 sslmode=disable”)
orm.RegisterModel(
new(models.User))
orm.RunSyncdb("default", false, true)
}
orm.RegisterDriver为配置postgresql数据库驱动
orm.RegisterDataBase中:
“default”是默认项
“postgres”表示使用的是postgresql数据库
user=postgres password=nasadmin dbname=20180111_loongc_test:分别表示数据库用户名、用户密码、数据库名
host=127.0.0.1 port=5432:分别表示数据库主机地址、数据库端口(5432是postgresql的默认端口)
orm.RegisterModel:表示注册model,每添加一个model文件,都需要register,否则无法访问。当前表示有两个model,User和topic
模型构造
在文件夹models下新建文件User.go,文件内容如下:
package models
import (
“github.com/astaxie/beego/orm”
)
type User struct {
Id int `json: “id”`
Username string `json:”username”`
Password string `json:”password”`
Role string `json:”role”`
}
模型User构造完成,一个完整的模型还需要添加函数通用方法,这里实现一个用户登录,在文件中添加用户登录验证函数,如下:
func Login(username string, password string)(bool, User){
o := orm.NewOrm()
var user User
err := o.QueryTable(user).Filter(“Username”, username).Filter(“Password”, password).One(&user)
return err != orm.ErrNoRows, user
}
登录界面
在views目录底下添加login.tpl文件,tpl文件是模板写法,本质还是遵循html文件写法,但是支持框架本身的很多变量。文件内容如下:
<!DOCTYPE html>
<html>
<head>
<title>Login page</title>
</head>
<body >
<form id="loginform">
id:<input type="text" name="username" value="{{.Username}}"><br>
pw:<input type="password" name="password" value="{{.Password}}"><br>
<input type="button" value="submit" id="loginbtn">
</form>
<script type="text/javascript" src="/static/js/jquery-3.2.1.js"></script>
<script type="text/JavaScript">
$(function(){
$('#loginbtn').bind('click', function(){
$.ajax({
url: "/login",
type: "post",
asyns: true,
data: $('#loginform').serialize(),
// dataType: "json",
success: function(res){
console.log(res);
if(res){
window.location.href = "/index";
}else{
window.location.href = "/";
}
// console.log({{.flash.success}});
// {{if .flash.success}}
// window.location.href = {{.flash.success}};
// {{end}}
},
ERROR: function(XMLHttprequest, testStatus, errorthrown){
console.log(XMLHttpRequest.status);
console.log(XMLHttpRequest.readyState);
console.log(testStatus);
}
});
})
});
</script>
</body>
</html>
控制器
beego框架中,所有视图view显示,都是要定义在控制器里的。当登录页面已经构建好,但是无法在浏览器里马上渲染。这也是beego的局限性,当我需要创建一个新的tpl文件放到服务器端,然后在iframe里通过src引用的时候,新的tpl的名字是动态的,无法动态的在控制器里添加定义。
在当前登录功能中,包括两个控制器,代码如下:
一个登录页面渲染控制器Loginpage,它定义了模板文件的位置,并且定义了两个输入框的值,在登录页面通过{{.Username}}的方法给用户id输入框设置默认值。
一个登录验证控制器Login,它是将用户提交的username和password拿到之后,然后调用之前model里定义的方法,实现验证。验证成功之后进入index.tpl页面(主页),验证失败仍停留在login.tpl。这里仍存在一个beego的问题,如果使用jquery 的ajax方法,beego无法设置返回值,这里原来的Redirect的也会失效,甚至c.TplName方法也同样不起作用。
package controllers
import (
"github.com/astaxie/beego"
"server/20180118_loongc_beego/models"
)
type LoginController struct {
beego.Controller
}
func (c *LoginController) Loginpage() {
c.Data["Username"] = "loongc"
c.Data["Password"] = "123"
c.Data["Error"] = ""
c.TplName = "login.tpl"
}
func (c *LoginController) Login() {
flash := beego.NewFlash()
username, password := c.Input().Get("username"), c.Input().Get("password")
if flag, _ := models.Login(username, password); flag {
// c.SetSecureCookie(beego.AppConfig.String("cookie.secure"), beego.AppConfig.String("cookie.role"), user.Role, 1*1*20*60, beego.AppConfig.String("cookie.domain"), "/", false, true)
c.Redirect("/index", 302)
// c.TplName = "index.tpl"
return
} else {
flash.Error("username or password error")
c.Redirect("/error", 302)
return
}
}
路由
登录界面使用jquery ajax发送的请求是如何被beego框架捕获的,因为很明显的是在这个案例中url给的value是 /login ,这是一个不符合一般化的ajax格式的值,这个是由beego框架自己定义的路由来控制的。在routers目录底下有一个router.go文件,在这里定义了前端的所有请求的最后会被分发到不同控制器,代码如下所示:
package routers
import (
"github.com/astaxie/beego"
"server/20180118_loongc_beego/controllers"
)
func init() {
beego.Router("/", &controllers.LoginController{}, "GET:Loginpage")
beego.Router("/login", &controllers.LoginController{}, "POST:Login")
beego.Router("/index", &controllers.IndexController{}, "GET:Indexpage")
beego.Router("/error", &controllers.IndexController{}, "GET:Error")
}
这里一共定义了四个四个不同的路由,按顺序,分别是初始化web的默认打开页面、登录验证控制器、初始化index.tpl(这个是登录成功之后打开的页面),最后一个是在本实例中设计的登录页面跳转问题,后续章节继续说明。
beego的局限性和解决登录跳转问题
- 前面已经提到的,对于所有view文件的渲染,都需要事先在控制器里定义好,对于新生成的view文件,目前来看好像无能为力
- 其次,在于与jquery ajax的配合,beego在这种情况下好像无法返回值,当我在控制器里添加return 一个bool值,并没有拿到,但是通过控制器里存在Redirect方法,console.log(res)时,可以返回Redirect的页面代码。基于以上,ajax无法获得控制页面跳转的参数,不仅如此,beego自身的页面跳转也会出现失效问题。尽管官方提供了扩展方法,但是好像不是很成熟
解决登录跳转
在这里还是坚持ajax做数据发送,因为并不是所有的情况的都是通过input、testxarea、select输入要保存的数据。
在这里提供鉴于console.log(res)出的是要打开页面的代码,那么假设验证登录失败,如果打开的页面是个空的文档,那么if(res) 只有在验证正确的时候才会恒为true,否则就为false,所以我在路由中定义了一个 /error 的路由,在控制器里让它打开一个名为error.tpl的空文档,当验证错误的时候console.log(res)是空的,所以if(res)为false,以此来控制登录验证成功与否时的跳转。但是提示错误信息并没有很好展现
结论
beego是比较完善的框架,但是适用范围仅限于,按照模板输出不同数据。
后台控制跳转,算不得友好,尤其是前端<a>标签都无法单独控制页面跳转。
无法实现灵活的数据数据输入,路由限制决定了数据发送方式被限定太死,不符合实际。尤其是与ajax这种很成熟的数据路由配合都很差。
输入数据的合法性校验,由后端完成,这种工作应该尽量由前端完成。