源码阅读-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/ ...
随机推荐
- java遇到的笔试题
一.基础题(CSS经常遇到的面试题) 1.在Jquery中,想让一个元素隐藏,用什么实现,显示隐藏的元素用什么实现? 答:show()方法可以使一个元素显示:hide()隐藏可见的元素:[slideD ...
- Spring(二)--Spring入门案例
Spring入门案例 1.需要的实体类 2.需要的接口和实现类 3.需要的service和实现类 /** * service层的作用 * 在不改变dao层代码的前提下,增加业务逻辑操作 */ publ ...
- 洛谷 P2801 教主的魔法 题解
题面 刚看到这道题的时候用了个树状数组优化前缀和差分的常数优化竟然AC了?(这数据也太水了吧~) 本人做的第一道分块题,调试了好久好久,最后竟然没想到二分上还会出错!(一定要注意)仅此纪念: #inc ...
- 【统计】Causal Inference
[统计]Causal Inference 原文传送门 http://www.stat.cmu.edu/~larry/=sml/Causation.pdf 过程 一.Prediction 和 causa ...
- JavaSE--基础知识
Java基础知识 一.基础知识 1.java命名规则 由26个英文字母大小写,0-9 ,_或 $ 组成 数字不可以开头. 不可以使用关键字和保留字,但能包含关键字和保留字. Java中严格区分大小写, ...
- MVC和MVVM设计模式简单理解
1.mvc设计模式理解 Model: 模型 持有所有的数据状态和业务逻辑; 泛指数据库,链接数据库,建立数据模型 View: 视图 用来展示数据模型在页面上,泛指前端 Controller: 控制器, ...
- 完整的JavaScript包括三部分、script标签、JavaScript的基本语法以及变量和字面量的关系
完整的JavaScript包括三大部分: -ECMAScript JavaScript的开发规范:提供核心语言功能 -DOM document object model 文档对象模型:提供 ...
- 1.javascript知识点总结
1.写javaScript的三种方式: 2.写javaScript的注意事项: ①严格区分字母的大小写: ②空格和换行.多余的空格会被忽略,可以将一行代码分成多行写: ③分号作为一个语句的结束: ④单 ...
- JS预解释
1.声明(declare) var num // 告诉浏览器在全局作用域中有一个num变量 定义(defined) num = 12 // 给我们的比变量进行赋值 2.var:在预解释时只是提前 ...
- Linux下部署springboot项目的步骤及过程
最近在研究将springboot项目部署到Linux服务器上,由于springboot是内嵌了tomcat,所以可以直接将项目打包上传至服务器上.我是在idea上的项目,所以我就基于此说下过程. (一 ...