lua開發--模板渲染

動態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進行測試。

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

轉載:
http://jinnianshilongnian.iteye.com/blog/2187775

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章