轉(zhuǎn)載:http://xiecc.blog.163.com/blog/static/14032200791635949331/
全球第二大社交網(wǎng)站的facebook推出的開發(fā)平臺在幾個(gè)月之內(nèi)迅速走紅。在拒絕了 yahoo,google等的收購后,它的狼子野心也暴露無遺,它要做基于web的OS,在它的開放發(fā)臺上可以搭建集成任何應(yīng)用。游戲、工作、理財(cái)一切都在facebook中了,瀏覽器+facebook,會成為以后人們的生活方式嗎?
然而不得不說facebook的官方文檔既亂且差, 很多剛開發(fā)facebook應(yīng)用的人可能都會丈二和尚摸不著頭腦。這篇日志算是八卦+tutorial吧。
一、facebook簡介
這段純屬廢話,給那些不解facebook, 又不愿意點(diǎn)鏈接的人看。
Facebook發(fā)源于哈佛大學(xué),是目前社會化網(wǎng)絡(luò)和web2.0的風(fēng)向標(biāo)。這個(gè)網(wǎng)站目前全球排名第8位,估值可能超過100億美元。而Facebook開放平臺的推出,更是讓互聯(lián)網(wǎng)業(yè)內(nèi)認(rèn)為它是最有可能和Google比肩的公司。 Facebook創(chuàng)建于2004年2月。這樣的高速增長和短短三年多取得的成就,成為當(dāng)今互聯(lián)網(wǎng)發(fā)展的一個(gè)奇跡。
(Facebook創(chuàng)始人兼CEO Mark Zuckerberg)
這里的介紹更詳細(xì):
http://www.yeeyan.com/articles/view/thunder/2346
二、facebook platform
2007年5月24日,F(xiàn)acebook推出應(yīng)用編程接口(API)。通過這個(gè)API,第三方軟件開發(fā)者可以開發(fā)在Facebook網(wǎng)站運(yùn)行的應(yīng)用程序。這被稱為Facebook開放平臺(Facebook Platform)。
沒有什么比facebook創(chuàng)始人mark Zackerberg的總結(jié)更好了:
"We want to make Facebook into something of an operating system so you can run full applications," Zuckerberg told me, saying it would be analogous to the platform that Microsoft Windows provides for developers.
去 http://www.facebook.com/apps/ 看看吧, 那里的應(yīng)用真是應(yīng)用盡有。
讀寫網(wǎng)總結(jié)的top 10 facebook apps也相當(dāng)?shù)陌簦?
http://www.readwriteweb.com/archives/top_10_facebook_apps_work.php
http://www.readwriteweb.com/archives/top_10_facebook_apps_play.php
三、facebook 應(yīng)用概述
1、平臺開發(fā)環(huán)境
Facebook的開發(fā)環(huán)境是LAMP, 這套傳統(tǒng)的linux+apache+mysql+php的架構(gòu)盡管被很多java程序員和ruby程序員所不屑,但它卻仍然以絕對的優(yōu)勢占據(jù)著主導(dǎo)地位。
不過這對java程序員來說確實(shí)有點(diǎn)痛苦,因?yàn)閒acebook官方包裝的java client相當(dāng)?shù)牟?,更關(guān)鍵的是它沒有提供任何java開發(fā)web應(yīng)用的例子和文檔。幸虧還有一些非官方的tutorial。地址附在后面。
2、應(yīng)用集成
談到應(yīng)用集成, 我們首先想到的是web services 和SOA,這些被工業(yè)界吹了那么多年的buzzword終于得到了推廣,然而值得諷刺的是最后web services的推廣形式不是他們花了那么多年想出來的SOAP標(biāo)準(zhǔn),而是最簡單又不用任何標(biāo)準(zhǔn)的REST,facebook正是提供了一堆REST的 Web services(從嚴(yán)格意義上說facebook的所有service都是POST過去的,URL也沒有完全遵守REST)。
然而這個(gè)層面的集成顯然不能滿足facebook作為web OS的需要,facebook需要讓application運(yùn)行在它提供的平臺上。看看操作系統(tǒng)的需要就能想象到facebook的web OS應(yīng)用提供怎么的集成。
在windows上我們需要安裝應(yīng)用軟件,facebook提供了完整的搜索、瀏覽、添加application的方式。
在windows上我們利用各種快捷方式讓應(yīng)用運(yùn)行在自己的平臺里,facebook提供了運(yùn)行應(yīng)用的簡單入口,而所有的應(yīng)用都是在facebook內(nèi)部展示的。
記得前幾天看到的一篇文章將應(yīng)用集成分為三個(gè)層面:
1 基于web services和SOA的應(yīng)用程序交互
2 平臺運(yùn)行在內(nèi)部服務(wù)器上,而各種應(yīng)用運(yùn)行在外部服務(wù)器上,這正是facebook的方式
3 平臺和應(yīng)用都運(yùn)行在內(nèi)部服務(wù)器上
但是不知道他有沒有想過第三種集成方式的擴(kuò)展性和伸縮性是多么貧乏,我相信facebook的集成方式才是最好的方式。
Facebook的這篇官方文檔解剖了facebook應(yīng)用集成到平臺后的各個(gè)界面展示:
http://developers.facebook.com/anatomy.php
四、facebook應(yīng)用種類
Facebook提供了三類的應(yīng)用:
External application
Iframe
fbml
1、 external application沒什么好說的,就是基于web services的集成,外部應(yīng)用在經(jīng)過facebook的認(rèn)證后可以調(diào)用facebook提供的一些web services。
2、 Iframe的集成也相當(dāng)簡單,只是在facebook平臺的應(yīng)用頁面上放了個(gè)iframe, iframe里跑的是應(yīng)用程序的應(yīng)用。好象facebook里的最火的應(yīng)用之一top friends是用iframe做的。但是由于iframe的天生限制,使它無法完全集成facebook平臺提供的功能,如fbml,在頁面的顯示上也有些怪。
3、目前應(yīng)用用的最多還是fbml。因?yàn)樵趂bml的應(yīng)用中,facebook平臺的頁面(下圖所示的菜單部分)和應(yīng)用程序的頁面(如下圖黃色部分)是無縫顯示的,看上去完全象是一個(gè)應(yīng)用做的事。想象成OS的話,外部的菜單欄更象是windows提供的桌面和開始菜單,黃色區(qū)域則是應(yīng)用程序。
在fbml應(yīng)用中,facebook平臺主要起著中間人的作用,如下圖所示,
所有的用戶對facebook平臺的請求都被轉(zhuǎn)到了應(yīng)用的url(在application 里可以配callback url),只不過是把所有的請求變?yōu)閜ost, 同時(shí)加上認(rèn)證必需的一些參數(shù)。最后返回的html顯示在facebook的application區(qū)的canvas里。
但是這個(gè)中間人的角色并不象想象中的那么簡單, 它至少會引起以下問題:
1、httpsession信息丟失,基本上現(xiàn)在的httpsession都依賴于cookie中的jsessionid,但是經(jīng)過中間人(facebook服務(wù)器)后,cookie的信息是無法獲取,也意味著httpsession是無法保存信息的。因此所有的用戶相關(guān)的信息都是加在中轉(zhuǎn)后的reqeust參數(shù)里的,從request里的userId 和sessionKey應(yīng)用程序可以重建出用戶的所有信息。 不過這倒反而實(shí)現(xiàn)了應(yīng)用的share nothing architectue,對系統(tǒng)的scalability是有好處的。
2、外部css丟失,由于中轉(zhuǎn)的時(shí)候只去request callback url里的頁面,所有外部的css內(nèi)容都是干掉的,應(yīng)用程序只能在html文件里定義css,這對于css狂們真是災(zāi)難。
3、js丟失,facebook會把頁面中所有的js給濾掉,而取而代之用自己設(shè)計(jì)的有限的安全的js語言,這很重要的一部分原因是安全性。但對于ajax狂來說這又是災(zāi)難。
五、facebook的authentication
Facebook的認(rèn)證過程其實(shí)不復(fù)雜, 但是如果java程序捧著官方提供的java包搗騰,恐怕還要費(fèi)些功夫,官方那個(gè)只提供了桌面應(yīng)用的認(rèn)
證程序,而web應(yīng)用的認(rèn)證過程則大廂徑庭。
應(yīng)用程序在注冊時(shí)會獲得該應(yīng)用的api_key和secret,這實(shí)際上是訪問該應(yīng)用的用戶名和密碼了,只有開發(fā)人員可以看到。事實(shí)上以后的每次調(diào)用facebook api都會帶上這api_key,但這顯然還不夠,登錄用戶必須擁自己特定的信息:sessionKey,每次調(diào)用帶上這個(gè)key才能將用戶的信息關(guān)聯(lián)(類似于tomcat的jsessionid),因此認(rèn)證的主要目的就是拿到sessionKey。
上圖是外部web應(yīng)用的認(rèn)證過程,這種應(yīng)用只通過web services與facebook集成,這種應(yīng)用唯一要做的是獲得取得調(diào)用web services的權(quán)限,上圖的流程很清楚了。如果用java開發(fā),一般先用一個(gè)filter或其它interceptor攔截,如果發(fā)現(xiàn)沒有登錄 facebook應(yīng)用自動(dòng)導(dǎo)到facebook的login頁面(在request的參數(shù)里將登錄完后回來的頁面?zhèn)鬟M(jìn)去),登錄后跳回到原來的頁面,就可以在filter中通過request里的authtoken獲取sessionKey了,這種應(yīng)用一般將認(rèn)證后的sessionKey放到HttpSession就可以了(以后不用重復(fù)認(rèn)證)。
上圖是fbml應(yīng)用的認(rèn)證過程,事實(shí)上內(nèi)部應(yīng)用的authentication遠(yuǎn)比外部應(yīng)用簡單,但是官方竟然沒提供文檔。由于facebook的用戶必須登錄才能使用,實(shí)際上在使用 facebook應(yīng)用時(shí)用戶已經(jīng)登錄并擁有了sessionKey和user_id等參數(shù),因此在中間人(facebook server)中轉(zhuǎn)到應(yīng)用的url時(shí),它在request里會把sessionKey和userId等參數(shù)傳進(jìn)去,因此在拿到這些參數(shù)后客戶端可以直接進(jìn)行任何web services的調(diào)用。
六、facebook api (RESTful web services)
Facebook提供了一堆的api,有認(rèn)證、用戶、相冊、好友等功能,從使用的角度來說這倒并不存在什么難點(diǎn)。本身REST的api就是一個(gè)httpRequest請求過去返回一個(gè)xml的response。經(jīng)過了官方或非官方的包裝以后就變成一個(gè)簡單的方法調(diào)用。
1、所有的api調(diào)用都是無狀態(tài)的,這也是facebook擁有這么好的 scalability的重要原因。每個(gè)request里都會帶上api_key, session_key, call_id, sig等參數(shù),這保證了安全性的同時(shí)也保證了scalbility。
2、java的客戶端調(diào)用包比起ruby來實(shí)在是惡心多了。這個(gè)時(shí)候動(dòng)態(tài)語言的優(yōu)勢體現(xiàn)得太明顯了。利用ruby的method missing功能,一個(gè)簡單的實(shí)現(xiàn)就可以調(diào)用facebook的所有api了,而且擴(kuò)展性好。Java的包里則定義了一堆惡心方法,而且返回的是一個(gè) xml document, 經(jīng)過一堆的解析才能取到結(jié)果。
七、fql與fbml
Fql就是facebook版的sql,從使用的角度來說fql的其實(shí)挺簡單,它只是sql的一個(gè)子集, 只支持單表查詢,where條件必須是索引過的字段,支持子查詢, 還支持一些sql的函數(shù)。最簡單的例子:
SELECT name, pic FROM user WHERE uid=211031 OR uid=4801660
Fbml是facebook提供的一堆tag,它只能在fbml的應(yīng)用程序中使用。從使用的角度來說也很簡單,以下html顯示了一個(gè)用戶頭像:
<td><fb:profile-pic uid="${friendId}" linked="true" /></td>
八、開發(fā)環(huán)境
開發(fā)外部的facebook應(yīng)用和iframe的facebook應(yīng)用不需要任何的特殊配置,但是開發(fā)fbml的facebook應(yīng)用卻是另一回事了。從第四節(jié)的facebook as middleman的圖中我們可以看到facebook服務(wù)器要讀到應(yīng)用的頁面塞到facebook的canvas里。這意味著應(yīng)用的頁面必須是外網(wǎng)可以直接訪問才能看到效果。
而我們的開發(fā)平臺卻是搭在本地的, 難道只有部署到服務(wù)器上才能看到頁面效果?這對開發(fā)調(diào)是一個(gè)嚴(yán)重的挑戰(zhàn)。
后悔我當(dāng)初沒有看到這篇blog, 利用SSH的reverse tunnel功能可以將外網(wǎng)的地址按端口號tunnel到本地的開發(fā)環(huán)境。
http://blog.evanweaver.com/articles/2007/07/13/developing-a-facebook-app-locally
我采用另一種方法:增加middleman,facebook本身起了一個(gè)中間人的作用,將facebook的請示導(dǎo)到了應(yīng)用的請求,為什么我們不可以再增加一個(gè)中間人, 把外網(wǎng)的請求導(dǎo)到內(nèi)網(wǎng)?
幸好一個(gè)幾十行的ruby on rails程序就可以搞定route的功能。
這樣實(shí)現(xiàn)后的配置也很簡單,只要將callback url里的參數(shù)映射到本地機(jī)器就可以實(shí)現(xiàn)多人的同時(shí)開發(fā):
urlMap={
:xcc=>'http://192.168.80.156/facebook/',
:skt=>'http://192.168.80.133/facebook/'
}
附 facebook平臺開發(fā)的非官方tutorial:
Ruby的:
http://www.liverail.net/articles/2007/6/29/tutorial-on-developing-a-facebook-platform-application-with-ruby-on-rails
http://giantrobots.thoughtbot.com/2007/6/14/fist-in-your-facebook
java的:
http://javablog.co.uk/2007/07/25/tips-for-writing-facebook-applications-in-java
http://tmachine1.dh.bytemark.co.uk/blog/index.php/2007/08/02/how-to-make-facebook-apps-using-java-part-1/
http://tmachine1.dh.bytemark.co.uk/blog/index.php/2007/08/13/how-to-make-facebook-apps-using-java-part-2/
http://tmachine1.dh.bytemark.co.uk/blog/index.php/2007/09/21/ten-tips-and-tricks-for-writing-facebook-apps/