目錄:
App項(xiàng)目實(shí)戰(zhàn)之路(一):概述篇
App項(xiàng)目實(shí)戰(zhàn)之路(二):API篇
App項(xiàng)目實(shí)戰(zhàn)之路(三):原型篇
App項(xiàng)目實(shí)戰(zhàn)之路(四):UI篇
App項(xiàng)目實(shí)戰(zhàn)之路(五):服務(wù)端篇
App項(xiàng)目實(shí)戰(zhàn)之路(六):數(shù)據(jù)庫(kù)篇
這個(gè)系列文章主要是講服務(wù)端的設(shè)計(jì)和實(shí)現(xiàn), 對(duì)這部分的知識(shí)有個(gè)概念性的理解即可.
http://keeganlee.me/post/practice/20160807
App項(xiàng)目實(shí)戰(zhàn)之路(一):概述篇
這章講的是app的功能需求.
類似微博的程序員社交app.
http://keeganlee.me/post/practice/20160812
App項(xiàng)目實(shí)戰(zhàn)之路(二):API篇
假如現(xiàn)在要定義登錄、退出登錄、注冊(cè)、查詢用戶資料的接口,那么,可以這樣定義:
接口 方法 Endpoint
登錄 POST /user/login
退出登錄 POST /user/logout
注冊(cè) POST /user/register
查詢用戶資料 GET /user/queryInfo
這種最傳統(tǒng)普遍定義的API就是所謂的RPC方式.
最直接的區(qū)別就是:RPC抽象的是過程,REST抽象的是資源。過程是以動(dòng)詞為核心,而資源是以名詞為核心。也可以簡(jiǎn)單類比為:RPC是面向過程的,REST是面向?qū)ο蟮摹?br>
給我的感覺就是:好混亂!這種大部分都是在對(duì)REST有過很初淺的了解,但卻缺少正確理解的情況下做出的設(shè)計(jì)。或者是對(duì)于部分接口不知道該如何抽象為資源,所以就直接用RPC方式去定義了。
其實(shí),使用REST風(fēng)格設(shè)計(jì)API,我覺得難點(diǎn)就在于如何抽象資源。使用RPC則相對(duì)容易很多。這時(shí),也許有人就會(huì)提出疑問了。既然使用RPC比用REST更容易抽象出接口,那為何還要用REST呢?要解答這個(gè)疑問,可以從面向過程和面向?qū)ο蟮慕嵌热ニ伎?。我們知道,面向過程的思考方式處理問題更直接簡(jiǎn)單,那為什么我們還要使用面向?qū)ο竽兀恐劣谶@個(gè)問題的答案,我就不再展開了。
其實(shí)這點(diǎn)我也不理解, 現(xiàn)在暫時(shí)勉強(qiáng)淺顯的理解吧.
一個(gè)定義良好的URI,應(yīng)該具有可讀性,即從URI本身即可知道它所代表的資源。
接著,就需要對(duì)每個(gè)資源定義操作的方法了。我傾向于使用以下四個(gè)方法
POST 創(chuàng)建新資源
GET 查詢資源
PUT 修改資源
DELETE 刪除資源
不過,并不是所有資源都會(huì)開放這四個(gè)方法。例如,對(duì)/post是不開放PUT和DELETE方法的。對(duì)于以上資源,具體需要定義哪些方法,這里就不再列出來了。
最終以RestFul定義出來的API是這樣的:
Endpoint 資源
/users 用戶
/users/{user_id} 某用戶
/users/{user_id}/posts 某用戶發(fā)布的內(nèi)容
/users/{user_id}/following 某用戶關(guān)注的人
/users/{user_id}/followers 某用戶的粉絲
/posts 發(fā)布的內(nèi)容
/posts/{post_id} 某條內(nèi)容
/posts/{post_id}/comments 某條內(nèi)容的評(píng)論
/me 當(dāng)前用戶
/me/posts 我發(fā)布的內(nèi)容
/me/stars 我星標(biāo)的內(nèi)容
/me/following 我關(guān)注的人
/me/followers 我的粉絲
/me/messages 我的消息
說白了, 以RestFul方式定義出來的API,名字上以資源為核心, 通過POST, GET, PUT, DELETE這幾種操作對(duì)資源進(jìn)行增刪改查, 傳統(tǒng)上, 以RPC方式定義出來的API, 名字上以動(dòng)作為核心, 一般情況下, 使用的http方法也只是POST和GET.
API版本控制使用這種方式:
http://api.domain.com/v2.1/posts
最后,再定義下響應(yīng)的數(shù)據(jù)協(xié)議。初期打算使用JSON,后期可能會(huì)考慮使用Protocol Buffers。數(shù)據(jù)結(jié)構(gòu)則如下:
{
code:200,
message: "success",
data: { key1: value1, key2: value2, ... }
}
響應(yīng)統(tǒng)一使用code、message、data的JSON數(shù)據(jù)格式
protocol buffer是和json等價(jià)的一種數(shù)據(jù)結(jié)構(gòu), 這點(diǎn)基礎(chǔ)概念要了解.
文件格式以*.proto結(jié)尾, 到現(xiàn)在, 項(xiàng)目中還沒有用到過.
API安全設(shè)計(jì)
安全設(shè)計(jì)方面,首先,我打算全面使用HTTPS。使用HTTPS,雖然犧牲了性能,但可以解決大部分安全問題。另外,蘋果在之前的WWDC上就已宣布,從2017年1月1日起,所有iOS應(yīng)用將強(qiáng)制使用HTTPS。這其實(shí)也意味著,從2017年起,所有App都將會(huì)使用HTTPS,不只是iOS。
全面https化是個(gè)趨勢(shì).
其次,用戶鑒權(quán)方面則打算采用Token方式。用戶登錄之后分配一個(gè)accessToken和一個(gè)refreshToken,accessToken用于發(fā)起用戶請(qǐng)求,refreshToken用于更新accessToken。accessToken會(huì)設(shè)置有效期,可以設(shè)為24小時(shí)。而用戶退出登錄之后,accessToken和refreshToken都將作廢。重新登錄之后會(huì)分配新的accessToken和refreshToken。
accessToken和一個(gè)refreshToken的概念要了解
然后,我還打算在App層級(jí)分配AppKey和AppSecret
每次向服務(wù)端發(fā)送請(qǐng)求時(shí),AppKey都必須帶上,服務(wù)端會(huì)對(duì)相應(yīng)的AppKey進(jìn)行校驗(yàn)。而AppSecret則需要安全保存在客戶端,也不能在網(wǎng)絡(luò)上進(jìn)行傳輸,防止泄露。AppSecret只用于加密一些安全性級(jí)別較高的數(shù)據(jù),以及為URL生成簽名。
URL簽名算法步驟如下:
- 將所有參數(shù)按參數(shù)名進(jìn)行升序排序;
- 將排序后的參數(shù)名和值拼接成字符串stringParams,格式:key1value1key2value2...;
- 在上一步的字符串前面拼接上請(qǐng)求URI的Endpoint,字符串后面拼接上AppSecret,即:stringURI + stringParams + AppSecret;
- 使用AppSecret為密鑰,對(duì)上一步的結(jié)果字符串使用HMAC算法計(jì)算MAC值,這個(gè)MAC值就是簽名。
上面講的是使用AppSecret生成簽名的過程, 不必深究, 現(xiàn)在了解概念即可.
URL簽名在每次發(fā)送請(qǐng)求時(shí)都需要附加在參數(shù)中,服務(wù)端接收到請(qǐng)求后會(huì)使用同樣的簽名算法計(jì)算簽名值,只有服務(wù)端計(jì)算出來的簽名值和接收到的簽名值一致時(shí)才認(rèn)為請(qǐng)求是安全的。
自此,API部分的設(shè)計(jì)就完成了。在此總結(jié)一下:
- 采用REST風(fēng)格定義API,接口抽象成對(duì)資源的操作;
- 添加API版本控制,版本號(hào)嵌在URL中;
- 響應(yīng)統(tǒng)一使用code、message、data的JSON數(shù)據(jù)格式;
- 全站采用HTTPS;
- 使用Token方式對(duì)用戶鑒權(quán);
- 使用AppKey方式對(duì)應(yīng)用鑒權(quán);(也就是分辨是Android端還是IOS端發(fā)過來的請(qǐng)求)
- 使用URL簽名對(duì)請(qǐng)求鑒權(quán);
- 參數(shù)中添加nonce值增強(qiáng)簽名的不可預(yù)測(cè)性。
http://keeganlee.me/post/practice/20160816
App項(xiàng)目實(shí)戰(zhàn)之路(三):原型篇
作者使用的是墨刀工具來設(shè)計(jì)原型.
也有人提出使用 Sketch 做原型設(shè)計(jì)。無可否認(rèn),Sketch 也是可以設(shè)計(jì)原型的,PS、AI 等工具也同樣可以。至于交互,用標(biāo)注的方式就好了。但這些工具,確切地說,更適合用來做 UI 設(shè)計(jì),而不是原型設(shè)計(jì)。做原型設(shè)計(jì),要求的就是能夠快速看到效果,不只是界面效果,還有交互效果。用UI設(shè)計(jì)工具來做,一是很難達(dá)到快速的要求,二是交互效果等于沒有。
http://keeganlee.me/post/practice/20160903
App項(xiàng)目實(shí)戰(zhàn)之路(四):UI篇
設(shè)計(jì)工具自然是用強(qiáng)大的Sketch
http://keeganlee.me/post/practice/20161006
App項(xiàng)目實(shí)戰(zhàn)之路(五):服務(wù)端篇
對(duì)服務(wù)端的開發(fā), 大致了解下背景就可以了.
之前,我是沒打算將服務(wù)端也列入開源名單的。但現(xiàn)在的想法已經(jīng)改變了,我打算將整個(gè)項(xiàng)目都開源,不只是Android端和iOS端,也包括服務(wù)端,為一些有志于成為全棧工程師(甚至是全棧架構(gòu)師)的程序猿提供一個(gè)不斷進(jìn)化的完整的學(xué)習(xí)項(xiàng)目。
數(shù)據(jù)庫(kù)方面,我選擇了廣泛使用的MySQL。原因有二:一是據(jù)聞Facebook、Twitter等社交平臺(tái)核心數(shù)據(jù)庫(kù)也是MySQL;二是MySQL 5.7版本加入了對(duì)JSON格式的原生支持,這點(diǎn)特性使得MySQL也具備了NoSQL的功能。但本項(xiàng)目初期考慮先只用關(guān)系型的數(shù)據(jù)結(jié)構(gòu)。
最后,應(yīng)用服務(wù)器自然就是選擇Tomcat了.
http://keeganlee.me/post/practice/20161016
App項(xiàng)目實(shí)戰(zhàn)之路(六):數(shù)據(jù)庫(kù)篇
瀏覽器項(xiàng)目的數(shù)據(jù)庫(kù)的表結(jié)構(gòu)起碼要總結(jié)的出來.
這章講的是服務(wù)端數(shù)據(jù)庫(kù)的設(shè)計(jì),大致了解下技術(shù)背景就可以了.
---------DONE.----------