APIJSON-以堅(jiān)持和偏執(zhí),回敬傲慢和偏見(jiàn)

<p><strong>APIJSON簡(jiǎn)介:</strong></p>

<p>APIJSON是一種JSON傳輸結(jié)構(gòu)協(xié)議。</p>

<p>客戶端可以定義任何JSON結(jié)構(gòu)去向服務(wù)端發(fā)起請(qǐng)求,服務(wù)端就會(huì)返回對(duì)應(yīng)結(jié)構(gòu)的JSON字符串,所求即所得。</p>

<p>一次請(qǐng)求任意結(jié)構(gòu)任意數(shù)據(jù),方便靈活,不需要專門接口或多次請(qǐng)求。</p>

<p>支持增刪改查、模糊搜索、遠(yuǎn)程函數(shù)調(diào)用等。還能去除重復(fù)數(shù)據(jù),節(jié)省流量提高速度!</p>

<p>從此HTTP傳輸JSON數(shù)據(jù)沒(méi)有接口,更不需要文檔!</p>

<p>客戶端再也不用和服務(wù)端溝通接口或文檔問(wèn)題了!再也不會(huì)被文檔各種錯(cuò)誤坑了!</p>

<p>服務(wù)端再也不用為了兼容舊版客戶端寫新版接口和文檔了!再也不會(huì)被客戶端隨時(shí)隨地沒(méi)完沒(méi)了地?zé)┝耍?lt;/p>

<p><strong>項(xiàng)目主頁(yè)詳細(xì)介紹:</strong></p>

<p><a >https://github.com/TommyLemon/APIJSON</a></p>

<p><strong>下載試用</strong></p>

<p><a >APIJSONClientApp.apk</a></p>

<p>


</p>

<p>

</p>

<p>

</p>

<p>

</p>

<p>
</p>

<p>前些天我發(fā)了幾篇博客來(lái)推廣APIJSON,幾乎每次發(fā)布后都引起了很大的爭(zhēng)議,有贊賞和認(rèn)可,也有質(zhì)疑和否定。</p>

<p>評(píng)論太亂太分散,就挑出部分偏見(jiàn),在這里對(duì)關(guān)于APIJSON的<strong>開發(fā)、<strong><strong>功能、<strong>使用、性能、</strong><strong>安全</strong></strong></strong></strong>做一個(gè)統(tǒng)一的解答吧。</p>

<p> </p>

<p><strong>首先聲明:</strong></p>

<p>開發(fā)APIJSON是為了解決小公司、團(tuán)隊(duì)及個(gè)人開發(fā)者中客戶端和服務(wù)端的接口、文檔和溝通問(wèn)題,簡(jiǎn)化開發(fā)、提高效率、縮短周期。</p>

<p>希望大家不要用大公司的業(yè)務(wù)去要求APIJSON的功能、性能、安全等,而且個(gè)人也能力有限,所以只要方便、夠用就好。</p>

<p>一般來(lái)說(shuō)小公司只能開發(fā)小型系統(tǒng),只有大公司才能開發(fā)大型系統(tǒng)。APIJSON解決的問(wèn)題在小公司很容易出現(xiàn)并且容易造成致命的影響(開發(fā)周期長(zhǎng)、產(chǎn)品上線遲導(dǎo)致資金鏈斷裂而倒閉),但大公司因?yàn)橘Y源(人才、資金、管理)充??梢院芎玫乇苊膺@些問(wèn)題。APIJSON降低了開發(fā)門檻和成本,使得小公司也能快速實(shí)現(xiàn)產(chǎn)品、節(jié)約資源,提高自己的競(jìng)爭(zhēng)力。</p>

<p>另外,一般大公司基本都是自己造輪子用的,說(shuō)不定有些公司也開發(fā)了類似APIJSON的數(shù)據(jù)交換協(xié)議,只是沒(méi)有開源。</p>

<p> </p>

<p> </p>

<p><strong>一、關(guān)于開發(fā)</strong></p>

<p>翻了下聊天記錄,大概是從2016年11月5日的問(wèn)題開始構(gòu)思的:</p>

<p>如果一個(gè)界面(如微信詳細(xì)資料界面)需要獲取1個(gè)User(個(gè)人資料)和它對(duì)應(yīng)的1個(gè)pictureList(個(gè)人相冊(cè)),目前有這幾種方法:<br />
1.接口返回的User里包括pictureList;<br />
2.分別請(qǐng)求User和pictureList兩個(gè)接口;<br />
3.后臺(tái)新增一個(gè)接口,返回?cái)?shù)據(jù)包括User和pictureList。<br />
這幾種哪種最好呢?</p>

<p>我陸續(xù)問(wèn)了公司群、技術(shù)群、圈子內(nèi)的朋友們,獲得了很多阿里、網(wǎng)易、恒生、微店、蘑菇街、挖財(cái)?shù)瓤蛻舳?、前端、后端開發(fā)者的回答,但得到的方案都是上面的,我都不滿意。</p>

<p>或許是真的沒(méi)有人知道新的方案,也可能是公司的方案不能外傳。之前也網(wǎng)上搜索了一些接口定制、組合、嵌套等相關(guān)的關(guān)鍵詞,都沒(méi)找到滿意的答案。</p>

<p> </p>

<p>求人不如求己,還是自己造一個(gè)輪子吧。</p>

<p>然后我花了大概一周的時(shí)間構(gòu)思和評(píng)估新方案的</p>

<p><strong>需求(實(shí)現(xiàn)微信詳細(xì)資料的用戶+最近相冊(cè)、QQ空間的用戶+動(dòng)態(tài)+評(píng)論等數(shù)據(jù)的各種組合嵌套)、</strong></p>

<p><strong>方式(</strong><strong><strong>客戶端可定制、組合、嵌套服務(wù)端的返回?cái)?shù)據(jù))</strong>、</strong></p>

<p><strong>實(shí)現(xiàn)(數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)、傳輸與交互、封裝與解析算法等)。</strong></p>

<p>之后就開始動(dòng)工了,先花了一周實(shí)現(xiàn)了最重要的</p>

<p><strong>封裝與解析協(xié)議可行性驗(yàn)證(確定了3個(gè)方案中基于JSON的方案二)、</strong></p>

<p><strong>數(shù)據(jù)庫(kù)MySQL JDBC查詢{User:{id:1}}、</strong></p>

<p><strong>簡(jiǎn)單對(duì)象組合{User:{},pictureList:[]}與列表+對(duì)象組合{[]:{User:{},Moment:{},Comment[]:{}}}的封裝與解析,</strong></p>

<p>然后實(shí)現(xiàn)了</p>

<p><strong>客戶端與服務(wù)端的HTTP通信、</strong></p>

<p><strong>客戶端對(duì)Reqeust的封裝和對(duì)Response的解析、</strong></p>

<p><strong><strong><strong>服務(wù)端</strong>對(duì)<strong>Reqeust</strong>的解析和</strong>對(duì)<strong>Response<strong>的封裝。</strong></strong></strong></p>

APIJSON初步完成,放到Bitbucket遠(yuǎn)程倉(cāng)庫(kù)用SourceTree管理和備份,后來(lái)遷移到碼云。</p>

<p>之后又經(jīng)過(guò)了1.0-3.1的內(nèi)部版本迭代,2016年11月21日放到GitHub上開源。</p>

<p>開發(fā)過(guò)程中遇到了很多問(wèn)題:</p>

<p>1.一開始打算用請(qǐng)求格式最簡(jiǎn)潔的方案三,因?yàn)橐呀?jīng)脫離JSON的合法格式不能封裝和解析,嘗試定制FastJSON失敗,于是轉(zhuǎn)為符合JSON格式的方案二。</p>

<p>2.對(duì)列表+對(duì)象組合Request的解析出現(xiàn)的各種問(wèn)題,經(jīng)過(guò)好幾天的反復(fù)嘗試、調(diào)試和修改終于完成。</p>

<p>3.URL中含有轉(zhuǎn)義的字符'/'被UTF-8編碼后發(fā)送到服務(wù)端仍然無(wú)法解析,后來(lái)通過(guò)多層encode解決。</p>

<p>...</p>

<p> </p>

<p><strong>偏見(jiàn):</strong></p>

<p>以我的經(jīng)驗(yàn)來(lái)看,此方式不通。也許只是作者一個(gè)人的狂熱。閉門造車出來(lái)的產(chǎn)物吧...</p>

<p><strong>回敬:</strong></p>

<p>APIJSON不是閉門造車的產(chǎn)物,而恰恰是為了解決自己和開發(fā)圈子里的各種接口問(wèn)題而總結(jié)出來(lái)的實(shí)踐經(jīng)驗(yàn)。</p>

<p>APIJSON解決了傳統(tǒng)方式導(dǎo)致的開發(fā)周期長(zhǎng)(客戶端要等服務(wù)端開發(fā)完接口、寫好文檔才能請(qǐng)求和解析接口)、客戶端容易被文檔的各種錯(cuò)誤坑從而導(dǎo)致耗費(fèi)大量的調(diào)試和與后端溝通的時(shí)間等問(wèn)題。</p>

<p> </p>

<p> </p>

<p><strong><strong>二、</strong>關(guān)于功能</strong></p>

<p>APIJSON目前已實(shí)現(xiàn):</p>

<p>大體功能:增刪改查、分頁(yè)查詢、統(tǒng)計(jì)與驗(yàn)證、注冊(cè)登錄、模糊搜索、結(jié)構(gòu)校驗(yàn)、數(shù)據(jù)保護(hù)、遠(yuǎn)程函數(shù)調(diào)用等</p>

<p>操作方式:增、刪、改、查、調(diào)用遠(yuǎn)程函數(shù)</p>

<p>操作對(duì)象:?jiǎn)蝹€(gè)對(duì)象、可關(guān)聯(lián)的多個(gè)對(duì)象、數(shù)組等</p>

<p>請(qǐng)求方法:GET,HEAD,POST_GET,POST_HEAD,POST,PUT,DELETE</p>

<p>請(qǐng)求結(jié)構(gòu):{Table:{...}}、{Table0:{...},Table1{...},Table2:{...}...}、{"[]":{Table:{...}}}、{"[]":{Table0:{...},Table1{...},"Array0[]":{...},...}}等各種組合和嵌套</p>

<p>返回結(jié)構(gòu):對(duì)應(yīng)請(qǐng)求結(jié)構(gòu)的各種JSON結(jié)構(gòu)。</p>

<p>功能符號(hào):</p>

<pre>
"key[]":{} // 查詢數(shù)組

"key{}":[] // 匹配選項(xiàng)范圍

"key{}":"條件0,條件1..." // 匹配條件范圍

"key()":"function(Type0:value0,Type1:value1...)" // 遠(yuǎn)程調(diào)用函數(shù)

"key@":"key0/key1.../targetKey" // 依賴引用

"key$":"SQL搜索表達(dá)式" // 模糊搜索

"key+":key指定類型的Object // 增加/擴(kuò)展

"key-":key指定類型的Object // 減少/去除

"@key":key指定類型的Object // @key為JSONObject中的關(guān)鍵詞。如指定字段@columns、自定義關(guān)鍵詞@position
</code></pre>

<p>具體見(jiàn)文檔:</p>

<p><a >https://github.com/TommyLemon/APIJSON</a></p>

<p> </p>

<p><strong>偏見(jiàn)1:</strong></p>

<p>表連接查詢</p>

<p><strong>回敬:</strong></p>

<p>table都是通過(guò)id關(guān)聯(lián)的,連接查詢?cè)谖恼碌?<strong>查詢類微信朋友圈動(dòng)態(tài)列表數(shù)據(jù)</strong> 里就給了demo,用戶User、動(dòng)態(tài)Moment、評(píng)論Comment就是通過(guò)id關(guān)聯(lián)查詢的。</p>

<p> </p>

<p><strong>偏見(jiàn)2:</strong></p>

<p>那要是3個(gè)表4個(gè)表內(nèi)連接呢?</p>

<p><strong>回敬:</strong></p>

<p>APIJSON給出的Demo里的Moment,User,Comment這3個(gè)表就是通過(guò)id內(nèi)連接的。文中給出的查詢類似微信朋友圈動(dòng)態(tài)列表數(shù)據(jù)的demo:</p>

<pre>
{
"[]": { //請(qǐng)求一個(gè)array
"page": 0, //array條件
"count": 2,
"User": { //請(qǐng)求查詢名為User的table,返回名為User的JSONObject
"sex": 0 //object條件
},
"Moment": {
"userId@": “/User/id” //缺省依賴路徑,從同級(jí)object的路徑開始
},
"Comment[]": { //請(qǐng)求一個(gè)名為Comment的array
"page": 0,
"count": 2,
"Comment": {
"momentId@": “[]/Moment/id” //完整依賴路徑
}
}
}
}</code></pre>

<p>這就表示Moment.userId = User.id, Comment.momentId = Moment.id,不就實(shí)現(xiàn)了3個(gè)表內(nèi)連接查詢么?而且還是多個(gè)數(shù)組和單個(gè)Object復(fù)雜嵌套的應(yīng)用場(chǎng)景。</p>

<p> </p>

<p><strong>偏見(jiàn)3:</strong></p>

<p>處理不了復(fù)雜的請(qǐng)求,只能看著玩玩。</p>

<p><strong>回敬:</strong></p>

<p>APIJSON就是為復(fù)雜請(qǐng)求和數(shù)據(jù)結(jié)構(gòu)變化而生的。</p>

<p>不管是簡(jiǎn)單對(duì)象組合{User:{},pictureList:[]},還是列表+對(duì)象組合{[]:{User:{},Moment:{},Comment[]:{}}}都可以。</p>

<p>微信朋友圈動(dòng)態(tài)列表夠復(fù)雜吧?APIJSON查詢:(可<a >下載App測(cè)試</a>)</p>

<p>請(qǐng)求:</p>

<pre>
{
"[]": { //請(qǐng)求一個(gè)array
"page": 0, //array條件
"count": 2,
"User": { //請(qǐng)求查詢名為User的table,返回名為User的JSONObject
"sex": 0 //object條件
},
"Moment": {
"userId@": “/User/id” //缺省依賴路徑,從同級(jí)object的路徑開始
},
"Comment[]": { //請(qǐng)求一個(gè)名為Comment的array
"page": 0,
"count": 2,
"Comment": {
"momentId@": “[]/Moment/id” //完整依賴路徑
}
}
}
}</code></pre>

<p><a >點(diǎn)擊這里測(cè)試</a></p>

<p>返回:</p>

<pre>
{
"[]":[
{
"User":{
"id":38710,
"sex":0,
"phone":"1300038710",
"name":"Name-38710",
"head":"http://static.oschina.net/uploads/user/1218/2437072_100.jpg?t=1461076033000"
},
"Moment":{
"id":470,
"title":"Title-470",
"content":"This is a Content...-470",
"userId":38710,
"pictureList":["http://static.oschina.net/uploads/user/585/1170143_50.jpg?t=1390226446000"]
},
"Comment[]":[
{
"Comment":{
"id":4,
"parentId":0,
"momentId":470,
"userId":310,
"targetUserId":14604,
"content":"This is a Content...-4",
"targetUserName":"targetUserName-14604",
"userName":"userName-93781"
}
},
{
"Comment":{
"id":22,
"parentId":221,
"momentId":470,
"userId":332,
"targetUserId":5904,
"content":"This is a Content...-22",
"targetUserName":"targetUserName-5904",
"userName":"userName-11679"
}
}
]
},
{
"User":{
"id":70793,
"sex":0,
"phone":"1300070793",
"name":"Name-70793",
"head":"http://static.oschina.net/uploads/user/1174/2348263_50.png?t=1439773471000"
},
"Moment":{
"id":170,
"title":"Title-73",
"content":"This is a Content...-73",
"userId":70793,
"pictureList":["http://my.oschina.net/img/portrait.gif?t=1451961935000"]
},
"Comment[]":[
{
"Comment":{
"id":44,
"parentId":0,
"momentId":170,
"userId":7073,
"targetUserId":6378,
"content":"This is a Content...-44",
"targetUserName":"targetUserName-6378",
"userName":"userName-88645"
}
},
{
"Comment":{
"id":54,
"parentId":0,
"momentId":170,
"userId":3,
"targetUserId":62122,
"content":"This is a Content...-54",
"targetUserName":"targetUserName-62122",
"userName":"userName-82381"
}
}
]
}
]
}</code></pre>

<p> </p>

<p> </p>

<p><strong><strong>三、</strong>關(guān)于使用</strong></p>

<p>見(jiàn)項(xiàng)目的文檔和服務(wù)端及客戶端的Demo工程:</p>

<p><a >https://github.com/TommyLemon/APIJSON</a></p>

<p> </p>

<p><strong><strong>偏見(jiàn)</strong>1:</strong></p>

<p>有違項(xiàng)目開發(fā)前后端分離的趨勢(shì)。</p>

<p><strong>回敬:</strong></p>

<p>傳統(tǒng)方式連客戶端的UI都是和后端接口關(guān)聯(lián)的,比如類似微信朋友圈、QQ空間的動(dòng)態(tài)的列表都需要特定接口來(lái)傳輸對(duì)應(yīng)結(jié)構(gòu)的數(shù)據(jù),耦合性很高。</p>

<p>而APIJSON讓服務(wù)端和客戶端UI完全分離了,不需要服務(wù)端為客戶端UI定制接口,也不用為了兼容舊版客戶端保留冗余字段以及開發(fā)新版接口(v2,v3...)和更新接口文檔。</p>

<p>難道APIJSON不是更好地實(shí)現(xiàn)了前后端分離?</p>

<p> </p>

<p><strong><strong><strong>偏見(jiàn)2</strong></strong>:</strong></p>

<p>數(shù)據(jù)結(jié)構(gòu)過(guò)于羅嗦,為什么我還需要聲明返回值是一個(gè)數(shù)組?</p>

<p><strong>回敬:</strong></p>

<p>數(shù)組非必須,只有獲取列表(數(shù)組)數(shù)據(jù)才需要,可能你只看了最上面復(fù)雜結(jié)構(gòu)的APIJSON請(qǐng)求,誤解了APIJSON請(qǐng)求方式。</p>

<p>比如獲取一個(gè)User可以是{"User":{"id":1}},獲取一個(gè)女性User列表可以是{"[]":{"User":{"sex":1}}},page和count也都是可選參數(shù)非必須。</p>

<p>僅從請(qǐng)求上看,APIJSON的數(shù)據(jù)確實(shí)比傳統(tǒng)方式的多;但從整體上看,APIJSON讓客戶端看請(qǐng)求知結(jié)果,所求即所得,讓服務(wù)端和客戶端都大幅降低了開發(fā)和溝通成本,所以是值得的。</p>

<p>而且APIJSON的客戶端工程提供了JSONRequest類,可以很方便地封裝請(qǐng)求,還不需要像傳統(tǒng)方式那樣addParameter后再拼接鍵值對(duì),請(qǐng)求的代碼量反而更少。</p>

<p> </p>

<p> </p>

<p><strong><strong><strong><strong>偏見(jiàn)3</strong></strong>:</strong></strong></p>

<p>GET的限制。請(qǐng)求報(bào)文不能太長(zhǎng)。。。</p>

<p><strong>回敬:</strong></p>

<p>http協(xié)議里并沒(méi)有對(duì)GET請(qǐng)求的長(zhǎng)度有限制,瀏覽器到倒是有,最少的是IE,限制為2083字符,Chrome限制為8182,Safari限制為80000,其它都在8000以上。</p>

<p>APIJSON客戶端DemoApp主頁(yè)圈子仿微信朋友圈界面,列表里的單項(xiàng)有1個(gè)發(fā)布者User、一個(gè)帶圖片的Moment、最多顯示3個(gè)評(píng)論Comment(多出就折疊),每個(gè)評(píng)論里至少有1個(gè)評(píng)論者User,有的還有1個(gè)被回復(fù)的User。</p>

<p>就這么復(fù)雜的數(shù)據(jù)列表,APIJSON的GET請(qǐng)求經(jīng)過(guò)URLEncder.encode后是1144個(gè)字符。其它界面都比圈子界面簡(jiǎn)單得多,url長(zhǎng)度短很多,所以怎么都是夠用的了。</p>

<p> </p>

<p><strong><strong><strong><strong>偏見(jiàn)4</strong></strong>:</strong></strong></p>

<p>還不是要一套查詢文檔,感覺(jué)也沒(méi)多少必要,也一樣麻煩。</p>

<p><strong>回敬:</strong></p>

<p>APIJSON給出的是公開的隨時(shí)可用的文檔;<br />
傳統(tǒng)模式下是不同后端寫出水平不一、參差不齊的還可能只有在公司內(nèi)才能看的文檔。<br />

APIJSON的文檔僅針對(duì)通用特性,少量、統(tǒng)一、清晰;<br />
傳統(tǒng)模式下的文檔要根據(jù)不同業(yè)務(wù)邏輯、不同功能劃分,一般的程序員還真寫不好,內(nèi)容多、容易混亂,難免出現(xiàn)不少錯(cuò)誤和坑。當(dāng)然如果和你配合的后端是個(gè)大牛就當(dāng)我沒(méi)說(shuō)。<br />
總之,傳統(tǒng)方式不僅導(dǎo)致服務(wù)端開發(fā)成本高、客戶端要等服務(wù)端開發(fā)完接口和文檔才能請(qǐng)求,而且很容易被文檔的錯(cuò)誤坑,增加大量的調(diào)試和溝通成本;<br />
而APIJSON大幅簡(jiǎn)化了連接方式,降低了雙方的開發(fā)和溝通成本;將后端的業(yè)務(wù)邏輯和前端/客戶端的UI分離類似于MVP開發(fā)模式的Model和View解耦,大幅降低了開發(fā)和調(diào)試難度。</p>

<p> </p>

<p><strong><strong><strong><strong>偏見(jiàn)5</strong></strong>:</strong></strong></p>

<p>如果要這樣設(shè)計(jì)的話,那不如讓js直接訪問(wèn)數(shù)據(jù)庫(kù),還可以沒(méi)有接口!</p>

<p><strong>回敬:</strong></p>

<p>這會(huì)導(dǎo)致以下問(wèn)題:<br />
1.前端、客戶端需要了解后端結(jié)構(gòu)、會(huì)使用數(shù)據(jù)庫(kù);<br />
2.容易引發(fā)sql注入,不安全。如果要預(yù)防sql注入,需要從文本提取字段去分析,代碼又會(huì)很臃腫。</p>

<p> </p>

<p><strong><strong><strong><strong><strong>偏見(jiàn)6</strong></strong>:</strong></strong></strong></p>

<p><strong>APIJSON可以讓客戶端傳一個(gè)columns字段來(lái)指定需要的字段</strong>這種方式會(huì)造成客戶端服務(wù)器的強(qiáng)耦合,比如有一天我刪了這個(gè)columns,所有依賴這個(gè)columns的消費(fèi)方都掛了</p>

<p><strong><strong><strong>回敬:</strong></strong></strong></p>

<p>傳統(tǒng)方式刪掉不照樣會(huì)掛?你把currentUserId、pageNum或者User里的id、name、head刪掉一個(gè)試試?</p>

<p> </p>

<p><strong><strong><strong><strong>偏見(jiàn)7</strong></strong>:</strong></strong></p>

<p>業(yè)務(wù)模型如果發(fā)生變化.就會(huì)出現(xiàn)不知道要改哪些地方的問(wèn)題.</p>

<p>后端改字段會(huì)直接影響到前端.</p>

<p><strong><strong><strong>回敬:</strong></strong></strong></p>

<p>傳統(tǒng)方式也是如此,并且還需要更新文檔,然后再通知客戶端修改代碼。</p>

<p>而APIJSON做到了不會(huì)因?yàn)榍岸?客戶端的UI變化而要后端修改返回JSON結(jié)構(gòu)的代碼,也不會(huì)因?yàn)楹蠖烁慕涌趲?lái)開發(fā)和溝通成本,這恰好是APIJSON的優(yōu)勢(shì)。</p>

<p>所以APIJSON在版本迭代上也是遠(yuǎn)超傳統(tǒng)方式的,不需要服務(wù)端寫兼容接口,然后更新文檔,只要客戶端改就行了。<br />
APIJSON還不會(huì)因?yàn)榉?wù)端給的JSON結(jié)構(gòu)不好用導(dǎo)致解析很麻煩,更不會(huì)因?yàn)閺?fù)雜數(shù)據(jù)結(jié)構(gòu)的變化導(dǎo)致修改非常困難(服務(wù)端和客戶端都要重構(gòu)接口相關(guān)代碼)。</p>

<p> </p>

<p><strong>偏見(jiàn)8:</strong></p>

<p>不贊同大范圍使用這種設(shè)計(jì)</p>

<p>要有多種客戶端,一種寫一套,寫得亂七八糟,真好管理!</p>

<p><strong>回敬:</strong></p>

<p>同版本的客戶端的需求都是統(tǒng)一的,都得實(shí)現(xiàn)統(tǒng)一的需求,請(qǐng)求和解析JSON邏輯也是基本一致的,怎么會(huì)混亂不好管理呢?傳統(tǒng)方式為了兼容舊版客戶端要寫v2,v3一堆新版接口和文檔不是更亂管理更麻煩?</p>

<p> </p>

<p><strong>偏見(jiàn)9:</strong></p>

<p>url不友好,容易混亂</p>

<p><strong>回敬:</strong></p>

<p>GET: base_url/get/</p>

<p>HEAD: base_url/head/</p>

<p>POST_GET: base_url/post_get/</p>

<p>POST_HEAD: base_url/post_head/</p>

<p>POST: base_url/post/</p>

<p>PUT: base_url/put/</p>

<p>DELETE: base_url/delete/</p>

<p>再加上login、register、get_authcode等少數(shù)幾個(gè)url。</p>

<p>這難道還多?請(qǐng)求方法和url對(duì)應(yīng)這么清晰,很還混亂?</p>

<p>傳統(tǒng)方式要對(duì)幾乎每個(gè)Table定對(duì)應(yīng)幾個(gè)方法的幾個(gè)url,甚至還要對(duì)細(xì)分功能單獨(dú)定制url,隨便一個(gè)業(yè)務(wù)主要在服務(wù)端的APP都需要50個(gè)以上的url。</p>

<p>我之前兩家公司的兩個(gè)產(chǎn)品的url都超過(guò)100個(gè)。對(duì)第二個(gè)產(chǎn)品隨便翻了一個(gè)非最新版的Word文檔,總共66頁(yè),url有112個(gè),狀態(tài)碼233個(gè),字符數(shù)15148。</p>

<p>每次去文檔里搜索查找url、字段、狀態(tài)碼一堆東西都要不少時(shí)間,還經(jīng)常被文檔里的字段名、字段類型等錯(cuò)誤坑,有的表格還多了或者少了字段!</p>

<p>所以你這句話應(yīng)該用在傳統(tǒng)方式上,APIJSON恰恰大幅減少了url數(shù)量,解決了接口混亂問(wèn)題。</p>

<p> </p>

<p><strong><strong><strong>偏見(jiàn)10</strong></strong>:</strong></p>

<p>沒(méi)覺(jué)得方便。</p>

<p><strong><strong><strong><strong>偏見(jiàn)11</strong></strong>:</strong></strong></p>

<p>沒(méi)看出什么優(yōu)勢(shì)。開發(fā)往往不是技術(shù)問(wèn)題,而是協(xié)作溝通問(wèn)題。</p>

<p><strong>回敬:</strong></p>

<p>服務(wù)端不需要寫接口,不需要寫接口文檔;客戶端不用等服務(wù)端開發(fā)完接口寫好文檔才能請(qǐng)求和解析,也不會(huì)被文檔各種錯(cuò)誤坑,更不會(huì)有因?yàn)槲臋n問(wèn)題帶來(lái)的調(diào)試和與服務(wù)端溝通的成本。 </p>

<p>IDE什么用?用記事本照樣能寫。<br />
Java有什么用?用C照樣能寫。<br />
SDK有什么用?里面的功能都能實(shí)現(xiàn)。<br />
上面都不是技術(shù)問(wèn)題,而是協(xié)作溝通問(wèn)題?</p>

<p> </p>

<p><strong><strong><strong>偏見(jiàn)12</strong></strong>:</strong></p>

<p>跟前端直接把sql傳到后端相比,有什么優(yōu)勢(shì)?</p>

<p><strong>回敬:</strong></p>

<p>用APIJSON比直接傳SQL語(yǔ)句要方便且安全得多。</p>

<p>1.APIJSON支持遠(yuǎn)程函數(shù)調(diào)用,這是SQL語(yǔ)句沒(méi)有的特性。</p>

<p><br />
2.SQL delete忘加where條件引發(fā)的數(shù)據(jù)庫(kù)被清空事件一直都有,前段時(shí)間還有一不小心就刪了整個(gè)公司的新聞。</p>

<p>而客戶端請(qǐng)求APIJSON的方法不是GET或HEAD時(shí),客戶端發(fā)出的Request必須滿足服務(wù)端的配置(具體看table目錄下的sys_Request.sql,可用MySQLWorkbench查看)。</p>

<p>并且都只允許操作某個(gè)id對(duì)應(yīng)的table,不會(huì)發(fā)生忘加條件導(dǎo)致非法DELETE,POST,PUT等請(qǐng)求污染甚至清空數(shù)據(jù)。</p>

<p><br />
3.主流的編輯器對(duì)SQL語(yǔ)句沒(méi)有檢查,一旦出錯(cuò),可能不僅僅是不能返回正確結(jié)果,還可能破壞數(shù)據(jù)。<br />
而APIJSON的Request使用JSONRequest封裝,里面一般都是由業(yè)務(wù)model給定鍵值對(duì)。</p>

<p>比如獲取一個(gè)id為38710的User</p>

<pre>
/**

  • 用戶模型
    */
    public class User {

    private Long id;

    public User() {
    }

    public Long getId() {
    return id;
    }
    public User setId(Long id) {
    this.id = id;
    return this;
    }
    }
    </code></pre>

<p>直接傳SQL:</p>

<pre>
select * from User where id='38710'</code></pre>

<p>這種操作不能保證id的值是某個(gè)類型,甚至可能出現(xiàn)id='3u710',id='38 710'等。關(guān)鍵詞和詞語(yǔ)順序也很容易打錯(cuò), 例如</p>

<pre>
select User * whre id='38710'</code></pre>

<p><br />
APIJSON:</p>

<pre>
JSONRequest request = new JSONRequest(new User().setId(38710));</code></pre>

<p>這樣就得到了 {"User":{"id":38710}} 這個(gè)請(qǐng)求一個(gè)User的Request的body。<br />
如果傳入id值的類型不是Long,編輯器就能檢查出錯(cuò)誤,另外JSON也有很多校驗(yàn)工具(代碼、網(wǎng)站等)。</p>

<p>APIJSON使用阿里巴巴開源的fastjson,會(huì)對(duì)JSON格式校驗(yàn)。最后服務(wù)器上生成的SQL語(yǔ)句一定是合法合理的。 </p>

<p> </p>

<p> </p>

<p><strong><strong>四、</strong>關(guān)于性能</strong> </p>

<p>JSON數(shù)據(jù)很輕量對(duì)客戶端設(shè)備的性能影響可以忽略不計(jì),至于web前端我還不夠深入所以不好回答。</p>

<p> </p>

<p><strong><strong><strong>偏見(jiàn)</strong></strong>:</strong></p>

<p>查詢性能問(wèn)題</p>

<p><strong>回敬:</strong></p>

<p>你是愿意多花幾個(gè)月開發(fā)、測(cè)試、溝通,還是更愿意多花幾百元升級(jí)下服務(wù)器配置?</p>

<p>性能與方便是需要權(quán)衡的,只要性能在可接受范圍內(nèi)就值得使用,如果都往性能一邊倒,現(xiàn)在就不會(huì)有Java,JavaScprit等語(yǔ)言了。</p>

<p>java剛出來(lái)時(shí):垃圾!虛擬機(jī)邊解釋邊運(yùn)行,性能肯定很差!結(jié)果java現(xiàn)在基本上統(tǒng)一了后端、客戶端;<br />
JavaScript剛發(fā)布時(shí),垃圾動(dòng)態(tài)語(yǔ)言!邊運(yùn)行邊判斷類型,一定會(huì)卡到爆!結(jié)果現(xiàn)在它成了當(dāng)之無(wú)愧的前端之王。<br />
歷史總是驚人地相似。</p>

<p>當(dāng)一個(gè)新的技術(shù)出現(xiàn)時(shí),如果它能促進(jìn)技術(shù)和行業(yè)的進(jìn)步,我們作為走在時(shí)代前沿的人是不是應(yīng)該這么想:我該如何推動(dòng)它的發(fā)展?</p>

<p> </p>

<p> </p>

<p><strong><strong>五、</strong>關(guān)于安全</strong></p>

<p>1.APIJSON會(huì)對(duì)請(qǐng)求的格式進(jìn)行校驗(yàn)。</p>

<p>2.APIJSON只有GET,HEAD請(qǐng)求才是明文,其它如POST都是非明文,這個(gè)和傳統(tǒng)方式是一樣的。</p>

<p>3.APIJSON會(huì)對(duì)非GET、HEAD請(qǐng)求的請(qǐng)求方法、結(jié)構(gòu)、內(nèi)容進(jìn)行嚴(yán)格校驗(yàn)。</p>

<p>4.APIJSON對(duì)Table默認(rèn)保護(hù)不可訪問(wèn),需要服務(wù)端配置允許的請(qǐng)求與結(jié)構(gòu)才能用指定的請(qǐng)求方法與結(jié)構(gòu)訪問(wèn)。</p>

<p> </p>

<p><strong>偏見(jiàn)1:</strong></p>

<p>不怕別人偷數(shù)據(jù)?</p>

<p><strong>回敬:</strong></p>

<p>怎么偷?沒(méi)有權(quán)限不能訪問(wèn)需要非公開數(shù)據(jù)。如果是撞庫(kù),傳統(tǒng)方式已經(jīng)被成功黑進(jìn)去拖庫(kù)N次了,iCloud艷照門、網(wǎng)易郵箱、京東數(shù)據(jù)外泄等,安全性也不見(jiàn)得強(qiáng)。</p>

<p> </p>

<p><strong>偏見(jiàn)2:</strong></p>

<p>容易出現(xiàn)安全問(wèn)題。</p>

<p><strong>偏見(jiàn)3:</strong></p>

<p>直接查詢數(shù)據(jù)庫(kù)的數(shù)據(jù)庫(kù)查詢安全。</p>

<p><strong>偏見(jiàn)4:</strong></p>

<p>這跟直接連數(shù)據(jù)庫(kù)沒(méi)什么區(qū)別了,安全性是大問(wèn)題。</p>

<p><strong>偏見(jiàn)5:</strong></p>

<p>把行為交給客戶端控制,安全性不夠</p>

<p><strong>偏見(jiàn)6:</strong></p>

<p>這個(gè)等于是提供了一個(gè)萬(wàn)能API,我只要截獲你的報(bào)文,就可以根據(jù)規(guī)則隨意偽造報(bào)文刪光你的數(shù)據(jù)庫(kù)。</p>

<p><strong>回敬:</strong></p>

<p>1.APIJSON不是客戶端直接查數(shù)據(jù)庫(kù)。中間隔著協(xié)議,怎么會(huì)和直接連數(shù)據(jù)庫(kù)沒(méi)區(qū)別?照這么說(shuō),哪種方式都和直連數(shù)據(jù)庫(kù)沒(méi)區(qū)別了。</p>

<p>2.APIJSON拼接SQL是在服務(wù)端完成的,客戶端是不能直接發(fā)送SQL給服務(wù)端的。整個(gè)數(shù)據(jù)庫(kù)操作都是服務(wù)端完全可控的。</p>

<p>3.APIJSON安全性有多重機(jī)制保障,根本不會(huì)發(fā)生一次性誤刪數(shù)據(jù)庫(kù)的問(wèn)題,甚至連臟數(shù)據(jù)都很難產(chǎn)生。</p>

<p>APIJSON對(duì)Table默認(rèn)保護(hù)不可訪問(wèn),需要配置允許的請(qǐng)求才能用指定的請(qǐng)求方法訪問(wèn)。比如開放User的GET和PUT請(qǐng)求,需要Server工程內(nèi)的AccessVerifier.java內(nèi)加上一行代碼</p>

<pre>
accessMap.put("User", new RequestMethod[]{GET,PUT});//只允許GET和PUT方法訪問(wèn)</code></pre>

<p>如果允許全部請(qǐng)求,可以</p>

<pre>
accessMap.put("User", RequestMethod.values());//允許RequestMethod內(nèi)所有方法。</code></pre>

<p>點(diǎn)擊或復(fù)制到瀏覽器測(cè)試:(請(qǐng)求成功)<br />
<a href="http://139.196.140.118:8080/get/{"User":{"id":38710}}">http://139.196.140.118:8080/get/{"User":{"id":38710}}</a><br />
而Wallet需要保護(hù),就沒(méi)有配置GET請(qǐng)求,通過(guò)GET是訪問(wèn)不了的。配置了POST_GET,可以用POST_GET訪問(wèn),非明文,請(qǐng)求body和返回結(jié)果都被保護(hù)。<br />
點(diǎn)擊或復(fù)制到瀏覽器測(cè)試:(請(qǐng)求失敗,無(wú)GET權(quán)限)<br />
<a href="http://139.196.140.118:8080/get/{"Wallet":{"userId":38710}}">http://139.196.140.118:8080/get/{"Wallet":{"userId":38710}}</a><br />
對(duì)于Wallet,因?yàn)榉?wù)端Demo工程指定了POST_GET請(qǐng)求的JSON結(jié)構(gòu),即便用POST_GET方法,也不能隨意訪問(wèn)。</p>

<pre>
{"Wallet":{"disallowColumns":"!", "necessaryColumns":"userId"}, "necessaryColumns":"currentUserId,loginPassword"}</code></pre>

<p>請(qǐng)求結(jié)構(gòu)必須是類似以下這種:</p>

<pre>
{"Wallet":{"userId":38710}, "currentUserId":38710, "loginPassword":"apijson"}</code></pre>

<p> 以下請(qǐng)求都不合法:</p>

<pre>
{"Comment":{"id":100,...}, ....} //缺少tag</code></pre>

<pre>
{"tag":"Comment", ....} //缺少table,這里指Comment</code></pre>

<pre>
{"Comment":{"id":100,...}, "tag":"Moment", ....} //tag和table名不匹配</code></pre>

<pre>
{"Moment":{"id":100,...}, "tag":"Comment", ....} //tag和table名不匹配</code></pre>

<p>如果多傳了沒(méi)有配置的table,例如</p>

<pre>
{"Comment":{"id":100,...},"Moment":{...}, "tag":"Comment", ....}</code></pre>

<p>服務(wù)端只會(huì)接受Comment,而Moment無(wú)效。<br />
服務(wù)端在QueryConfig中還會(huì)繼續(xù)對(duì)id值進(jìn)行校驗(yàn),傳空值不讓通過(guò)。</p>

<p> </p>

<p><strong>偏見(jiàn)7:</strong></p>

<p>試想一個(gè)User表(包含用戶名,密碼,手機(jī)號(hào)等),用戶要要登陸就可以查詢這個(gè)表吧,那我是不是可以構(gòu)造一個(gè)請(qǐng)求查詢出別人的隱私信息?<br />
我想說(shuō)的是權(quán)限控制很多場(chǎng)景下是要根據(jù)內(nèi)容授權(quán)的,你這個(gè)允許客戶端指定查詢哪個(gè)表甚至查詢條件,無(wú)疑是給客戶端開放的權(quán)限太大了,這跟留一個(gè)后門沒(méi)什么區(qū)別<em> </em></p>

<p><strong>回敬:</strong></p>

<p>目前密碼是單獨(dú)放在Password表里的,不給GET權(quán)限,推薦密碼加密后存儲(chǔ),只允許比較,不允許獲取,成熟的方案很多。<br />
對(duì)于Column的單獨(dú)授權(quán)目前可以設(shè)置dissallowColumns禁止訪問(wèn),對(duì)細(xì)分場(chǎng)景的配置會(huì)繼續(xù)完善。關(guān)于權(quán)限的配置希望大家能給些建議。<br />
開放的權(quán)限沒(méi)你說(shuō)的那么大,關(guān)于安全之前的回復(fù)已一一說(shuō)明。</p>

<p>權(quán)限的開放程度是要權(quán)衡和取舍的,黑莓手機(jī)安全吧,Android,iPhone都不能比,可用的人越來(lái)越少。</p>

<p>功能手機(jī)更安全,不能聯(lián)網(wǎng)不能安裝應(yīng)用,遠(yuǎn)程黑入絕不可能,可為什么安全性相對(duì)差很多的智能機(jī)卻越來(lái)越普及了呢?</p>

<p>另外網(wǎng)絡(luò)安全這東西很復(fù)雜,涉及學(xué)科和范圍很廣,需要軟硬件結(jié)合、各種加密驗(yàn)證機(jī)制等多重手段去保證,用哪種請(qǐng)求方式都不是能輕易解決的。<br />
APIJSON主要面向的是互聯(lián)網(wǎng)小公司、團(tuán)隊(duì)及個(gè)人開發(fā)者,一般不會(huì)對(duì)安全有太高的要求,所以Demo給的是簡(jiǎn)單的示例。<br />
如果對(duì)安全要求很高,可以做Table或者Column映射。 </p>

<p> </p>

<p> </p>

<p> </p>

<p><strong>統(tǒng)計(jì)了下,大部分偏見(jiàn)都是沒(méi)有根據(jù)的憑空臆測(cè)!<strong>實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)!</strong></strong></p>

<p><strong>項(xiàng)目主頁(yè)提供了詳細(xì)的文檔,為什么不看一下?</strong></p>

<p><strong>文檔里提供了測(cè)試鏈接,為什么不點(diǎn)一下?</strong></p>

<p><strong>博客和文檔里都提供了App下載鏈接,<strong>為什么</strong>不用一下?</strong></p>

<p><strong>開源庫(kù)提供了客戶端和服務(wù)端源碼,為什么不運(yùn)行一下?</strong></p>

<p>。。。</p>

<p> </p>

<p>我現(xiàn)在只是杭州電子科技大學(xué)一名普通的大四學(xué)生,</p>

<p>最受歡迎的開源項(xiàng)目<a >ZBLibrary</a>只有800多個(gè)Star;</p>

<p>拿過(guò)最大的獎(jiǎng)不過(guò)是華為創(chuàng)想杯的決賽入圍獎(jiǎng);</p>

<p>待過(guò)最好的公司只是國(guó)內(nèi)500強(qiáng)企業(yè)的一個(gè)子公司;</p>

<p>和幾個(gè)兄弟一起創(chuàng)業(yè)的<a >蝙蝠餓了手機(jī)游戲</a>項(xiàng)目也失敗了。</p>

<p>既沒(méi)有國(guó)外FAG的榮譽(yù),也沒(méi)有國(guó)內(nèi)BAT的光環(huán)。</p>

<p> </p>

<p>我知道博客中講黃段子容易吸引閱讀,我也知道項(xiàng)目中放美女圖容易獲得Star,但這些都是我一直不愿觸及的心里防線。</p>

<p>或許是沒(méi)有光環(huán)、人微言輕,又不愿妥協(xié),才會(huì)有如此多的憑空臆測(cè)的質(zhì)疑和否定。</p>

<p>但我仍然滿腔熱血,渴望對(duì)開源社區(qū)貢獻(xiàn)一份微薄的力量;</p>

<p>但我仍然對(duì)APIJSON充滿希望,一如既往地不斷更新迭代,將它發(fā)展壯大;</p>

<p>但我仍然認(rèn)為群眾的眼睛是雪亮的,開源的力量是強(qiáng)大的。</p>

<p>我會(huì)保持一顆開放包容、虛心學(xué)習(xí)、積極進(jìn)取的心,同廣大的開發(fā)者們互相交流探討,一起學(xué)習(xí)成長(zhǎng)。</p>

<p>最后,很感謝大家提出的各種建設(shè)性意見(jiàn)和寶貴的建議。</p>

<p>技術(shù)改變世界,以此共勉。</p>

<p> </p>

<p><strong>APIJSON,讓接口和文檔見(jiàn)鬼去吧!</strong></p>

<p><strong>下載試用(測(cè)試服務(wù)器地址:</strong>139.196.140.118:8080<strong>)</strong></p>

<p><a >APIJSONClientApp.apk</a></p>

<p><strong>源碼及文檔(覺(jué)得不錯(cuò)就Star支持下吧_)</strong></p>

<p><a >https://github.com/TommyLemon/APIJSON</a></p>

<p> </p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容