前面的章节我们学会了如何编写一个后台页面, 现在我们深入了解如何开发路由联动页面与模块化.
配置回顾
local httpd = require "httpd"
local app = httpd:new("http")
-- httpd启用Cookie扩展
app:enable_cookie()
-- httpd设置Cookie加密的密匙
app:cookie_secure("candymi")
local DB = require "DB"
local db = DB:new {
host = "localhost",
port = 3306,
username = 'root',
password = '123456789',
database = 'cfadmin',
charset = 'utf8',
max = 100,
}
db:connect()
-- 导入cf内置的admin库
local cfadmin = require "admin"
local json = require "json"
-- 注册后台页面路由
cfadmin.init_page(app, db)
local view = require "admin.view"
view.use("/admin/test1", function (ctx, db)
return view.template([[hello test1]]) { }
end)
view.use("/admin/test2", function (ctx, db)
return view.template([[hello test2]]) { }
end)
view.use("/admin/test3", function (ctx, db)
return view.template([[hello test3]]) { }
end)
view.api("/api/admin/test1", function (ctx, db)
return json.encode { code = 200, message = "这是/api/admin/test1的接口"}
end)
view.api("/api/admin/test2", function (ctx, db)
return json.encode { code = 200, message = "这是/api/admin/test1的接口"}
end)
view.api("/api/admin/test3", function (ctx, db)
return json.encode { code = 200, message = "这是/api/admin/test1的接口"}
end)
app:static("static")
app:listen("", 9090)
app:run()
view库介绍
详细的介绍可以参考这里.
现在我们简单介绍使用admin.view库注册的路由与httpd注册的路由之间的差异.
注册路由差异
第一个参数不再是一个HTTP Content, 而是一个HTTP Protocol Class. 它内部封装了一些方法可以简单的获取一系列HTTP协议相关参数.
第二个参数返回script/main.lua中注册的DB对象, 它可以在任何一个回调函数中使用. 并且不用担心阻塞与重入的问题.
安全性的差异
从安全性角度来说, admin.view会在httpd库的基础上提供安全性封装. 它根据注册路由的类型提供不同的验证方法.
例如: api路由验证Token, use路由验证Cookie. 但是原生的httpd库未提供这些, 开发者需要自行完成这些功能.
从某种角度来说, 原生httpd库更适合开发前后端分离的业务逻辑. 封装的admin库则包含管理后台业务需要的基础封装.
修改示例
本次修改主要涉及以下内容:
编写独立出单独的模板文件用来编写
HTML静态页面.根据不同的接口路由与页面路由实时渲染页面.
解决上一章节遇到的接口认证问题.
修改页面路由
首先, 在cf框架的根目录创建一个view目录用于存放我们编写普通的HTML页面模板test.html.
然后, 我们在head标签中添加title标签, 使用模板语法来用于描述当前页面路由与接口路由归属.
其次, 我们在模板主体内部包含一个h1标签, 让它来居中显示欢迎信息.
最后, 我们定义p标签, 通过jquery来请求对应接口完成message内容展示.
HTML代码如下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{*title*}</title>
<script type="text/javascript" src="/js/jquery.min.js"></script>
</head>
<body>
<h1 align="center">no h1 value</h1>
<p align="center">no p value</p>
</body>
<script>
$.ajax({
type: "get",
url : "{*domain*}",
headers: { token: "{*token*}"},
success: function(res) {
console.log(res)
$("h1").text(res.welcome)
$("p").text(res.content)
},
error: function(res) {
console.log(res)
}
})
</script>
</html>
上面的代码中, 我们混合使用了Lua模板语法与jquery的ajax请求完成页面的动态渲染与接口请求.
其中url/domain/title都是有模板渲染生成的, 这些值根据接口的不同回生成不同的值.
而h1/p标签的值则是请求接口后返回的, 由jquery库的选择器方法添加到标签內.
修改接口路由
根据上面的模板参数定义, 我们现在也来修改接口路由与页面路由都代码.
local Cookie = require "admin.cookie"
view.use("/admin/test1", function (ctx, db)
return view.template("view/test.html") {
title = "test1",
domain = "/api/admin/test1",
token = Cookie.getCookie("CFTOKEN"),
}
end)
view.use("/admin/test2", function (ctx, db)
return view.template("view/test.html") {
title = "test2",
domain = "/api/admin/test2",
token = Cookie.getCookie("CFTOKEN"),
}
end)
view.use("/admin/test3", function (ctx, db)
return view.template("view/test.html") {
title = "test3",
domain = "/api/admin/test3",
token = Cookie.getCookie("CFTOKEN"),
}
end)
view.api("/api/admin/test1", function (ctx, db)
return json.encode {
code = 200,
welcome = "欢迎来到/admin/test1的页面",
content = "这是/admin/test1的页面内容",
}
end)
view.api("/api/admin/test2", function (ctx, db)
return json.encode {
code = 200,
welcome = "欢迎来到/admin/test2的页面",
content = "这是/admin/test2的页面内容",
}
end)
view.api("/api/admin/test3", function (ctx, db)
return json.encode {
code = 200,
welcome = "欢迎来到/admin/test3的页面",
content = "这是/admin/test3的页面内容",
}
end)
可以看到, 我们为了获取token导入了admin.cookie库.
cookie库可以获得指定key的Cookie. 我们将得到的值传递给页面用于获取指定接口路由.
框架内部会保障的Cookie的有效性与权限, 即: 无效、非法、权限不足的Cookie将会和之前一样被拒绝.
展示效果
最后, 你看到的内容应该是这样子.
test1:test2:
test3:
模块化
前面我们提到了独立模板文件, 这在大量使用模板的时候是非常不错的.
但是细心的同学可能发现了, 即使这样我们的script/main.lua中的代码还是很多.
现在, 我们将不同的页面与接口路由分布到不同的文件中. 完成模块化设计
分离代码
建立
script/test文件夹, 并在test文件夹中建立这test1.lua/test2.lua/test3.lua文件.按照
相同的接口路由与页面路由一组为模式, 将这些路由代码其分别写入到这些文件夹内部.重新运行
cfadmin并查看效果.你的代码应该如下所示:
-- script/main.lua
local httpd = require "httpd"
local app = httpd:new("http")
app:enable_cookie()
app:cookie_secure("candymi")
local DB = require "DB"
local db = DB:new {
host = "localhost",
port = 3306,
username = 'root',
password = '123456789',
database = 'cfadmin',
charset = 'utf8',
max = 100,
}
db:connect()
local cfadmin = require "admin"
cfadmin.init_page(app, db)
require "test.test1"
require "test.test2"
require "test.test3"
app:static("static")
app:listen("", 8080)
app:run()
-- script/test/test1.lua
local view = require "admin.view"
local Cookie = require "admin.cookie"
local json = require "json"
view.use("/admin/test1", function (ctx, db)
return view.template("view/test.html") {
title = "test1",
domain = "/api/admin/test1",
token = Cookie.getCookie("CFTOKEN"),
}
end)
view.api("/api/admin/test1", function(ctx, db)
return json.encode {
code = 200,
welcome = "欢迎来到/admin/test1的页面",
content = "这是/admin/test1的页面内容",
}
end)
-- script/test/test2.lua
local view = require "admin.view"
local Cookie = require "admin.cookie"
local json = require "json"
view.use("/admin/test2", function (ctx, db)
return view.template("view/test.html") {
title = "test2",
domain = "/api/admin/test2",
token = Cookie.getCookie("CFTOKEN"),
}
end)
view.api("/api/admin/test2", function(ctx, db)
return json.encode {
code = 200,
welcome = "欢迎来到/admin/test2的页面",
content = "这是/admin/test2的页面内容",
}
end)
-- script/test/test3.lua
local view = require "admin.view"
local Cookie = require "admin.cookie"
local json = require "json"
view.use("/admin/test3", function (ctx, db)
return view.template("view/test.html") {
title = "test3",
domain = "/api/admin/test3",
token = Cookie.getCookie("CFTOKEN"),
}
end)
view.api("/api/admin/test3", function(ctx, db)
return json.encode {
code = 200,
welcome = "欢迎来到/admin/test3的页面",
content = "这是/admin/test3的页面内容",
}
end)
这样模块化之后的代码, 无论可读性还是维护性都提升了一个档次.
最后
这一章我们学会了如何编写一个后台页面, 下面的章节我们将单独介绍模板的使用方法.
