最后更新: 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

  1. 普通的url Scheme,
[[JLRoutes routesForScheme:@"JLRoutesOne"] addRoute:@"/:ViewController/:userID/:pass" handler:nil]

最终会生成一个 JLRRouteDefinition 对象, 里面包含了 scheme = JLRoutesOnepattern= /:ViewController/:userID/:passpriority 以及 patternComponents = [:ViewController, :userID, :pass] 还有 对应的回调 handlerBlock;

其实我们可以看出, JLRRouteDefinition 对象 已经保存了所有 URL相关的信息。

然后将 JLRRouteDefinitionJLRoutes 根据优先级对象管理起来; [self.routes addObject:route];

  1. 包含可选参数的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:.

  1. 会根据url生成对应的 JLRRouteRequest; 将url进行一些列的拆分; host & Path & query

  2. 遍历 JLRoutes.routes里面的 JLRRouteDefinition, 判断能否根据 JLRRouteRequest来匹配,生成对应的 JLRRouteResponse,

    匹配规则比较简单,根据前面的 : *来设置;

  3. JLRoutes 还支持通配符;


四: 总结:

JLRoutes 相对来设比较简单的一个框架,但是实用性非常的高, 作者用一个全局的Map来保存对应的Scheme信息,解析 Url 成一个 request, 根据是否匹配生成对应的response, 然后进行设置。

设置很巧妙,

但是这个好像存在几个问题:

  1. 全局保存,如果成指数型的增长,可能占用较大内存;
  2. 对所有的handler 都需要提前注册进去

此框架使用了 NSSCanner 以及 NSURLCompenent

相关链接:

1. 官方的JLRoutes链接;

2. 我阅读的版本,已经fork过来

3. 可参考demo

源码阅读-JLRoutes路由设置的更多相关文章

  1. Yii2.0源码阅读-从路由到控制器

    之前的文章弄清了一次请求的开始到结束.主要讲了Yii Applicaton实例的创建.初始化,UrlManager如何返回Yii中的路由信息,到runAction,最后将Response发送给客户端. ...

  2. laravel5.5源码阅读草稿——路由

    laravel 里的路由是由RouteServiceProvider提供的,其中的boot方法为启动项,调用了父类的boot方法. RouteServiceProvider中的boot方法设置了自己与 ...

  3. Kibana源码分析--Hapijs路由设置理解笔记

    [ES6解构赋值]:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_ ...

  4. Hadoop 副本放置策略的源码阅读和设置

    本文通过MetaWeblog自动发布,原文及更新链接:https://extendswind.top/posts/technical/hadoop_block_placement_policy 大多数 ...

  5. CI框架源码阅读笔记4 引导文件CodeIgniter.php

    到了这里,终于进入CI框架的核心了.既然是“引导”文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.c ...

  6. 40 网络相关函数(八)——live555源码阅读(四)网络

    40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...

  7. 36 网络相关函数(四)——live555源码阅读(四)网络

    36 网络相关函数(四)——live555源码阅读(四)网络 36 网络相关函数(四)——live555源码阅读(四)网络 简介 7)createSocket创建socket方法 8)closeSoc ...

  8. 33 网络相关函数(一)——live555源码阅读(四)网络

    33 网络相关函数(一)——live555源码阅读(四)网络 33 网络相关函数(一)——live555源码阅读(四)网络 简介 1)IsMulticastAddress多播(组播)地址判断函数 多播 ...

  9. gogs 源码阅读笔记 001

    gogs 源码阅读笔记 001 gogs项目相当不错,本笔记实际是基于gogs fork版本 git-122a66f. gitea (gitea版本由来)[https://blog.gitea.io/ ...

随机推荐

  1. 【中间件】Kafka 学习 01

    KafKa 博客教程-1 博客教程-2 kafka简介 kafka起源 Kafka是由LinkedIn开发并开源的分布式消息系统,2012年捐赠给Apache基金会,采用Scala语言,运行在JVM中 ...

  2. P4962 朋也与光玉题解

    题目链接 光坂小镇是一个由 n 个点(编号为 1 ~ n),m 条有向边构成的图,每个节点上都有一个光玉,光玉共有 k 种,编号为 0 ~ k−1. 为了使一切改变,朋也需要找齐全部的 k种光玉.他可 ...

  3. 使用Tomcat、JNDI与ActiveMQ实现JMS消息通信服务

    前言 之所以使用JNDI 是出于通用性考虑,该例子使用JMS规范提供的通用接口,没有使用具体JMS提供者的接口,这样可以保证我们编写的程序适用于任何一种JMS实现(ActiveMQ.HornetQ等) ...

  4. ConstantUtils

    public class ConstantUtils { public static final Integer PAGE_SIZE=2; public static final Integer NA ...

  5. C语言:标准IO_fopen( )、fclose() ①

    思前想后一个月,我终于敲下了我的第一篇开山之作. 博客千千万,我的博客首先记录的是学习时候的理解,用于给自己翻阅查找,现在主要研究的是C语言和STM32.如果能帮到你,那是最好的,假如我写的东西有错误 ...

  6. tomcat同个端口配置多个项目后无后缀的页面跳转

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  7. 总结下Nginx的功能模块

    nginx-1.10.3]# ./configure  \ --prefix=/usr/local/nginx   \        #指定安装路径 --user=nginx --group=ngin ...

  8. IDeajCommunity 配置smart tomcat插件

    ntelliJ IDEA社区版没有自带tomcat. 装插件--smart tomcat. IntelliJ IDEA>>Preferences>>Plugins>> ...

  9. mysql orderby 问题

    开发写的sql select * from aaa where course_id=xx order by  a,b 当a,b条件都一致时,默认应该以id排序,当数据条数大于1x条(17)时,结果变为 ...

  10. 解读sam格式文件

    1,SAM文件格式介绍 SAM(The Sequence Alignment / Map format)格式,即序列比对文件的格式,详细介绍文档:http://samtools.github.io/h ...