源码阅读-JLRoutes路由设置
最后更新: 2018-1-20
JLRoutes 是在 github 上 Star 比较多的一个, 在各大平台也有介绍, 一些知识可以参考到下面的连接查看. 本文仅仅作为我的思考以及对应的心得;
一、 JLRoutes如何管理URLScheme以及对应的Handler
当调用 [JLRoutes globalRoutes]; 时候, 回去调用 + (instancetype)routesForScheme:(NSString *)scheme;, 想起代码如下;
static NSMutableDictionary *routeControllersMap = nil;
+ (instancetype)globalRoutes
{
return [self routesForScheme:JLRoutesGlobalRoutesScheme];
}
+ (instancetype)routesForScheme:(NSString *)scheme
{
JLRoutes *routesController = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
routeControllersMap = [[NSMutableDictionary alloc] init];
});
if (!routeControllersMap[scheme]) {
routesController = [[self alloc] init];
routesController.scheme = scheme;
routeControllersMap[scheme] = routesController;
}
routesController = routeControllersMap[scheme];
return routesController;
}
有上面可以看出, 实例化一个 JLRoutes之后,会生成一个 routeControllersMap 全局静态字典,key为URL scheme, Value 为JLRoutes 对象, JLRoutes 对应的 Scheme 唯一,但是对应的 Routes 可以有多个.
总结: JLRoutes 使用键值对形式保存;
二、JLRoutes 如何注册 URL Scheme
- 普通的url Scheme,
[[JLRoutes routesForScheme:@"JLRoutesOne"] addRoute:@"/:ViewController/:userID/:pass" handler:nil]
最终会生成一个 JLRRouteDefinition 对象, 里面包含了 scheme = JLRoutesOne、pattern= /:ViewController/:userID/:pass、priority 以及 patternComponents = [:ViewController, :userID, :pass] 还有 对应的回调 handlerBlock;
其实我们可以看出, JLRRouteDefinition 对象 已经保存了所有 URL相关的信息。
然后将 JLRRouteDefinition 让 JLRoutes 根据优先级对象管理起来; [self.routes addObject:route];
- 包含可选参数的URL;
[[JLRoutes globalRoutes] addRoute:"/path/:thing/(/a)(/b)(/c)" handler:nil]
+ (NSArray <NSString *> *)expandOptionalRoutePatternsForPattern:(NSString *)routePattern
{
/* this method exists to take a route pattern that is known to contain optional params, such as:
/path/:thing/(/a)(/b)(/c)
and create the following paths:
/path/:thing/a/b/c
/path/:thing/a/b
/path/:thing/a/c
/path/:thing/b/a
/path/:thing/a
/path/:thing/b
/path/:thing/c
*/
if ([routePattern rangeOfString:@"("].location == NSNotFound) {
return @[];
}
NSString *baseRoute = nil;
// 分析点1:
NSArray *components = [self _optionalComponentsForPattern:routePattern baseRoute:&baseRoute];
// 分析点2
NSArray *routes = [self _routesForOptionalComponents:components baseRoute:baseRoute];
return routes;
}
分析点1:
通过 NSSCanner来解析开数据, 拆解可选部分与必选部分, baseRoute 为必选部分,components 为可选部分;
baseRoute = /path/:thing/
components = ["/a", "/b", "/c"]
分析点2:
此处就是将 components 拼接成一个个的url;
<__NSFrozenArrayM 0x60400024b370>(
/path/:thing//a/b/c,
/path/:thing//b/c,
/path/:thing//a/c,
/path/:thing//c,
/path/:thing//a/b,
/path/:thing//b,
/path/:thing//a,
/path/:thing/
)
深入进去还是比较有意思的,我们进去看看:
运用递归的想法.
逐步解析一下:
/c [/a, /b]
/b [/a]
/a []
递归回去
[[/a], []]
[[/a], [], [/a, /b], [/b]]
[[/a], [], [/a, /b], [/b], [/a, /c], [/c], [/a, /b, /c], [/b, /c]]
解析出来之后,将数组中的每一项,生成一个 JLRRouteDefinition 对象, 然后由 JLRoutes.routes来管理;
- (NSArray<NSArray *> *)JLRoutes_allOrderedCombinations
{
NSInteger length = self.count;
if (length == 0) {
return [NSArray arrayWithObject:[NSArray array]];
}
id lastObject = [self lastObject];
NSArray *subarray = [self subarrayWithRange:NSMakeRange(0, length - 1)];
NSArray *subarrayCombinations = [subarray JLRoutes_allOrderedCombinations];
NSMutableArray *combinations = [NSMutableArray arrayWithArray:subarrayCombinations];
for (NSArray *subarrayCombos in subarrayCombinations) {
[combinations addObject:[subarrayCombos arrayByAddingObject:lastObject]];
}
return [NSArray arrayWithArray:combinations];
}
三、 JLRoutes 调用
系统调用 OpenUrl,因为注册的Scheme为当前app 使用,因此会调用到 AppDelegate的
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
return [JLRoutes routeURL:url];
}
查看源代码,可以追溯到 -_routeURL:withParameters:executeRouteBlock:.
会根据url生成对应的
JLRRouteRequest; 将url进行一些列的拆分;host&Path&query遍历
JLRoutes.routes里面的JLRRouteDefinition, 判断能否根据JLRRouteRequest来匹配,生成对应的JLRRouteResponse,
匹配规则比较简单,根据前面的 : *来设置;JLRoutes 还支持通配符;
四: 总结:
JLRoutes 相对来设比较简单的一个框架,但是实用性非常的高, 作者用一个全局的Map来保存对应的Scheme信息,解析 Url 成一个 request, 根据是否匹配生成对应的response, 然后进行设置。
设置很巧妙,
但是这个好像存在几个问题:
- 全局保存,如果成指数型的增长,可能占用较大内存;
- 对所有的handler 都需要提前注册进去
此框架使用了 NSSCanner 以及 NSURLCompenent
相关链接:
1. 官方的JLRoutes链接;
2. 我阅读的版本,已经fork过来
3. 可参考demo
源码阅读-JLRoutes路由设置的更多相关文章
- Yii2.0源码阅读-从路由到控制器
之前的文章弄清了一次请求的开始到结束.主要讲了Yii Applicaton实例的创建.初始化,UrlManager如何返回Yii中的路由信息,到runAction,最后将Response发送给客户端. ...
- laravel5.5源码阅读草稿——路由
laravel 里的路由是由RouteServiceProvider提供的,其中的boot方法为启动项,调用了父类的boot方法. RouteServiceProvider中的boot方法设置了自己与 ...
- Kibana源码分析--Hapijs路由设置理解笔记
[ES6解构赋值]:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_ ...
- Hadoop 副本放置策略的源码阅读和设置
本文通过MetaWeblog自动发布,原文及更新链接:https://extendswind.top/posts/technical/hadoop_block_placement_policy 大多数 ...
- CI框架源码阅读笔记4 引导文件CodeIgniter.php
到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...
- 40 网络相关函数(八)——live555源码阅读(四)网络
40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...
- 36 网络相关函数(四)——live555源码阅读(四)网络
36 网络相关函数(四)——live555源码阅读(四)网络 36 网络相关函数(四)——live555源码阅读(四)网络 简介 7)createSocket创建socket方法 8)closeSoc ...
- 33 网络相关函数(一)——live555源码阅读(四)网络
33 网络相关函数(一)——live555源码阅读(四)网络 33 网络相关函数(一)——live555源码阅读(四)网络 简介 1)IsMulticastAddress多播(组播)地址判断函数 多播 ...
- gogs 源码阅读笔记 001
gogs 源码阅读笔记 001 gogs项目相当不错,本笔记实际是基于gogs fork版本 git-122a66f. gitea (gitea版本由来)[https://blog.gitea.io/ ...
随机推荐
- numpy中线性代数用法
numpy中线性代数用法 矩阵乘法 >>> import numpy as np >>> x=np.array([[1,2,3],[4,5,6]]) >> ...
- 使用批处理选择运行控制台程序(简易cui)
批处理可以用于启动一些控制台程序.昨天在github上找到一个有意思的项目OpenRA : 一个开源的红警游戏. 发现该游戏的启动程序(launch-game)是用批处理写的 就学习了下 *没有玩过批 ...
- C# ref out parase 理解
这节课我们来学习方法中的参数传递,在面向对象二中,我曾说过,参数也属于变量的一种,在c语言的学习时,同学们都学习过参数这个概念和用法,方法使用参数列表来传递变量的基本语法如下:returnType ...
- doT学习(二)之用法集合
Advanced templating: illustrates defines and includes. Include external snippet defined in a variabl ...
- view视图总结
视图实质上存储的是一段sql. 创建方式: 1.create view 视图名 as 子查询语句 , 特点:与主表数据同步,对当前视图进行修改,会同时将根表一并修改. 2.create or ...
- Assets.xcassets的详细使用方法
开始之前,首先回顾一下iOS7初体验(1)——第一个应用程序HelloWorld中的一张图,如下所示: 本文分享一下Images.xcassets的体验~_~ 1. 打开此前使用过的HelloWorl ...
- Spring Boot整合Spring Security总结
一.创建Spring Boot项目 引入Thymeleaf和Web模块以及Spring Security模块方便进行测试,先在pom文件中将 spring-boot-starter-security ...
- centos--软件源--本地软件源---离线安装
一.软件源配置文件 1./etc/yum.conf 配置文件 [main] cachedir=/var/cache/yum #yum下载的RPM包的缓存目录 keepcache= #缓存是否保存,1保 ...
- mongoose 开源http库(2) --HTTP服务示例
要创建HTTP服务器,请按照以下格式: 通过调用mg_bind()或mg_bind_opt()创建侦听连接 调用mg_set_protocol_http_websocket()创建listening连 ...
- 008-zabbix监控nginx
(1)agent端配置 1)nginx编译安装需要加上该选项--with-http_stub_status_module 2)修改nginx配置文件 #vim /usr/local/nginx/con ...