动态web网页开发是Web开发中一个常见的场景,比如像京东商品详情页,其页面逻辑是非常复杂的,需要使用模板技术来实现。而Lua中也有许多模板引擎,如目前我在使用的lua-resty-template,可以渲染很复杂的页面,借助LuaJIT其性能也是可以接受的。

如果学习过JavaEE中的servlet和JSP的话,应该知道JSP模板最终会被翻译成Servlet来执行;而lua-resty-template模板引擎可以认为是JSP,其最终会被翻译成Lua代码,然后通过ngx.print输出。

而lua-resty-template和大多数模板引擎是类似的,大体内容有:

模板位置:从哪里查找模板;

变量输出/转义:变量值输出;

代码片段:执行代码片段,完成如if/else、for等复杂逻辑,调用对象函数/方法;

注释:解释代码片段含义;

include:包含另一个模板片段;

其他:lua-resty-template还提供了不需要解析片段、简单布局、可复用的代码块、宏指令等支持。

首先需要下载lua-resty-template

Java代码  
  1. cd /usr/example/lualib/resty/
  2. wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template.lua
  3. mkdir /usr/example/lualib/resty/html
  4. cd /usr/example/lualib/resty/html
  5. wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template/html.lua

接下来就可以通过如下代码片段引用了

Java代码  
  1. local template = require("resty.template")

模板位置

我们需要告诉lua-resty-template去哪儿加载我们的模块,此处可以通过set指令定义template_location、template_root或者从root指令定义的位置加载。

如我们可以在example.conf配置文件的server部分定义

Java代码  
  1. #first match ngx location
  2. set $template_location "/templates";
  3. #then match root read file
  4. set $template_root "/usr/example/templates";

也可以通过在server部分定义root指令

Java代码  
  1. root /usr/example/templates;

其顺序是

Java代码  
  1. local function load_ngx(path)
  2. local file, location = path, ngx_var.template_location
  3. if file:sub(1)  == "/" then file = file:sub(2) end
  4. if location and location ~= "" then
  5. if location:sub(-1) == "/" then location = location:sub(1, -2) end
  6. local res = ngx_capture(location .. '/' .. file)
  7. if res.status == 200 then return res.body end
  8. end
  9. local root = ngx_var.template_root or ngx_var.document_root
  10. if root:sub(-1) == "/" then root = root:sub(1, -2) end
  11. return read_file(root .. "/" .. file) or path
  12. end

1、通过ngx.location.capture从template_location查找,如果找到(状态为为200)则使用该内容作为模板;此种方式是一种动态获取模板方式;

2、如果定义了template_root,则从该位置通过读取文件的方式加载模板;

3、如果没有定义template_root,则默认从root指令定义的document_root处加载模板。

此处建议首先template_root,如果实在有问题再使用template_location,尽量不要通过root指令定义的document_root加载,因为其本身的含义不是给本模板引擎使用的。

接下来定义模板位置

Java代码  
  1. mkdir /usr/example/templates
  2. mkdir /usr/example/templates2

example.conf配置server部分

Java代码  
  1. #first match ngx location
  2. set $template_location "/templates";
  3. #then match root read file
  4. set $template_root "/usr/example/templates";
  5. location /templates {
  6. internal;
  7. alias /usr/example/templates2;
  8. }

首先查找/usr/example/template2,找不到会查找/usr/example/templates。

然后创建两个模板文件

Java代码  
  1. vim /usr/example/templates2/t1.html

内容为

Java代码  
  1. template2
Java代码  
  1. vim /usr/example/templates/t1.html

内容为

Java代码  
  1. template1

test_temlate_1.lua

Java代码  
  1. local template = require("resty.template")
  2. template.render("t1.html")

example.conf配置文件

Java代码  
  1. location /lua_template_1 {
  2. default_type 'text/html';
  3. lua_code_cache on;
  4. content_by_lua_file /usr/example/lua/test_template_1.lua;
  5. }

访问如http://192.168.1.2/lua_template_1将看到template2输出。然后rm /usr/example/templates2/t1.html,reload nginx将看到template1输出。

接下来的测试我们会把模板文件都放到/usr/example/templates下。

API

使用模板引擎目的就是输出响应内容;主要用法两种:直接通过ngx.print输出或者得到模板渲染之后的内容按照想要的规则输出。

1、test_template_2.lua

Java代码  
  1. local template = require("resty.template")
  2. --是否缓存解析后的模板,默认true
  3. template.caching(true)
  4. --渲染模板需要的上下文(数据)
  5. local context = {title = "title"}
  6. --渲染模板
  7. template.render("t1.html", context)
  8. ngx.say("<br/>")
  9. --编译得到一个lua函数
  10. local func = template.compile("t1.html")
  11. --执行函数,得到渲染之后的内容
  12. local content = func(context)
  13. --通过ngx API输出
  14. ngx.say(content)

常见用法即如下两种方式:要么直接将模板内容直接作为响应输出,要么得到渲染后的内容然后按照想要的规则输出。

2、examle.conf配置文件

Java代码  
  1. location /lua_template_2 {
  2. default_type 'text/html';
  3. lua_code_cache on;
  4. content_by_lua_file /usr/example/lua/test_template_2.lua;
  5. }

使用示例

1、test_template_3.lua

Java代码  
  1. local template = require("resty.template")
  2. local context = {
  3. title = "测试",
  4. name = "张三",
  5. description = "<script>alert(1);</script>",
  6. age = 20,
  7. hobby = {"电影", "音乐", "阅读"},
  8. score = {语文 = 90, 数学 = 80, 英语 = 70},
  9. score2 = {
  10. {name = "语文", score = 90},
  11. {name = "数学", score = 80},
  12. {name = "英语", score = 70},
  13. }
  14. }
  15. template.render("t3.html", context)

请确认文件编码为UTF-8;context即我们渲染模板使用的数据。

2、模板文件/usr/example/templates/t3.html

Java代码  
  1. {(header.html)}
  2. <body>
  3. {# 不转义变量输出 #}
  4. 姓名:{* string.upper(name) *}<br/>
  5. {# 转义变量输出 #}
  6. 简介:{{description}}<br/>
  7. {# 可以做一些运算 #}
  8. 年龄: {* age + 1 *}<br/>
  9. {# 循环输出 #}
  10. 爱好:
  11. {% for i, v in ipairs(hobby) do %}
  12. {% if i > 1 then %},{% end %}
  13. {* v *}
  14. {% end %}<br/>
  15. 成绩:
  16. {% local i = 1; %}
  17. {% for k, v in pairs(score) do %}
  18. {% if i > 1 then %},{% end %}
  19. {* k *} = {* v *}
  20. {% i = i + 1 %}
  21. {% end %}<br/>
  22. 成绩2:
  23. {% for i = 1, #score2 do local t = score2[i] %}
  24. {% if i > 1 then %},{% end %}
  25. {* t.name *} = {* t.score *}
  26. {% end %}<br/>
  27. {# 中间内容不解析 #}
  28. {-raw-}{(file)}{-raw-}
  29. {(footer.html)}

{(include_file)}:包含另一个模板文件;

{* var *}:变量输出;

{{ var }}:变量转义输出;

{% code %}:代码片段;

{# comment #}:注释;

{-raw-}:中间的内容不会解析,作为纯文本输出;

模板最终被转换为Lua代码进行执行,所以模板中可以执行任意Lua代码。

3、example.conf配置文件

Java代码  
  1. location /lua_template_3 {
  2. default_type 'text/html';
  3. lua_code_cache on;
  4. content_by_lua_file /usr/example/lua/test_template_3.lua;
  5. }

访问如http://192.168.1.2/lua_template_3进行测试。

基本的模板引擎使用到此就介绍完了。

来源:http://jinnianshilongnian.iteye.com/blog/2187775

第五章 常用Lua开发库3-模板渲染相关推荐

  1. 第五章 常用Lua开发库2-JSON库、编码转换、字符串处理

    JSON库 在进行数据传输时JSON格式目前应用广泛,因此从Lua对象与JSON字符串之间相互转换是一个非常常见的功能:目前Lua也有几个JSON库,本人用过cjson.dkjson.其中cjson的 ...

  2. 第五章 常用Lua开发库1-redis、mysql、http客户端

    对于开发来说需要有好的生态开发库来辅助我们快速开发,而Lua中也有大多数我们需要的第三方开发库如Redis.Memcached.Mysql.Http客户端.JSON.模板引擎等. 一些常见的Lua库可 ...

  3. [单刷APUE系列]第五章——标准I/O库

    目录 [单刷APUE系列]第一章--Unix基础知识[1] [单刷APUE系列]第一章--Unix基础知识[2] [单刷APUE系列]第二章--Unix标准及实现 [单刷APUE系列]第三章--文件I ...

  4. 【Python】推荐五个常用的图像处理库

    1. 引言 Python目前是世界上使用最多的编程语言之一.它能够以更少的工作量和更少的代码行数来完成许多事情.它还可以使用很少的代码行来方便地编辑和创建图像. 本文重点介绍,在图像处理领域,我们最常 ...

  5. 19年8月 字母哥 第四章 常用web开发数据库框架 不要用公司网络加载不出来 用热点!!!

    第四章 常用web开发数据库框架 4.1.整合Spring JDBC操作数据 4.2 Spring JDBC多数据源的实现 4.3.Spring JDBC JTA实现分布式事务 4.4.ORM主流框架 ...

  6. 概率论||期末考试复习手写笔记-第五六七章(知识点+例题)第五章 常用统计分布 第六章 参数估计 第七章 假设检验

    第五章  常用统计分布 考点一:常用统计量 考点二:三大统计分布 考点三:抽样分布(单正态总体+双正态总体) 第六章 参数估计 考点一: 估计量的评价标准(无偏性+有效性+相合性) 考点二:点估计的常 ...

  7. 《NodeJS开发指南》第五章微博实例开发总结

    所有文章搬运自我的个人主页:sheilasun.me <NodeJS开发指南>这本书用来NodeJS入门真是太好了,而且书的附录部分还讲到了闭包.this等JavaScript常用特性.第 ...

  8. APUE学习笔记:第五章 标准I/O库

    5.1 引言 标准I/O库处理很多细节,例如缓冲区分配,以优化长度执行I/O等.这些处理不必担心如何使用正确的块长度.这使得它便于用户使用,但是如果不较深入地了解I/O库函数的操作,也会带来一些问题 ...

  9. UNIX 环境高级编程总结——第五章 标准I/O 库

    5.1 流和 FILE 对象 对于标准 I/O 库,它们的操作则是围绕流(stream)进行的. 当打开一个流时,标准 I/O 函数 fopen 返回一个指向 FILE 对象的指针. 为了引用一个流, ...

最新文章

  1. 用json来组织数据,用IGame导出模型
  2. 在JavaScript中使用“原型”还是“ this”?
  3. MFC CString转换为字符数组
  4. Java迭代器ListIterator
  5. c++批量重命名_文件批量重命名?这个方法百试百灵
  6. 图像的亮度和对比度区别
  7. 最全面的 MySQL 索引详解
  8. 启动hiveserver2时报错Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient
  9. mysql order by
  10. android4.0蓝牙使能的详细解析 (转载)
  11. lightslider-支持移动触摸的轻量级jQuery幻灯片插件
  12. ORACLE DELETE数据慢的案例
  13. python2.7使用教程_使用模块 - 廖雪峰 Python 2.7 中文教程
  14. java的打印语句_java打印输出语句是什么?
  15. 冒泡排序(java)——3种方法
  16. Activision解散《吉他英雄》,取消《真实犯罪》
  17. supervisor安装使用
  18. 佛祖保佑注释代码(内含神兽与美女)
  19. 电子计算机4个发展阶段的划分,计算机以什么划分发展阶段
  20. AD软件出现“Your license is already used on computer “LAPTOP-F99R6OR1“ using product “AltiumDesigner“

热门文章

  1. 2020-12-23
  2. 图文了解 Kafka 的副本复制机制
  3. 01_初识Matplotlib、Figure的组成、绘图函数的输入类型、第一个例子(学习笔记)
  4. 【C语言】switch…case无break情况(2)
  5. android adb 联系人,使用adb命令向Android模拟器中导入通讯录联系人的方法
  6. pythonpip安装与使用_Python pip 安装使用与问题
  7. oracle 删除补全日志组_浅谈Oracle 20c ASM文件组模板技术
  8. 计算机旁边快速访问没有桌面图标了怎么办,桌面找不到我的电脑(计算机)图标的解决办法-win10桌面显示我的电脑...
  9. verilog 移位运算符 说明_FPGA、数字IC系列(2)——电子科大与北航部分Verilog题目与解析...
  10. 图像锐化算法(Image sharpening):拉普拉斯增强和Unsharp Masking(附代码)