英文原文:Reverse Ajax, Part 3: Web servers and Socket.IOjavascript
前言html
時至今日,用戶期待的是可經過web訪問快速、動態的應用。這一文章系列展現瞭如何使用反向Ajax(Reverse Ajax)技術來開發事件驅動的web應用。系列的第1部分介紹了反向Ajax、輪詢(polling)、流(streaming)、Comet和長輪詢(long polling)。你已經瞭解了Comet是如何使用HTTP長輪詢的,這是可靠地實現反向Ajax的最好方式,由於現有的全部瀏覽器都提供支持。系列的第2部分說明了如何使用WebSocket來實現反向Ajax,一些代碼例子被用來幫助說明WebSocket、FlashSocket、服務器端的約束、請求做用域(request-scoped)服務以及暫停長生存期請求等。html5
在本篇文章中,咱們深刻細節,討論在web應用中使用不一樣web容器和API(Servlet 3.0和Jetty Continuations)的Comet和WebSocket,瞭解如何經過使用諸如Socket.IO一類的抽象庫來透明地使用Comet和Websocket。Socket.IO使用功能檢測來肯定鏈接是使用WebSocket、Ajax長輪詢、Flash仍是其餘方式來創建。java
前提條件git
理想狀況下,要充分體會本文的話,你應該對JavaScrpit和Java有必定的瞭解。本文中建立的例子是使用Google Guice來構建的,這是一個使用Java編寫的依賴注入框架。若要讀懂文中所談內容,你應該要熟悉諸如Guice、Spring或是Pico一類的依賴注入框架的概念。github
若要運行本文中的例子,你還須要最新版本的Maven和JDK(參見參考資料)。web
Comet和WebSocket的服務器端解決方案ajax
你在第1部份內容中已經瞭解到了,Comet(長輪詢或是流)須要服務器端可以暫停某個請求,並在一個可能的長延遲以後恢復或是完成該請求。第2部份內容描述了服務器端如何使用非阻塞式的I/O功能來處理大量的鏈接,以及它們只能使用線程來服務請求(每一個請求一個線程模式)。你也已經瞭解到了WebSocket的使用是服務器端依賴的,且並不是全部的服務器都支持WebSocket。apache
本節內容說明了若是適用的話,那麼在Jetty、Tomcat和Grizzly等web服務器上是如何使用Comet和WebSocket的。本文提供的源代碼包含了Jetty和Tomcat的一個聊天web應用例子。本節內容還討論了下面的這些應用服務器:Jboss、Glassfish和WebSphere所支持的API。json
Jetty
Jetty是一個web服務器,支持Java Servlet 3.0規範、WebSocket和其餘的許多集成規範。Jetty:
1. 功能強大且靈活
2. 易於嵌入
3. 支持虛擬主機、會話集羣和許多可很容易地經過用於Google App Engine的託管服務的Java代碼或是XML來配置的功能。
核心的Jetty項目由Eclipse Foundation打理。
從版本6開始,Jetty加入了一個被稱做Jetty Continuation(Jetty延續)的異步API,該API容許請求被暫停並在以後被恢復。表1給出了所支持的規範和Jetty的主要版本系列的API之間的一個對照關係。
表1. Jetty的版本和支持
Supports | Jetty 6 | Jetty 7 | Jetty 8 |
---|---|---|---|
Non-blocking I/O | X | X | X |
Servlet 2.5 | X | X | X |
Servlet 3.0 | X | X | |
Jetty Continuations (Comet) | X | X | X |
WebSockets | X | X |
若要實現使用Comet的反向Ajax的話,你可使用Jetty的Continuation API,如清單1所示:
清單1. 用於Comet的Jetty Continuation API
完整的web應用在本文所帶的源代碼中。Jetty Continuation被打包放在一個JAR歸檔文件中,你須要把這一JAR文件放在web應用的WEB-INF/lib目錄下才能使用Jetty的Comet功能。Jetty Continuation在Jetty 六、7和8上都是可用的。
從Jetty 7開始,你還能夠訪問WebSocket功能,把Jetty的WebSocket JAR文件放在web應用的WEB-INF/lib目錄下以得到對Jetty的WebSocket API的訪問,如清單2所示:
清單2. Jetty的Websocket API
在下載的源代碼的jetty-websocket目錄下有一個聊天應用的例子,該例子說明了如何使用Jetty的WebSocket API。
Tomcat
Tomcat多是最廣爲人知的web服務器了,其已經使用多年,且被做爲web容器整合在Jboss應用服務器的早期版本中。Tomcat也被用做是servlet規範的參考實現,但到了servlet API 2.5後就再也不是了,這時人們開始尋求另外一種基於非阻塞式I/O的作法(好比說Jetty)。表2給出了所支持的規範和兩個最新的Tomcat版本系列的API之間的對照。
表2. Tomcat的支持
Supports | Tomcat 6 | Tomcat 7 |
---|---|---|
Non-blocking I/O | X | X |
Servlet 2.5 | X | X |
Servlet 3.0 | X | |
Advanced I/O (Comet) | X | X |
WebSockets |
正如表2所示的那樣,Tomcat不支持WebSocket;它有一個至關於Jetty的Continuation的API,這一被稱爲Advanced I/O的API支持Comet。與其說Advanced I/O是一個很好地方便了Comet使用的API,倒不如說它是一個封裝了NIO的低層面包裝器。它缺少文檔資料,幾乎沒有什麼使用API的應用例子。清單3給出了一個servlet例子,該例子掛起並恢復聊天web應用中的請求。你能夠在本文的源代碼中找到完整的web應用。
清單3. Tomcat用於Comet的API
在Tomcat中,異步的servlet必需要實現CometProcessor。對於異步的servlet來講,Tomcat並不調用標準的HTTP方法(doGet、doPost等),取而代之的是,事件會被髮送給event(CometEvent)方法。當請求首次到達時,例子查看是不是一個GET,是的話便掛起它,evt.close()沒有被調用。若是是一個POST的話,這意味着是用戶發送了一個消息,所以給其餘CometEvent廣播消息,而後調用evt.close()來完成該post請求。在客戶這一端,廣播會讓全部的長輪詢請求完成消息的發送,另外一個長輪詢請求會被馬上發送出去以接收接下來的事件。
Grizzly和Glassfish
Grizzly不是一個web容器,它更像是一個用來幫助開發者構建可伸縮應用的NIO框架。它是被做爲Glassfish項目的一部分開發出來的,但也能夠獨立或是嵌入使用。Grizzly提供了充當HTTP/HTTPS服務器的組件,除了其餘的一些組件以外,其還提供了Bayeux Protocol、Servlet、HttpService OSGi和Comet組件。Grizzly支持WebSocket,其被用在Glassfish中提供Comet和WebSocket支持。
Oracle的應用服務器Glassfish是J2EE 6規範的參考實現。Glassfish是一個完整的套件,相似WebSphere和Jboss,使用Grizzly來支持NIO、Websocket和Comet。它的基於OSGI的模塊化架構,使得其在更換組件時具備真正的靈活性。表3說明了Glassfish對Comet和WebSocket的支持。
表3. Glashfish的支持
Supports | Glassfish 2 | Glassfish 3 |
---|---|---|
Non-blocking I/O | X | X |
Servlet 2.5 | X | X |
Servlet 3.0 | X | |
Comet | X | X |
WebSockets | X |
Grizzly的用法值得一說,由於它本來打算是以嵌入的方式或是直接經過Java代碼來使用的。它被普遍用做支持Comet和WebSocket的框架,可被嵌入到一個更大的應用中,好比說Glassfish,該應用提供了web部署功能和Servlet規範API。
請參閱參考資料一節得到到Grizzly或是Glassfish中的WebSocket和Comet的例子的連接,由於Glassfish使用了Grizzly,因此例子在二者上面都是應該可以運行的。WebSocket API與Jetty中的很是相似,但Comet API就更復雜一些。
Jboss
Jboss是一個構建在Tomcat之上的應用服務器,它從版本5開始支持Comet和NIO。Jboss 7還在開發中,不過也被放在了下面的表4中進行比較。
表4. Jboss的支持
Supports | Jboss 5 | Jboss 6 | Jboss 7 |
---|---|---|---|
Non-blocking I/O | X | X | X |
Servlet 2.5 | X | X | X |
Servlet 3.0 | X | X | |
Comet | X | X | X |
WebSockets |
WebSphere
WebSphere是一個IBM的應用服務器,版本8的WebSphere支持Servlet 3 API(包含了用於Comet的標準的異步API)(請參閱參考資料來了解發布公告的內容)。
表5. WebSphere的支持
Supports | WebSphere 8 |
---|---|
Non-blocking I/O | X |
Servlet 2.5 | X |
Servlet 3.0 | X |
Comet | X |
WebSockets |
通用API方面的狀況
每一個服務器都有本身的本地Comet和WebSocket API,正如你或已猜到的那樣,編寫一個可移植的web應用可能會很難。Servlet 3.0包含了掛起和以後再恢復請求的附加方法,容許全部支持Servlet 3.0規範的web容器支持Comet和長輪詢請求。
Jetty提供了一個被稱做Jetty Continuation的庫,該庫獨立於Jetty容器存在。Jetty Continuation庫很是聰明,可以檢測出可用的容器或是規範。若是是運行在Jetty服務器上,應用所使用的就是本地的Jetty API;若是是運行在支持Servlet 3.0規範的容器上的話,應用所使用的就是這一通用的API;不然的話,就要使用一個無伸縮性的實現。
關於WebSocket,如今在Java中尚未一個標準,所以,若是你想要使用WebSocket的話,就須要在web應用中使用容器供應商的API。
表6總結了各類服務器支持的技術。
表6. 服務器支持的技術
Container | Comet | WebSocket |
---|---|---|
Jetty 6 | Jetty Continuations | N/A |
Jetty 7 | Servlet 3.0 Jetty Continuations |
Native Jetty API |
Jetty 8 | Servlet 3.0 Jetty Continuations |
Native Jetty API |
Tomcat 6 | Advanced I/O | N/A |
Tomcat 7 | Servlet 3.0 Advanced I/O Jetty Continuations |
N/A |
Glassfish 2 | Native Grizzly API | N/A |
Glassfish 3 | Servlet 3.0 Native Grizzly API Jetty Continuations |
Native Grizzly API |
Jboss 5 | Native Jboss API | N/A |
Jboss 6 | Servlet 3.0 Native Jboss API Jetty Continuations |
N/A |
Jboss 7 | Servlet 3.0 Native Jboss API Jetty Continuations |
N/A |
WebSphere 8 | Servlet 3.0 Jetty Continuations |
N/A |
除了使用容器的API以外,在WebSocket方面顯然尚未什麼解決方案。至於Comet,每一個支持Servlet 3.0規範的容器都支持Comet。Jetty Continuation在這方面的優點是在全部的這些容器上都提供了對Comet的支持,所以,某些反向Ajax庫(這在下一節內容和本系列的下一篇文章中會談到)使用Jetty Continuation來做爲它們的服務器端API。
Jetty Continuation API在本文的Jetty例子中有說明,Servlet 3.0規範已經在本系列第1部分的兩個Comet例子中用到並作了介紹。
抽象庫
考慮一下全部主要的API(Servlet 3.0和Jetty Continuation),加上服務器端的全部本地化支持,以及客戶端的兩種主要的實現反向Ajax的方式(Comet和WebSocket),經過編寫本身的JavaScript和Java代碼來捆綁它們實屬不易,你還要考慮超時、鏈接失敗、確認、排序、緩衝等等。
本文餘下部分的內容說明了Socket.IO的用途,本系列的第4部份內容則會探討Atmosphere和CometD,這三個庫都是開源的,它們在許多服務器上都支持Comet和WebSocket。
Socket.IO
Socket.IO是一個JavaScript客戶端庫,相似於WebSocket,其提供了單個的API來鏈接遠程服務器,異步地發送和接收消息。經過提供一個通用的API,Socket.IO支持以下多種傳輸:WebSocket、Flash Socket、長輪詢、流、永久Iframe和JSONP輪詢。Socket.IO檢測瀏覽器的功能,而後嘗試選擇可用的最好傳輸方式。Socket.IO庫幾乎兼容全部的瀏覽器(包括較舊的那些,好比IE 5.5)和移動瀏覽器,它還擁有其餘的一些功能,好比說心跳、超時、斷開鏈接和錯誤處理等。
Socket.IO網站(參見參考資料)詳細描述了該庫的使用方式,以及其所用到的瀏覽器和反向Ajax技術。基本狀況是這樣,Socket.IO用到了一個通訊協議,該協議使得客戶端的庫可以與服務器端的端點進行通訊,服務器端的端點可以理解Socket.IO協議。Socket.IO一開始是爲Node JS這一用來構建更快的服務器的JavaScript引擎開發的,許多項目帶來了對其餘語言的支持,其中就包括了Java語言。
清單4給出了一個在客戶端使用Socket.IO JavaScript庫的例子,Socket.IO網站上有文檔和例子。
清單4. Socket.IO客戶端庫的用法
若要使用Socket.IO JavaScript庫的話,你須要有相應的被稱做Socket.IO Java(參見參考資料)的Java部分。這一項目最初是由Apach Wave團隊啓動的,是爲了給Wave提供反向Ajax支持,這是在WebSocket可用以前的事。Socket.IO Java派生出來後由Ovea(一家專門從事事件驅動的web開發的公司)來維護,再後來就被棄之不顧了。因爲有多種傳輸的緣故,開發支持Socket.IO客戶端庫的後端是很複雜的過程。本系列的第4部份內容會說明,爲了得到更好的伸縮性和瀏覽器支持,在客戶端庫中支持多種傳輸是沒有必要的,由於有長輪詢和WebSocket就足夠了。在WebSocket不可用時,Socket.IO確實是一個不錯的選擇。
Socket.IO Java使用Jetty Continuation API來掛起和恢復請求,其使用本地的Jetty WebSocket API做爲WebSocket支持。你能夠肯定使用了Socket.IO Java的web應用可在哪一個服務器上正確地運行。
下面清單5中的例子說明了在服務器端如何使用Socket.IO,你須要定義一個繼承了SocketIOServlet的servlet,並實現一個返回某種端點表示的方法。這一API很是相似於WebSocket API,它的優勢是用在服務器端,獨立於客戶端所選擇的傳輸方式。Socket.IO把全部的傳輸類型都轉換成服務器端的同一API。
清單5. 聊天例子中的Socket.IO Java的使用——servlet
清單6說明了返回端點的方式。
清單6. 聊天例子中的Socket.IO Java庫的用法——endpoint
Socket.IO的完整例子放在源代碼的socketio目錄下。
結束語
全部的web容器都支持Comet,且大部分的容器都支持WebSocket,即便規範帶來了幾種不一樣的本地化實現,你仍是可使用Comet和通用API(Servlet 3.0和Jetty Continuation)來開發web應用。且更樂觀的狀況是,你可使用諸如Socket.IO一類的庫,以透明的方式來利用Comet和WebSocket的強大功能。還有兩個庫,Atmosphere和CometD,會在本系列的下一篇文章中談及。這三個庫提供了多瀏覽器支持、很是出色的用戶體驗,以及錯誤處理、更簡單的API、超時和重鏈接等多方面的好處。
下載
描述 名稱 大小 下載方法
文章的源代碼 reverse_ajaxpt3_source.zip 21KB HTTP
學習資料
1. 閱讀這一系列以前的部分:
1.1. 第1部分:Comet介紹
1.2. 第2部分:Websocket
2. JSR 315:Java Servlet 3.0規範是2.5規範的更新。
3. 閱讀IBM WebSphere Application Server V8.0的發佈公告。
4. 「Google AppEngine uses Jetty!」介紹了Google的Jetty定製。
5. 瞭解更多關於Jetty Continuation的功能。
6. 瞭解一個使用Grizzly的Glassfish WebSocket例子。
7. WebSphere Application Server:瞭解更多關於IBM WebSphere系列中的這一旗艦產品。
8. WebSphere 8(支持Comet)啓用了智能化的應用環境管理,有助於更快地提交豐富的用戶體驗。
9. Socket.IO的目標是使實時應用在每種瀏覽器和移動設備上都成爲可能,其減輕了不一樣傳輸機制之間的區別。
10. 「Start using HTML5 WebSockets today」(Nettuts+):重溫在PHP中如何運行一個WebSocket服務器,並考慮如何構建一個客戶端來經過WebSocket協議發送和接收消息。
11. 「The WebSocket API」(W3C, July 2011):這一規範定義的API使得網頁可以使用WebSocket協議來和遠程主機進行雙向通訊。
12. 瞭解更多關於Servlet 3.0對異步處理的支持方面的內容。
13. Philip McCarthy的博客上的文章Comet & Java: Threaded Vs Nonblocking I/O中有着更多的內容。
14. 在維基百科上了解這些內容:
14.1. Ajax
14.2. Reverse Ajax
14.3 WebSockets
15. 「Exploring Reverse AJAX」:得到一些關於反向Ajax技術的介紹說明。
16. 「Cross-domain communications with JSONP, Part 1: Combine JSONP and jQuery to quickly build powerful mashups」(developerWorks, February 2009):瞭解如何把不起眼的跨域調用技術(JSONP)和一個靈活的JavaScript庫(JQuery)結合在一塊兒,以使人驚訝的速度構建出一些功能強大的聚合應用。
17. 「Build Ajax applications with Ext JS」(developerWorks, July 2008):對Ext Js背後的面向對象JavaScript 設計概念作了一個概述,並說明了如何把Ext JS框架用做富互聯網應用的UI元素。
18. 「Compare JavaScript frameworks」(developerWorks, February 2010):對極大地加強了JavaScript開發的那些框架有一個總體的瞭解。
19. 「Mastering Ajax, Part 2: Make asynchronous requests with JavaScript and Ajax」(developerWorks, January 2006):學習如何使用Ajax和XMLHttpRequest對象來建立一種永不會讓用戶等待服務器響應的請求/響應模型。
20. 「Create Ajax applications for the mobile Web」(developerWorks, March 2010):瞭解如何使用Ajax構建跨瀏覽器的智能手機Web應用。
21. 「Where and when to use Ajax in your applications」(developerWorks, February 2008):瞭解如何使用Ajax來改進網站,同時避免糟糕的用戶體驗。
22. 「Improve the performance of Web 2.0 applications「(developerWorks, December 2009):探討不一樣的瀏覽器端緩存機制。
23. 「Introducing JSON」(JSON.org):得到對JSON語法的一個入門介紹。
24. developerWorks Web development zone:得到各類談論基於Web的解決方案的文章。
25. developerWorks podcasts:收聽各類與軟件開發者進行的有趣的訪談和討論。
26. developerWorks technical events and webcasts:隨時關注developerWorks的技術事件和webcast的進展。
獲取產品和技術
1. Jetty:獲取Jetty,一個web服務器和javax.servlet容器,外帶對WebSocket的支持。
2. Apache Tomcat Advanced I/O文檔:得到有用的連接、用戶指南、參考手冊和Apache Tomcat開發說明。
3. Grizzly NIO Framework:幫助你使用Java NIO API。
4. Grizzly Comet例子:在從頭開始構建一個新的應用以前,瞭解須要對現有應用作哪些修改。
5. Glassfish Application Server:得到主要的Glassfish Server的開源版本。
6. Socket.IO Java:得到原始的項目和最後更新的Ovea的派生版本。
7. Apache Maven:獲取Maven,一個軟件項目管理和包容工具。
8. Java Development Kit, Version 6:得到Java平臺標準版(Java Platform, Standard Edition,Java SE),該平臺容許你在臺式機和服務器上,以及在當今要求苛刻的嵌入式環境上開發和部署Java應用。
9. 免費試用IBM軟件,下載使用版,登陸在線試用,在沙箱環境中使用產品,或是經過雲來訪問,有超過100種IBM產品試用版選擇。
討論
1. 參加論壇的討論。
2. 如今就建立你的developerWorks我的資料,並設置一個關於Reverse Ajax的觀看列表。與developerWorks社區創建聯繫並保持聯繫。
3. 找到其餘在web開發方面感興趣的developerWorks成員。
4. 分享你的知識:加入一個關注web專題的developerWorks組。
5. Roland Barcia在他的博客中談論Web 2.0和中間件。
6. 關注developerWork成員的shared bookmarks on web topics。
7. 快速得到答案:訪問Web 2.0 Apps論壇。
8. 快速得到答案:訪問Ajax論壇。
關於做者
Mathieu Carbou是Ovea的一位提供服務和開發解決方案的Java web架構師和顧問。他是幾個開源項目的提交者和領導者,也是Montreal的Java User Group的一位演講者和領導者。Mathieu有着很強的代碼設計和最佳實踐背景,他是一個從客戶端到後端的事件驅動的web開發方面的專家。他的工做重點是在高度可伸縮的web應用中提供事件驅動的和消息式的解決方案。你能夠看一看他的博客。