作為一名開發(fā)人員幢哨,大家肯定對URL非常熟悉吧雄人,但是有多少人對它去做過更深入的了解呢僚纷?在很多人眼里也許它就僅僅是一個URL
矩距,一個獲取數(shù)據(jù)的接口而已。然而在我看來怖竭,它不僅是URL
锥债,還是一個通信鏈。為什么說是通信鏈呢痊臭,因為它可以按我自己制定的規(guī)則協(xié)議去傳達我想要做的事情哮肚,尤其是在項目中解耦是非常的好用,這正是我今天所要分享的內(nèi)容广匙。相信很多人對URL
并沒有一個完整的認(rèn)識允趟,我先大致介紹下URL
吧。
URL的定義:
在www上鸦致,每一信息資源都有統(tǒng)一的且在網(wǎng)上唯一的地址潮剪,該地址就叫URL(Uniform Resource Locator,統(tǒng)一資源定位符)分唾,它是www的統(tǒng)一資源定位標(biāo)志抗碰,就是指網(wǎng)絡(luò)地址。
URL的組成:
URL的一般語法格式為(帶方括號[]的為可選項):
protocol://hostname[:port]/path/[;parameters][?query]#fragment
完整的绽乔、帶有授權(quán)部分的普通統(tǒng)一資源標(biāo)志符語法格式為:
協(xié)議://用戶名:密碼@子域名.域名.頂級域名:端口號/目錄/文件名.文件后綴?參數(shù)=值#標(biāo)志
URL的格式說明:
1.protocol(協(xié)議):
指定使用的傳輸協(xié)議弧蝇,下表列出 protocol 屬性的有效方案名稱。 最常用的是 HTTP協(xié)議,它也是目前www中應(yīng)用最廣的協(xié)議看疗。
- http 通過 HTTP 訪問該資源沙峻。 格式 http://
- https 通過安全的 HTTPS 訪問該資源。 格式 https://
- file 資源是本地計算機上的文件鹃觉。 格式 file:///(注意后邊應(yīng)是三個斜杠)
- ftp 通過 FTP 訪問該資源专酗。 格式 ftp://
- gopher 通過 Gopher 協(xié)議訪問該資源。
- mailto 資源為電子郵件地址盗扇,通過 SMTP 訪問祷肯。 格式 mailto:
- MMS 通過支持 MMS(流媒體)協(xié)議的播放該資源。(代表軟件:Windows Media Player) 格式 MMS://
- ed2k 通過支持 ed2k(專用下載鏈接)協(xié)議的 P2P 軟件訪問該資源疗隶。(代表軟件:電驢) 格式 ed2k://
- Flashget 通過支持 Flashget:(專用下載鏈接)協(xié)議的 P2P 軟件訪問該資源佑笋。(代表軟件:快車) 格式 Flashget://
- thunder 通過支持 thunder(專用下載鏈接)協(xié)議的 P2P 軟件訪問該資源。(代表軟件:迅雷) 格式 thunder://
- news 通過 NNTP 訪問該資源斑鼻。
2.hostname(主機名):
是指存放資源的服務(wù)器的域名系統(tǒng)(DNS) 主機名或 IP 地址蒋纬。有時,在主機名前也可以包含連接到服務(wù)器所需的用戶名和密碼(格式:username:password@hostname)坚弱。
3.port(端口號):
整數(shù)蜀备,可選,省略時使用方案的默認(rèn)端口荒叶,各種傳輸協(xié)議都有默認(rèn)的端口號碾阁,如http的默認(rèn)端口為80。如果輸入時省略些楣,則使用默認(rèn)端口號脂凶。有時候出于安全或其他考慮,可以在服務(wù)器上對端口進行重定義愁茁,即采用非標(biāo)準(zhǔn)端口號蚕钦,此時,URL中就不能省略端口號這一項鹅很。
4.path(路徑):
由零或多個“/”符號隔開的字符串嘶居,一般用來表示主機上的一個目錄或文件地址。
5.parameters(參數(shù)):
這是用于指定特殊參數(shù)的可選項促煮。
6.query(查詢):
可選食听,用于給動態(tài)網(wǎng)頁(如使用CGI、ISAPI污茵、PHP/JSP/ASP/ASP.NET等技術(shù)制作的網(wǎng)頁)傳遞參數(shù)樱报,可有多個參數(shù),用“&”符號隔開泞当,每個參數(shù)的名和值用“=”符號隔開迹蛤。
7.fragment(信息片斷):
字符串,用于指定網(wǎng)絡(luò)資源中的片斷。例如一個網(wǎng)頁中有多個名詞解釋盗飒,可使用fragment直接定位到某一名詞解釋嚷量。
而在 Objective-C
中,這些組成部分可以用系統(tǒng)提供的方法可以很方便的獲取到逆趣,而不用麻煩的處理一堆字符串蝶溶,下面給大家舉個栗子??。
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
可以得到我任何想要的信息抖所,當(dāng)然前提是我們得有一套規(guī)則協(xié)議去約束URL
。下面舉幾個小例子:
協(xié)議規(guī)則: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
-> 做跳轉(zhuǎn)到視頻詳情處理鞍恢,id=12345
-> 視頻id是12345傻粘。
??2:
URL = https://www.test.com/path?action=user&id=666
說明:https://www.test.com/path
-> 前綴,action=user
-> 做跳轉(zhuǎn)到用戶主頁處理帮掉,id=666
-> 用戶id是666弦悉。
當(dāng)然根據(jù)你自己的需求,這個URL隨便你怎么定制蟆炊,比如:URL = xhc://home.com/video/detail?id=12345
(跳轉(zhuǎn)首頁模塊下的視頻詳情稽莉,視頻id是12345),URL = xhc://store.com/goods/detail?id=88888
(跳轉(zhuǎn)商城模塊下的商品詳情盅称,商品id是88888)
通過以上的例子大家應(yīng)該知道了URL
是如何傳遞信息的肩祥。有的同學(xué)也許會有疑問后室,這有什么用呢缩膝,我明明知道跳轉(zhuǎn)到哪里,直接push
不就得了岸霹。但是如果是動態(tài)類型的跳轉(zhuǎn)呢疾层?如果是降低耦合度呢?該如何去做贡避。
就拿第一種情況來說(動態(tài)類型的跳轉(zhuǎn))痛黎,我們在點擊一個首頁banner
時需要根據(jù)服務(wù)端的配置數(shù)據(jù),進行動態(tài)的跳轉(zhuǎn)刮吧,配置不同湖饱,跳轉(zhuǎn)頁面不同。我們可以像上面這樣去規(guī)劃杀捻,做一個中間層去管理井厌,也許跳轉(zhuǎn)類型少看不出什么效果,但是跳轉(zhuǎn)類型多的話,這種方法效果還是不錯的仅仆,至少各種跳轉(zhuǎn)邏輯很清晰器赞,而且服務(wù)端也好控制。
第二種種情況(項目模塊之間解耦)墓拜,其實是涉及到組件化架構(gòu)的港柜,我們?yōu)榱私档晚椖績?nèi)部的耦合度,使每個模塊之間解耦咳榜,為了解耦我們需要做的一件事情就是設(shè)計一個類似于路由的中間層夏醉,讓Router
去處理各種邏輯,在此當(dāng)然不止是跳轉(zhuǎn)贿衍,比如點贊授舟,獲取一個NSObject
對象等等。而這個Router
的設(shè)計就需要用到上面的原理贸辈,其實說白了就是按約定好的規(guī)則去解析URL
释树,最后按各種參數(shù)返回給你,至于做什么擎淤,你自己處理奢啥,但前提是你得先注冊這個URL
的規(guī)則匹配,這個Router
的設(shè)計有興趣的同學(xué)可以看看蘑菇街的MGJRouter
嘴拢。后面我有空會把組件化架構(gòu)整理一下桩盲,供大家參考理解,共同學(xué)習(xí)交流席吴。
也許有人會問赌结,這不就是字符串嘛,干嘛還非得搞個URL
去處理孝冒。當(dāng)然字符串也可以處理柬姚,但是我感覺用系統(tǒng)的NSURL
一些方法處理起來更方便一點,獲取某些參數(shù)或值的時候更簡潔一點庄涡,當(dāng)然這也看個人喜好和業(yè)務(wù)需求量承,怎樣用方便,喜歡用什么就用什么穴店,畢竟條條大路通羅馬撕捍。??????