文章出處

通過前面幾章,我們已經掌握了一些基本的開發知識,但是代碼結構比較簡單,缺乏統一的標準,模塊化,也缺乏統一的異常處理,這一章我們主要來學習如何封裝一個輕量級的MVC框架,規范以及簡化開發,并且提供類似php所見即所得的能力

統一入口

通常來說一個mvc框架會有一個統一的入口點,類似于spring mvc的DispatcherServlet,會攔截所有的請求,也就是/,于是我們可以得出我們的入口點

conf/nginx.conf

worker_processes  1;

error_log logs/error.log notice;

events {
    worker_connections 1024;
}

http {
    lua_package_path "/Users/john/opensource/openresty-web-dev/demo8/lua/?.lua;/Users/john/opensource/openresty-web-dev/demo8/lualib/?.lua;/usr/local/openresty/lualib/?.lua";
    server {
        listen 80;
        server_name localhost;
        lua_code_cache off;

        location / {
            content_by_lua_file lua/mvc.lua;
        }

        location ~ ^/js/|^/css/|\.html {
            root html;
        }
    }
}

除了靜態文件js/css/html文件,其他的請求都會被我們的mvc.lua處理。

默認頁面

當請求uri為空時,默認返回index.html頁面,當然也可以自己定義,實現這個效果很簡單

local uri = ngx.var.uri
-- 默認首頁
if uri == "" or uri == "/" then
    local res = ngx.location.capture("/index.html", {})
    ngx.say(res.body)
    return
end

url解析

這里簡單的把url解析成模塊名模塊方法,根據/分割,如果只有模塊名,沒有方法名,則默認為index方法

local m, err = ngx.re.match(uri, "([a-zA-Z0-9-]+)/*([a-zA-Z0-9-]+)*")

local moduleName = m[1]     -- 模塊名
local method = m[2]         -- 方法名

if not method then
    method = "index"        -- 默認訪問index方法
else
    method = ngx.re.gsub(method, "-", "_")    
end

動態Controller模塊

得到模塊名之后,需要動態引入模塊,通過pcall,然后再調用模塊的方法

-- 控制器默認在web包下面
local prefix = "web."       
local path = prefix .. moduleName

-- 嘗試引入模塊,不存在則報錯
local ret, ctrl, err = pcall(require, path)

local is_debug = true       -- 調試階段,會輸出錯誤信息到頁面上

if ret == false then
    if is_debug then
        ngx.status = 404
        ngx.say("<p style='font-size: 50px'>Error: <span style='color:red'>" .. ctrl .. "</span> module not found !</p>")
    end
    ngx.exit(404)
end

-- 嘗試獲取模塊方法,不存在則報錯
local req_method = ctrl[method]

if req_method == nil then
    if is_debug then
        ngx.status = 404
        ngx.say("<p style='font-size: 50px'>Error: <span style='color:red'>" .. method .. "()</span> method not found in <span style='color:red'>" .. moduleName .. "</span> lua module !</p>")
    end
    ngx.exit(404)
end

-- 執行模塊方法,報錯則顯示錯誤信息,所見即所得,可以追蹤lua報錯行數
ret, err = pcall(req_method)

if ret == false then
    if is_debug then
        ngx.status = 404
        ngx.say("<p style='font-size: 50px'>Error: <span style='color:red'>" .. err .. "</span></p>")
    else
        ngx.exit(500)
    end
end

異常處理

可以看到,從引入模塊,到獲取模塊方法,已經執行方法,都有可能報錯,這里通過pcall來進行調用,這種方式可以安全的調用lua代碼,不會導致異常中斷,然后通過定義一個變量,來區分是否為開發調試階段,如果是則把錯誤信息輸出到瀏覽器端,否則直接報404或者500,避免把錯誤信息輸出到客戶端,導致代碼泄漏。

至此,一個簡單的mvc框架已經可以使用了,但是現在還只能做前端渲染,下一章,我講介紹如果進行服務端渲染。

示例代碼 參見demo8部分


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()