`
jinnianshilongnian
  • 浏览: 21513658 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2420447
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3010220
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5640568
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:260217
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597925
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250368
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5860558
Group-logo
跟我学Nginx+Lua开...
浏览量:702867
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785734
社区版块
存档分类
最新评论

第五章 常用Lua开发库3-模板渲染

阅读更多

动态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

cd /usr/example/lualib/resty/
wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template.lua
mkdir /usr/example/lualib/resty/html
cd /usr/example/lualib/resty/html 
wget https://raw.githubusercontent.com/bungle/lua-resty-template/master/lib/resty/template/html.lua

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

local template = require("resty.template")

  

模板位置

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

 

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

#first match ngx location
set $template_location "/templates";
#then match root read file
set $template_root "/usr/example/templates";

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

root /usr/example/templates;

 

其顺序是

local function load_ngx(path)
    local file, location = path, ngx_var.template_location
    if file:sub(1)  == "/" then file = file:sub(2) end
    if location and location ~= "" then
        if location:sub(-1) == "/" then location = location:sub(1, -2) end
        local res = ngx_capture(location .. '/' .. file)
        if res.status == 200 then return res.body end
    end
    local root = ngx_var.template_root or ngx_var.document_root
    if root:sub(-1) == "/" then root = root:sub(1, -2) end
    return read_file(root .. "/" .. file) or path
end

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

 

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

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

 

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

 

接下来定义模板位置

mkdir /usr/example/templates
mkdir /usr/example/templates2

 

example.conf配置server部分

    #first match ngx location
    set $template_location "/templates";
    #then match root read file
    set $template_root "/usr/example/templates";

    location /templates {
         internal;
         alias /usr/example/templates2;
    }

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

 

然后创建两个模板文件

vim /usr/example/templates2/t1.html

内容为 

template2

 

vim /usr/example/templates/t1.html

内容为 

template1

 

test_temlate_1.lua 

local template = require("resty.template")
template.render("t1.html")

 

example.conf配置文件

    location /lua_template_1 {
        default_type 'text/html';
        lua_code_cache on;
        content_by_lua_file /usr/example/lua/test_template_1.lua;
    }

访问如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

local template = require("resty.template")
--是否缓存解析后的模板,默认true
template.caching(true)
--渲染模板需要的上下文(数据)
local context = {title = "title"}
--渲染模板
template.render("t1.html", context)


ngx.say("<br/>")
--编译得到一个lua函数
local func = template.compile("t1.html")
--执行函数,得到渲染之后的内容
local content = func(context)
--通过ngx API输出
ngx.say(content)

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

 

2、examle.conf配置文件

    location /lua_template_2 {
        default_type 'text/html';
        lua_code_cache on;
        content_by_lua_file /usr/example/lua/test_template_2.lua;
    }

  

使用示例

1、test_template_3.lua

local template = require("resty.template")

local context = {
    title = "测试",
    name = "张三",
    description = "<script>alert(1);</script>",
    age = 20,
    hobby = {"电影", "音乐", "阅读"},
    score = {语文 = 90, 数学 = 80, 英语 = 70},
    score2 = {
        {name = "语文", score = 90},
        {name = "数学", score = 80},
        {name = "英语", score = 70},
    }
}

template.render("t3.html", context)

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

 

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

{(header.html)}
   <body>
      {# 不转义变量输出 #}
      姓名:{* string.upper(name) *}<br/>
      {# 转义变量输出 #}
      简介:{{description}}<br/>
      {# 可以做一些运算 #}
      年龄: {* age + 1 *}<br/>
      {# 循环输出 #}
      爱好:
      {% for i, v in ipairs(hobby) do %}
         {% if i > 1 then %},{% end %}
         {* v *}
      {% end %}<br/>

      成绩:
      {% local i = 1; %}
      {% for k, v in pairs(score) do %}
         {% if i > 1 then %},{% end %}
         {* k *} = {* v *}
         {% i = i + 1 %}
      {% end %}<br/>
      成绩2:
      {% for i = 1, #score2 do local t = score2[i] %}
         {% if i > 1 then %},{% end %}
          {* t.name *} = {* t.score *}
      {% end %}<br/>
      {# 中间内容不解析 #}
      {-raw-}{(file)}{-raw-}
{(footer.html)}

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

 

{* var *}:变量输出;

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

{% code %}:代码片段;

{# comment #}:注释;

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

 

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

 

3、example.conf配置文件

    location /lua_template_3 {
        default_type 'text/html';
        lua_code_cache on;
        content_by_lua_file /usr/example/lua/test_template_3.lua;
    }

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

 

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

 

5
0
分享到:
评论
5 楼 vsyour 2017-05-06  
test_temlate_1.lua 需要改成 test_template_1.lua 不然会报404的.
4 楼 apl330 2016-10-18  
根据你的博客,我也写了一篇
https://my.oschina.net/zjzhai/blog/759719
3 楼 123456789012 2016-05-18  
你好,麻烦了,我这边开发中碰到了困难无法解决,希望获得您的帮助。

场景:我这边使用nginx+lua渲染页面响应客户端,页面模板中存在include调用碎片页。当我关闭nginx的ssi时,响应正常,但是include的碎片页都会无效;当我开启ssi的时候,nginx就会报错,存在子请求,导致响应失败!

28816#0: *224 header already sent while sending response to client, client: 192.168.211.91, server: 10.10.*, request: "GET /99889195.dhtml HTTP/1.1", subrequest: "/inc/script/css/base.shtml",


我的邮箱: 66013804@qq.com,谢谢了,希望您百忙之中可以指点迷津!
2 楼 tianice 2016-03-18  
newboy2004 写道
模板没有解析 访问/lua_template_3返回t3.html????

模板位置写错了吧,windows上路径用这个 d:\\path1\\path2
1 楼 newboy2004 2015-12-20  
模板没有解析 访问/lua_template_3返回t3.html????

相关推荐

    跟我学Nginx+Lua开发.pdf

    - **第五章**: 常用Lua开发库3-模板渲染。介绍常用的Lua开发库以及如何使用它们进行模板渲染。 - **第六章**: Web开发实战1——HTTP服务。通过实际项目来加深对HTTP服务的理解。 - **第七章**: Web开发实战2——商品...

    ngx_lua_module-windows-1.1.2.0

    - **数据处理**:通过LuaJIT(Just-In-Time编译器)实现高效的数据处理,如JSON解析、模板渲染等。 - **缓存操作**:利用Lua实现内存缓存,提高响应速度。 - **动态内容生成**:根据用户请求动态生成内容,无需...

    跟我学Nginx+Lua开发

    1. **动态页面渲染**:使用Lua模板引擎(如Lunan)来生成动态HTML内容。 2. **API网关**:利用Lua脚本作为中间层来处理API请求,实现负载均衡、鉴权认证等功能。 3. **性能监控**:利用Lua脚本收集和分析Nginx的日志...

    [psp编程]LUA基本3D教程

    3. **PSP编程环境**:熟悉PSP的开发环境,包括必要的开发工具和软件。 #### 三、关键概念 ##### 1. 绘制缓存(Draw Buffer) - **定义**:绘制缓存是用于存储颜色、深度和模板信息的数据结构。 - **作用**:这些...

    《Cocos2d-x实战 JS卷 Cocos2d-js开发》随书源码下

    随书源码包含了从第13章到第24章的示例代码,由于文件大小超出上传限制,源码被分为两个压缩包。在这些章节中,读者可以深入学习Cocos2d-js的各种关键概念和技术。 Cocos2d-js是Cocos2d-x框架的一个分支,它允许...

    Love2D-Template:LÖVE的游戏开发模板

    - **第三方库**:LÖVE社区提供了许多扩展库,如Tiled(地图编辑器支持)、HUMP(游戏库)、LövePotion(增强功能库)等,可以提升开发效率和游戏质量。 - **性能优化**:理解LÖVE的渲染原理,避免不必要的计算,...

    thinklua:一个lua Web MVC框架一个基于openresty的web框架

    3. **模板引擎**:内置或支持第三方模板引擎,如LPeg-based模板引擎,使得视图渲染更加便捷。 4. **请求和响应对象**:提供了封装的请求和响应对象,简化了对HTTP头、查询参数、请求体等数据的处理。 5. **异常...

    NodeMCU-小程序远程控制模板.rar

    NodeMCU-小程序远程控制模板是一个基于NodeMCU和ESP8266微控制器的物联网(IoT)项目,用于实现微信小程序对硬件设备的远程操控。NodeMCU是一款基于ESP8266芯片的开源硬件开发板,具有强大的Wi-Fi功能和丰富的GPIO接口...

    一个基于C++为主语言,lua为脚本语言的打飞机小游戏.zip

    在这个“基于C++为主语言,lua为脚本语言的打飞机小游戏”项目中,我们可以深入探讨两种编程语言在游戏开发中的应用以及它们的交互方式。C++是一种强大的、高效的编程语言,常用于构建大型系统和游戏引擎,因为它...

    知易Cocos2D-iPhone_游戏开发源代码

    3. **脚本支持**:Cocos2D-iPhone支持Lua和JavaScript,允许开发者用这些易于学习的脚本语言编写游戏逻辑,降低开发难度。 4. **音频管理**:内置了简单的音频播放功能,支持背景音乐和音效的播放,为游戏增加生动...

    cocos2dx3.0中文帮助文档

    Cocos2d-x是一款开源的游戏开发框架,广泛应用于2D游戏、实时渲染应用程序和其他互动内容的制作。3.0版本是其发展历程中的一个重要里程碑,带来了许多优化和新特性。本中文帮助文档旨在为开发者提供详尽的指导,帮助...

    DOOM3 源代码

    《DOOM3源代码》是游戏开发领域的一份宝贵资源,它揭示了ID Tech 4引擎的内部工作原理。这个引擎是由著名游戏开发者约翰·卡马克(John Carmack)所设计,他是第一人称射击游戏领域的先驱者,对3D图形技术有着深远的...

    Game Engine Architecture_GameDevelopment_GameEngine_C++_

    音频引擎需要处理声音的播放、混音、3D空间化、音量控制等,常用库有OpenAL或FMOD。 6. **脚本系统**:游戏逻辑可以通过脚本语言编写,使非程序员也能进行游戏逻辑设计。常见的脚本系统有Lua、Python或Unity的...

    在游戏中使用CEGUI 第一章(底层).rar

    5. **脚本支持**:CEGUI支持使用脚本语言(如Python或Lua)进行动态界面配置和扩展,这极大地提高了灵活性。 6. **国际化与本地化**:CEGUI内置了对多语言支持的机制,使得游戏界面可以轻松地进行国际化和本地化。 ...

    Visual C++游戏基础

    由于文件大小限制,该资源被分割成了多个部分上传,例如“ch9_3”和“ch9_1”,这可能代表第九章的第三部分和第一部分。 C++游戏编程是计算机科学领域的一个重要分支,它利用C++的强大功能和面向对象特性来创建复杂...

    cocos2d的学习资料

    8. **扩展性**:cocos2d-x拥有丰富的第三方库和插件,如粒子系统、UI组件、广告集成等,进一步提升了开发效率和游戏质量。 学习cocos2d-x时,你需要理解基本的面向对象编程概念,掌握至少一种支持的语言,如C++或...

    一个三维打斗游戏源代码

    4. **物理引擎**:如碰撞检测、刚体动力学,可能使用了如Bullet或Box2D等第三方库。 5. **动画系统**:角色动作的创建和播放,包括骨骼动画和蒙皮技术。 6. **输入处理**:如何捕获和响应用户的键盘、鼠标或游戏手柄...

    小游戏源码-玛雅传奇.rar

    7. **库文件和框架**:游戏可能依赖于一些第三方库或框架,这些文件会提供额外的功能支持,如图形渲染、物理模拟等。 8. **文档**:可能包括设计文档、开发者笔记、API参考等,帮助理解和修改代码。 通过分析和研究...

Global site tag (gtag.js) - Google Analytics