###源起 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框架,因此它离你更近:)。感谢持续关注,咱们在努力完善中。