Lua admin后台开发 (5) 路由联动与模块化

前面的章节我们学会了如何编写一个后台页面, 现在我们深入了解如何开发路由联动页面与模块化.

配置回顾

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库则包含管理后台业务需要的基础封装.

修改示例

本次修改主要涉及以下内容:

  1. 编写独立出单独的模板文件用来编写HTML静态页面.

  2. 根据不同的接口路由与页面路由实时渲染页面.

  3. 解决上一章节遇到的接口认证问题.

修改页面路由

首先, 在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模板语法jqueryajax请求完成页面的动态渲染与接口请求.

其中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库可以获得指定keyCookie. 我们将得到的值传递给页面用于获取指定接口路由.

框架内部会保障的Cookie的有效性与权限, 即: 无效、非法、权限不足的Cookie将会和之前一样被拒绝.

展示效果

最后, 你看到的内容应该是这样子.

test1:
在这里插入图片描述

test2:


在这里插入图片描述

test3:
在这里插入图片描述

模块化

前面我们提到了独立模板文件, 这在大量使用模板的时候是非常不错的.

但是细心的同学可能发现了, 即使这样我们的script/main.lua中的代码还是很多.

现在, 我们将不同的页面与接口路由分布到不同的文件中. 完成模块化设计

分离代码

  1. 建立script/test文件夹, 并在test文件夹中建立这test1.lua/test2.lua/test3.lua文件.

  2. 按照相同的接口路由与页面路由一组为模式, 将这些路由代码其分别写入到这些文件夹内部.

  3. 重新运行cfadmin并查看效果.

  4. 你的代码应该如下所示:

-- 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)

这样模块化之后的代码, 无论可读性还是维护性都提升了一个档次.

最后

这一章我们学会了如何编写一个后台页面, 下面的章节我们将单独介绍模板的使用方法.

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容