作为一名开发人员,大家肯定对URL非常熟悉吧,但是有多少人对它去做过更深入的了解呢?在很多人眼里也许它就仅仅是一个URL
,一个获取数据的接口而已。然而在我看来,它不仅是URL
,还是一个通信链。为什么说是通信链呢,因为它可以按我自己制定的规则协议去传达我想要做的事情,尤其是在项目中解耦是非常的好用,这正是我今天所要分享的内容。相信很多人对URL
并没有一个完整的认识,我先大致介绍下URL
吧。
URL的定义:
在www上,每一信息资源都有统一的且在网上唯一的地址,该地址就叫URL(Uniform Resource Locator,统一资源定位符),它是www的统一资源定位标志,就是指网络地址。
URL的组成:
URL的一般语法格式为(带方括号[]的为可选项):
protocol://hostname[:port]/path/[;parameters][?query]#fragment
完整的、带有授权部分的普通统一资源标志符语法格式为:
协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值#标志
URL的格式说明:
1.protocol(协议):
指定使用的传输协议,下表列出 protocol 属性的有效方案名称。 最常用的是 HTTP协议,它也是目前www中应用最广的协议。
- http 通过 HTTP 访问该资源。 格式 http://
- https 通过安全的 HTTPS 访问该资源。 格式 https://
- file 资源是本地计算机上的文件。 格式 file:///(注意后边应是三个斜杠)
- ftp 通过 FTP 访问该资源。 格式 ftp://
- gopher 通过 Gopher 协议访问该资源。
- mailto 资源为电子邮件地址,通过 SMTP 访问。 格式 mailto:
- MMS 通过支持 MMS(流媒体)协议的播放该资源。(代表软件:Windows Media Player) 格式 MMS://
- ed2k 通过支持 ed2k(专用下载链接)协议的 P2P 软件访问该资源。(代表软件:电驴) 格式 ed2k://
- Flashget 通过支持 Flashget:(专用下载链接)协议的 P2P 软件访问该资源。(代表软件:快车) 格式 Flashget://
- thunder 通过支持 thunder(专用下载链接)协议的 P2P 软件访问该资源。(代表软件:迅雷) 格式 thunder://
- news 通过 NNTP 访问该资源。
2.hostname(主机名):
是指存放资源的服务器的域名系统(DNS) 主机名或 IP 地址。有时,在主机名前也可以包含连接到服务器所需的用户名和密码(格式:username:password@hostname)。
3.port(端口号):
整数,可选,省略时使用方案的默认端口,各种传输协议都有默认的端口号,如http的默认端口为80。如果输入时省略,则使用默认端口号。有时候出于安全或其他考虑,可以在服务器上对端口进行重定义,即采用非标准端口号,此时,URL中就不能省略端口号这一项。
4.path(路径):
由零或多个“/”符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。
5.parameters(参数):
这是用于指定特殊参数的可选项。
6.query(查询):
可选,用于给动态网页(如使用CGI、ISAPI、PHP/JSP/ASP/ASP.NET等技术制作的网页)传递参数,可有多个参数,用“&”符号隔开,每个参数的名和值用“=”符号隔开。
7.fragment(信息片断):
字符串,用于指定网络资源中的片断。例如一个网页中有多个名词解释,可使用fragment直接定位到某一名词解释。
而在 Objective-C
中,这些组成部分可以用系统提供的方法可以很方便的获取到,而不用麻烦的处理一堆字符串,下面给大家举个栗子🌰。
NSString *urlStr = @"https://www.testurl.com:8080/path/subpath;parms=test_parms?uid=123&gid=45#fragment=009&fragment";
NSURL *URL = [NSURL URLWithString:urlStr];
NSString *absoluteString = URL.absoluteString;
NSString *baseURL = URL.baseURL.absoluteString;
NSString *scheme = URL.scheme;
NSString *host = URL.host;
NSString *path = URL.path;
NSArray *pathComponents = URL.pathComponents;
NSString *lastPathComponent = URL.lastPathComponent;
NSString *pathExtension = URL.pathExtension;
NSString *query = URL.query;
NSString *fragment = URL.fragment;
NSString *parameterString = URL.parameterString;
NSString *relativePath = URL.relativePath;
NSString *port = [URL.port stringValue];
NSString *user = URL.user;
NSString *password = URL.password;
// absoluteString = https://www.testurl.com:8080/path/subpath;parms=test_parms?uid=123&gid=45#fragment=009&fragment
NSLog(@"absoluteString = %@", absoluteString);
// baseURL = (null)
NSLog(@"baseURL = %@", baseURL);
// scheme = https
NSLog(@"scheme = %@", scheme);
// host = www.testurl.com
NSLog(@"host = %@", host);
// port = 8080
NSLog(@"port = %@", port);
// path = /path/subpath
NSLog(@"path = %@", path);
// pathComponents = ("/", path, subpath)
NSLog(@"pathComponents = %@", pathComponents);
// lastPathComponent = subpath
NSLog(@"lastPathComponent = %@", lastPathComponent);
// pathExtension = @"" //<object returned empty description>
NSLog(@"pathExtension = %@", pathExtension);
// query = uid=123&gid=45
NSLog(@"query = %@", query);
// fragment = fragment=009&fragment
NSLog(@"fragment = %@", fragment);
// relativePath = /path/subpath (The same as path if baseURL is nil)
NSLog(@"relativePath = %@", relativePath);
// parameterString = parms=test_parms
NSLog(@"parameterString = %@", parameterString);
// user = (null)
NSLog(@"user = %@", user);
// password = (null)
NSLog(@"password = %@", password);
----------------------------- 分割线(下面才是重点) -----------------------------
URL的使用:
文章开头我说URL
还是一个通信链,因为我可以通过一个URL
可以得到我任何想要的信息,当然前提是我们得有一套规则协议去约束URL
。下面举几个小例子:
协议规则:https://www.test.com/path?action=xxx&id=xxx
前缀是:https://www.test.com/path?
action:告诉我想要做的事
id:具体详情id(如果不需要的话,可以不传)
🌰1:
URL = https://www.test.com/path?action=video&id=12345
说明:https://www.test.com/path
-> 前缀,action=video
-> 做跳转到视频详情处理,id=12345
-> 视频id是12345。
🌰2:
URL = https://www.test.com/path?action=user&id=666
说明:https://www.test.com/path
-> 前缀,action=user
-> 做跳转到用户主页处理,id=666
-> 用户id是666。
当然根据你自己的需求,这个URL随便你怎么定制,比如:URL = xhc://home.com/video/detail?id=12345
(跳转首页模块下的视频详情,视频id是12345),URL = xhc://store.com/goods/detail?id=88888
(跳转商城模块下的商品详情,商品id是88888)
通过以上的例子大家应该知道了URL
是如何传递信息的。有的同学也许会有疑问,这有什么用呢,我明明知道跳转到哪里,直接push
不就得了。但是如果是动态类型的跳转呢?如果是降低耦合度呢?该如何去做。
就拿第一种情况来说(动态类型的跳转),我们在点击一个首页banner
时需要根据服务端的配置数据,进行动态的跳转,配置不同,跳转页面不同。我们可以像上面这样去规划,做一个中间层去管理,也许跳转类型少看不出什么效果,但是跳转类型多的话,这种方法效果还是不错的,至少各种跳转逻辑很清晰,而且服务端也好控制。
第二种种情况(项目模块之间解耦),其实是涉及到组件化架构的,我们为了降低项目内部的耦合度,使每个模块之间解耦,为了解耦我们需要做的一件事情就是设计一个类似于路由的中间层,让Router
去处理各种逻辑,在此当然不止是跳转,比如点赞,获取一个NSObject
对象等等。而这个Router
的设计就需要用到上面的原理,其实说白了就是按约定好的规则去解析URL
,最后按各种参数返回给你,至于做什么,你自己处理,但前提是你得先注册这个URL
的规则匹配,这个Router
的设计有兴趣的同学可以看看蘑菇街的MGJRouter
。后面我有空会把组件化架构整理一下,供大家参考理解,共同学习交流。
也许有人会问,这不就是字符串嘛,干嘛还非得搞个URL
去处理。当然字符串也可以处理,但是我感觉用系统的NSURL
一些方法处理起来更方便一点,获取某些参数或值的时候更简洁一点,当然这也看个人喜好和业务需求,怎样用方便,喜欢用什么就用什么,毕竟条条大路通罗马。😂😂😂