基于json的數(shù)據(jù)傳輸設(shè)計(jì) - 整理細(xì)枝末節(jié)
- 脫離貧困 - 滿足基本需求
- 走向小康 - 豐滿格式設(shè)計(jì)
- 提升精神 - 添加容錯(cuò)機(jī)制
- 加強(qiáng)品質(zhì) - 加固安全機(jī)制
- 開放眼界 - 整體框架設(shè)計(jì)
- 追求真理 - 實(shí)踐博客系統(tǒng)
- 茶余飯后 - 整理細(xì)枝末節(jié)
-
restful思考
現(xiàn)在對于前后端數(shù)據(jù)傳輸最火熱的思想莫過于對restful的的討論了,對于什么是restful,這里不做詳細(xì)的表述,只是做一些簡單的解釋.
所謂的restful,其實(shí)我們得從url說起,url即統(tǒng)一資源定位符,在web世界里,所有的東西都是資源,一張網(wǎng)頁,一張圖片,一個(gè)css,一個(gè)js,都是資源,而我們總是可以通過一個(gè)鏈接訪問到該資源,那便是url.
而restful便是以url為資源定位,http協(xié)議動(dòng)作為操作方式的一種設(shè)計(jì).比如現(xiàn)在有article這種資源,那么我們?nèi)绾卧L問這個(gè)資源呢?假定訪問這個(gè)資源的url為{server_url}/article,那我們就有一下幾種訪問方式- get : {server_url}/article:{article_id} :獲取一片文章
- get : {server_url}/article : 獲取所有文章
- post : {server_url}/article:{article_id} 添加一片文章
- delete : {server_url}/article:{article_id} 刪除一片文章
- fetch : {server_url}/article:{article_id} 更新一片文章
在上一篇文章中,其實(shí)也利用了這種思想,但是也不全是,因?yàn)槲覓仐壛薶ttp的多種動(dòng)作,而全部采用post方式,在但是在命名上,還是采用很restful的方式來命名 - {serve_url}/article/get
- {serve_url}/article/create
- {serve_url}/article/update
- {serve_url}/article/delete
總的來說,restful只是一種思想,而非銀彈或者準(zhǔn)則,只是提出了一種更優(yōu)雅的設(shè)計(jì)方式,見仁見智.
-
資源復(fù)用
在之前的設(shè)計(jì)中,我們說了一種面向?qū)ο蟮臄?shù)據(jù)結(jié)構(gòu)設(shè)計(jì),其實(shí)這是為了符合面向?qū)ο蟮脑O(shè)計(jì)思想,為了實(shí)體的可復(fù)用性.什么叫做實(shí)體可復(fù)用性呢?
假定現(xiàn)在有兩個(gè)接口:- ARTICLE_GET : 獲取所有的文章(包含文章分類)
- ARTICLE_GROUP_GET : 獲取文章的分組
- ARTICLE_GET_BY_GROUP : 根據(jù)分類獲取文章
在頁面和需求上的提現(xiàn)便是: - 有一個(gè)分類導(dǎo)航,用戶點(diǎn)擊分類導(dǎo)航中的分類,可以獲取到該分類下的所有文章
- 有一個(gè)文章列表,用戶可以看見文章的標(biāo)題,文章的分類,文章的發(fā)布時(shí)間
- 用戶點(diǎn)擊文章中的文章分類,則可以跳轉(zhuǎn)到該分類下的所有文章
在ARTICLE_GROUP_GET接口上,我們其實(shí)是沒有分歧的:
{ "id":1, "name":"技術(shù)分類" }分歧在于其他兩個(gè)接口,這兩個(gè)接口的返回?cái)?shù)據(jù)其實(shí)是一樣的,他們的區(qū)別在于查詢方式的不同,所以其實(shí)可以合并成一個(gè)接口,
- 滿足需求1
{ "id":1, "title":"文章標(biāo)題", "create_time":"發(fā)布事件" }這里只是簡單滿足了需求1
- 滿足需求2和3
{ "id":1, "title":"文章標(biāo)題", "create_time":"發(fā)布事件", "group_id":1, "group_name":"分組名稱" }這里看是滿足了需求2和3但是卻有些問題,對于文章分組的信息,我們在字段之前添加了
group_前綴,看似優(yōu)雅的區(qū)分了文章資源和分組資源,但是如果照此設(shè)計(jì),一旦單個(gè)資源擴(kuò)大起來,將變得不可讀,同時(shí)也拋棄了group自身這個(gè)資源,所以我們必須修改一下設(shè)計(jì){ "id":1, "title":"文章標(biāo)題", "create_time":"發(fā)布事件", "group":{ "id":1, "name":"文章分組" } }這樣一來便可以達(dá)到可讀性和可維護(hù)性的提升,同時(shí)復(fù)用了
group這個(gè)資源,達(dá)到資源嵌套和復(fù)用.
但是,在達(dá)到資源復(fù)用的同時(shí),要避免資源的過分復(fù)用,比如一片文章中有3張圖片,那么這么設(shè)計(jì)是不對的:[ { "id":1, "url":"http://img_url" }, { "id":2, "url":"http://img_url" } { "id":3, "url":"http://img_url" } ]這里的解決方案應(yīng)當(dāng)是直接合并為一條
{ "imgs":"http://img1_url;http://img2_url;img3_url;" } id作為資源標(biāo)識
在所有的資源中,使用一個(gè)統(tǒng)一的鍵名來作為資源的標(biāo)識,我慣用的便是id-
列表和詳情的獲取分離
在api設(shè)計(jì)中,常常有一種需求,比如一個(gè)博客,有列表頁面和詳情頁面之分,這里有三種解決方案- 獲取列表的時(shí)候?qū)⑺袛?shù)據(jù)返回,從列表頁跳轉(zhuǎn)到詳情頁面的時(shí)候直接將之前的數(shù)據(jù)同步推送過去
- 如果單個(gè)資源數(shù)據(jù)過大,比如博客文章可能包含該一個(gè)富文本,將會(huì)導(dǎo)致獲取事件過長
- 跳轉(zhuǎn)延遲
- 獲取列表的時(shí)候獲取全部數(shù)據(jù),跳轉(zhuǎn)的時(shí)候推送
id過去,詳情頁通過id獲取該資源- 如果單個(gè)資源數(shù)據(jù)過大,比如博客文章可能包含該一個(gè)富文本,將會(huì)導(dǎo)致獲取事件過長
- 同時(shí)重復(fù)獲取資源導(dǎo)致資源浪費(fèi)
- 獲取列表的時(shí)候獲取必須數(shù)據(jù),跳轉(zhuǎn)的時(shí)候推送
id過去,詳情頁通過id獲取全部數(shù)據(jù)- 資源不統(tǒng)一
綜合考慮,第三種方案其實(shí)是最優(yōu)的,但是還是要把他的不足解決,解決方案便是,在列表接口吧不需要的數(shù)據(jù)或者不需要的大數(shù)據(jù)直接置空但是保留鍵值對.比如文章列表頁面吧文章正文字段置空,而在詳情頁面吧正文字段恢復(fù),這樣既保持了資源的統(tǒng)一,也保證了傳輸?shù)乃俣?/li>
- 資源不統(tǒng)一
- 獲取列表的時(shí)候?qū)⑺袛?shù)據(jù)返回,從列表頁跳轉(zhuǎn)到詳情頁面的時(shí)候直接將之前的數(shù)據(jù)同步推送過去
-
列表分頁
常見需求- 前端假分頁 : 前端獲取50條,單次顯示10條
- 顯示到40條的時(shí)候再次獲取數(shù)據(jù),每次刷新都很快的感覺
- 前端真分頁 : 前段獲取50條,顯示50條
- 每次都要獲取,暴露了獲取時(shí)間,需要等待
- 后端假分頁 : 查詢?nèi)繑?shù)據(jù),返回10條
- 浪費(fèi)資源
- 后端真分頁 : 查詢50條,返回50條
- 合理利用資源
最好的方案是 : 前端假分頁結(jié)合后端真分頁
- 合理利用資源
- 前端假分頁 : 前端獲取50條,單次顯示10條
資源存儲
不應(yīng)該吧圖片或者其他大型資源直接存儲到數(shù)據(jù)中,比如富文本中的圖片,如果直接以blob存儲到數(shù)據(jù)庫中,在獲取的時(shí)候是單線程堵塞的,應(yīng)當(dāng)將圖片等文件存儲到硬盤中,在富文本中保留鏈接,獲取的時(shí)候減輕數(shù)據(jù)傳輸?shù)耐瑫r(shí)將會(huì)以一步線程的方式訪問圖片音樂等資源
*7. id加密策略
將id用前后端協(xié)同好的算法加密,比如
- 生成32位隨機(jī)字母字符串(不包含數(shù)字)
- 將id順序插入替換
比較費(fèi)后端資源
- 更加合理利用
http協(xié)議- 將
token驗(yàn)證放入header中的x-auth-token - 將
code用http code代替
- 將
有空再細(xì)細(xì)修改完善