###源起 QQ羣常常看到有同窗問(Vanilla/OpenResty開發:205773855,OpenResty技術交流2羣:481213820):html
綜上問題都是一個事兒:如何給Vanilla(OpenResty)添加一個路由協議?git
本文將以一個小例子入手,展現在Vanilla中如何自定義一個路由協議,基於此幫助你們理解Vanilla中路由器、路由協議的用法和實現,固然若是你對實現本身的路由協議不感冒的話,vanilla-0.1.0.rc4
已經實現了兩種比較實用的路由協議vanilla.v.routes.restful
和vanilla.v.routes.simple
能知足當前各類URI路由需求,可直接使用,用法見相關文檔地址:https://idevz.gitbooks.io/vanilla-zh/content/route.html。這裏給出一個vanilla.v.routes.restful
路由的配置實例:github
local restful = { v1={}, v={} } restful.v.GET = { {pattern = '/user/:user_id', controller = 'test.index', action = 'web_rule'}, {pattern = '/', controller = 'test.index', action = 'web_root'}, } restful.v1.GET = { {pattern = '/user/:user_id', controller = 'test.index', action = 'api_v1_rule'}, {pattern = '/', controller = 'test.index', action = 'api_root'}, {pattern = '/test/index/index', controller = 'test.index', action = 'index'}, } return restful
Vanilla項目地址:web
Github:https://github.com/idevz/vanillabootstrap
GitOSC:http://git.oschina.net/idevz/vanillaapi
若是vanilla.v.routes.restful
和vanilla.v.routes.simple
(默認爲simple
若是須要使用restful
路由協議,則須要在bootstrap
中打開Bootstrap:initRoute()
)不能知足你的需求,你想在本身的項目中DIY本身的路由協議,請繼續往下:restful
###如何給Vanilla(OpenResty)添加一個路由協議?app
先看例子,再學原理(例子:給APP添加一個跟功能與simple_route同樣的路由協議routes.idevz
)框架
####實現步驟ide
application/library/routes/idevz.lua
route_name
屬性,並實現__tostring
元方法(路由器基於此管理路由協議棧)idevz.lua
中實現match
方法(功能:根據當前請求URI返回對應的controller
和action
)####關鍵兩點
route_name
屬性,並實現__tostring
元方法match
方法相關代碼實現以下:
-- perf local error = error local ngxmatch=ngx.re.gmatch -- init iDevz and set routes local iDevz = {} function iDevz:new(request) local instance = { route_name = 'routes.idevz', request = request } setmetatable(instance, { __index = self, __tostring = function(self) return self.route_name end }) return instance end function iDevz:match() local uri = self.request.uri if uri == '/' then return 'index', 'index' end --在此實現URI路由邏輯,並返回contrllor_name, action_name return contrllor_name, action_name end return iDevz
####原理
Vanilla運行在OpenResty的content Phase
,由content_by_lua_file
驅動,當用戶請求過來時會初始化當前APP請求實例,並作相關配置解析、視圖引擎配置、插件裝載、路由設置等初始化工做,緊接着就是請求路由分發、處理... 也就是run
的指令一下就開始進入請求路由。
Vanilla實現了一個路由器vanilla.v.router
(注意這裏是router
,是er
路由器,區別於後面的路由協議route
)和由這個路由協器管理的一個路由協議棧(self.routes
),這個棧管理着一序列路由協議,默認使用vanilla.v.routes.simple
,Vanilla經過遍歷這個路由協議棧裏面各個route
的match
方法來完成請求的路由。這個match
方法只作一件事「根據當前請求的URI告訴每一個請求該去哪一個controller
和哪一個action
」。
下面是router
目前提供的相關方法:
function Router:new(request) --傳入request實例初始化路由器,默認已經啓用:vanilla.v.routes.simple function Router:addRoute(route, only_one) --添加路由協議 function Router:removeRoute(route_name) --傳入路由協議名稱刪除路由協議 function Router:getRoutes() --獲取當前的路由協議棧 function Router:getCurrentRoute() --獲取當前請求所使用的路由協議實例 function Router:getCurrentRouteName() --獲取當前請求所使用的路由協議名稱 function Router:route() --路由當前請求
** 因此給Vanilla(OpenResty)添加一個路由協議的關鍵就在於實現這個match
方法歡迎你們各自按需DIY **
####在bootstrap中使用實例
function Bootstrap:initRoute() local router = self.dispatcher:getRouter() local simple_route = require('vanilla.v.routes.simple'):new(self.dispatcher:getRequest()) local restful_route = require('vanilla.v.routes.restful'):new(self.dispatcher:getRequest()) local idevz_route = require('routes.idevz'):new(self.dispatcher:getRequest()) router:addRoute(restful_route, true) router:addRoute(idevz_route, true) router:addRoute(simple_route) router:removeRoute('vanilla.v.routes.restful') router:removeRoute('vanilla.v.routes.simple') -- print_r(router:getRoutes()) end
###感謝 Vanilla開源以來的很長一段時間裏一直只支持一種單一的簡單路由協議simple_route,這讓不少朋友意猶未盡,甚至批評Vanilla不是框架,而是骨架:),首先感謝各位羣友、Vanilla用戶...感謝你們對Vanilla的支持與關注,我想象中的Vanilla是一個保持很好的擴展性、易用性,讓OpenResty開發更簡單方便,性能強勁的同時又不失優雅小巧的OpenResty開發框架,雖然如今的vanilla-0.1.0.rc4
離這個目標還有一段距離,但至少方向是這樣的。Vanilla是已知的第一款國產OpenResty MVC Web框架,因此它離你更近:)。感謝持續關注,咱們在努力完善中。