Google App Engine帶來的Java開發(fā)2.0實(shí)現(xiàn)
Java開發(fā)2.0?聽起來是個挺新穎,但也挺老調(diào)長談的概念。隨著云計算的興起,而Google App Engine又提供了Java支持,IBMDW的Andrew Glover在本文中將介紹這個Java開發(fā)2.0是怎么一回事,以及在Google App Engine中又是如何體現(xiàn)的。
Java 世界如同一個豐富的生態(tài)系統(tǒng),涉及開發(fā)人員、事務(wù)以及(最為重要的)應(yīng)用程序等各種角色,其中大部分內(nèi)容在過去十年里已經(jīng)發(fā)展成熟。全球 Java 社區(qū)在 Java 平臺上投入了巨大的金錢、時間和腦力勞動,這些貢獻(xiàn)造就了一個包含成功的開源商業(yè)工具、框架以及解決方案的巨大寶庫。
在 Java 平臺方面的各種投入使 Java 開發(fā)的方式產(chǎn)生了微妙的變化。兩個重要的趨勢正在快速改變 Java 開發(fā)的特征:
- 充分地利用開源工具和框架自上而下 構(gòu)建應(yīng)用程序
- 租用(或外借)各種應(yīng)用程序基礎(chǔ)設(shè)施來管理軟件生命周期,包括運(yùn)行應(yīng)用程序本身
我所指的 Java開發(fā)2.0 的任何一個方面都不是新的或革命性的改變,僅僅是實(shí)現(xiàn)技術(shù)已經(jīng)成熟到可以快速、便宜地組裝更好的應(yīng)用程序,這在 Java 技術(shù)的歷史上是從未有過的 — 這是全世界都希望實(shí)現(xiàn)的主要業(yè)務(wù)需求之一。
本文開啟了一個嶄新的系列,將深入討論 Java開發(fā)2.0。您將了解以下內(nèi)容:使用 Amazon EC2 構(gòu)建和部署 Web 應(yīng)用程序、使用 Google 的 App Engine、利用 CouchDB(被稱為 Web 的數(shù)據(jù)庫),以及在短期內(nèi)以目前為止最低的成本組裝、測試和部署應(yīng)用程序的工具和技術(shù)。
第一站:Google App Engine for Java。我將通過常用的 “Hello World” 方法來介紹這個平臺,然后展示如何使用 Groovy、Java Data Objects (JDO) 和 Eclipse plug-in for Google App Engine 來創(chuàng)建一個有效的 Web 應(yīng)用程序。但是,在此之前,讓我們先快速了解一下 Java開發(fā)2.0 的商業(yè)價值。
速度快成本低
快速和便宜以前很少會和 Java 開發(fā)聯(lián)系在一起。事實(shí)上,它們常常讓人聯(lián)想到不太嚴(yán)肅的軟件開發(fā) — 只有有限資源的小型企業(yè)進(jìn)行的開發(fā)。然而,事實(shí)的真相就是,IT 對于許多公司(不論大公司還是小公司)都是一個成本中心,這促使企業(yè)在最大程度獲取價值的同時降低 IT 成本。
這就是 Java 開發(fā) 2.0 發(fā)揮作用的舞臺。通過利用開源工具、框架甚至是解決方案,企業(yè)可以快速地組裝應(yīng)用程序,因?yàn)槠髽I(yè)自身不需要編寫大量代碼。當(dāng)我在十多年前第一次開始使用 Java 技術(shù)進(jìn)行開發(fā)時,可供開發(fā)人員選擇的工具和框架非常有限。并且這些有限的工具還不是免費(fèi)的。您必須購買一個 IDE、一個數(shù)據(jù)庫、一個對象-關(guān)系映射(ORM)框架(最糟的是,可能必須購買一個驅(qū)動程序才能與數(shù)據(jù)庫通信),當(dāng)然,還需要購買在其上部署應(yīng)用程序的機(jī)器。那么現(xiàn)在呢?我剛剛列出的所有(以及更多)內(nèi)容都可以免費(fèi)獲得,并且具有很棒的品質(zhì)。
此外,通過借用基礎(chǔ)設(shè)施(比如 Amazon EC2 或 Google App Engine 提供的基礎(chǔ)設(shè)施),您可以以非常低的成本部署應(yīng)用程序(您以前需要購買所需的基礎(chǔ)設(shè)施)。
構(gòu)建、購買還是借用:這是個新問題
許多企業(yè)為運(yùn)行應(yīng)用程序,比如數(shù)據(jù)庫、應(yīng)用服務(wù)器、變更管理系統(tǒng)和缺陷跟蹤工具,準(zhǔn)備了一個硬件清單。但是,在現(xiàn)在這個時代,這個清單完全可以扔掉,取而代之的是在其他人的基礎(chǔ)設(shè)施上以運(yùn)行服務(wù)的形式使用相同的軟件包。
團(tuán)隊(duì)用來管理開發(fā)流程的全部應(yīng)用程序堆棧都可以外借 — 也就是說,花費(fèi)少量的費(fèi)用租用 — 這樣公司就不需要再購買運(yùn)行應(yīng)用程序所需的硬件。例如,不需要購買機(jī)器來運(yùn)行變更管理系統(tǒng)(比如 Subversion 或 Git,兩者都是開源的免費(fèi)產(chǎn)品),團(tuán)隊(duì)可以使用 GitHub 之類的共享變更管理服務(wù)。出租 GitHub 的企業(yè)引入了硬件資產(chǎn)成本,因此需要向使用 Git 的其他組織收取少量費(fèi)用(通常為每用戶每月收?。钠渌峁┥桃苑?wù)形式租用軟件的原理可以應(yīng)用于缺陷跟蹤、測試用例管理和需求管理(比如,通過 Hosted JIRA 或 Pivotal Tracker)。
相同的原理可以應(yīng)用于運(yùn)行其他軟件平臺的底層硬件資產(chǎn)(通常為定制的)。企業(yè)可以放棄針對特定 Web 應(yīng)用程序的底層硬件,而傾向于在由 Amazon、Google 或該領(lǐng)域的其他競爭者提供的硬件上運(yùn)行應(yīng)用程序。這些企業(yè)提供了以不同程度租用 硬件的能力,這足以托管應(yīng)用程序。并且,這些公司還可以管理可伸縮性、備份甚至安全性。想一下:Amazon 和 Google 許久之前就解決了這些(以及更多)問題,現(xiàn)在它們更加擅長處理并創(chuàng)新高效運(yùn)行軟件平臺的方面(這是真的,面對事實(shí)吧)。
例如,通過使用 Google 的 App Engine,一家 IT 公司就可以降低購買基礎(chǔ)設(shè)施以運(yùn)行所需應(yīng)用程序的總體成本。并且可以更加快速地部署這些應(yīng)用程序,因?yàn)橐呀?jīng)考慮并提出了各種與應(yīng)用程序部署和管理有關(guān)的交叉問題(并且很可能以一種完美的方式)。
快速 和便宜 不再意味著劣質(zhì)。相反,Java 開發(fā) 2.0 是一種戰(zhàn)略性方法,已經(jīng)設(shè)想了一個以質(zhì)量為重點(diǎn)的可靠流程。
#p#
使用 Google App Engine 減輕負(fù)擔(dān)
Google App Engine 是一個可以在 Google 的昂貴基礎(chǔ)設(shè)施上構(gòu)建和部署 Java(和 Python)Web 應(yīng)用程序的真正平臺。無需任何許可費(fèi)用(當(dāng)然,除非您選擇在基礎(chǔ)設(shè)施上使用的軟件庫要求擁有一個許可)、無需為帶寬或存儲空間支付前期成本。App Engine 基礎(chǔ)設(shè)施在最初是完全免費(fèi)的,直到您達(dá)到了一個使用閾值 — 500MB 的存儲空間,引述 Google 的話,“為每個月大約 500 萬的頁面瀏覽提供足夠的 CPU 和帶寬”。可以這樣說,一旦您達(dá)到了 Google 開始收費(fèi)的那個點(diǎn),您的 Web 應(yīng)用程序已經(jīng)很明顯地產(chǎn)生了巨大的通信量(以及利益)。
啟動并運(yùn)行 App Engine 再簡單不過了。Google 甚至提供了一個 Eclipse 插件,可以為您處理幾乎任何事情。并且該插件包含 “Hello World” servlet 應(yīng)用程序的基本組件,該應(yīng)用程序可以幫助您開始了解此平臺。在其最近一篇 developerWorks 文章(“Google App Engine for Java:第 1 部分:運(yùn)轉(zhuǎn)起來!” 中,Rick Hightower 向您介紹了部署 Hello World 應(yīng)用程序(包含屏幕快照)的整個過程。如果您還沒有閱讀 Rick 的文章,那么可以遵循下面的步驟:
- 創(chuàng)建一個 Google App Engine 帳戶(是免費(fèi)的),方法是在 http://code.google.com/appengine/ 中單擊 Getting Started 下的 Sign up 鏈接。
- 從 http://code.google.com/appengine/downloads.html 下載 Google App Engine plug-in for Eclipse 并安裝它。
- 在 Eclipse 中通過單擊 New Web Application Project 按鈕創(chuàng)建一個新項(xiàng)目;在顯示的對話框中,不要勾選 Use Google Web Toolkit 選項(xiàng)。命名項(xiàng)目和您感興趣的相應(yīng)的包。
- 在層次結(jié)構(gòu)中選擇項(xiàng)目并單擊 Deploy App Engine Project 按鈕。
- 輸入憑證(在步驟 1 中創(chuàng)建 App Engine 帳戶時使用的內(nèi)容)。
- 將本地項(xiàng)目與在最初創(chuàng)建 App Engine 帳戶時生成的應(yīng)用程序 ID 關(guān)聯(lián)起來。(您最多可擁有 10 個 ID)。
- 單擊 Deploy 按鈕。將看到 Eclipse 控制臺中閃過大量文本(插件在后臺執(zhí)行大量工作,包括增強(qiáng)那些利用 Google 的出色的數(shù)據(jù)存儲服務(wù)所需的類)。當(dāng)屏幕穩(wěn)定后(并且一切工作正常),您應(yīng)當(dāng)會看到一條 “Deployment completed successfully” 消息。
- 訪問在 Google 上的 App Engine 帳戶頁面并在 Google 指示板上找到 Versions 鏈接。您將看到自己的已部署的版本及對應(yīng)的 URL。單擊 URL,然后單擊通向生成的 servlet 的鏈接,您會看到單調(diào)但令人欣慰的 “Hello, world” 純文本。
使用 Groovlets 編寫更少的代碼
您已經(jīng)成功部署了您的第一個 Google App Engine 應(yīng)用程序,并且沒有編寫一行代碼。事實(shí)上,如果計劃利用 App Engine,您總是要編寫一些代碼的 — 但要記住,您可以重用已有的大量代碼來更加輕松地 完成工作。這些可重用代碼可能是 Google 提供的一些服務(wù)(比如其數(shù)據(jù)存儲或 Google 帳戶服務(wù))或被移植到 Google 基礎(chǔ)設(shè)施上的開源庫。重用其他人的代碼意味著您常常只需編寫更少的代碼 — 而更少的代碼意味著更少的缺陷。
我最喜歡的開源庫(以及平臺)之一就是 Groovy,它總是可以生成更少的代碼行來創(chuàng)建有效的應(yīng)用程序。Groovy 團(tuán)隊(duì)最近發(fā)布了可以使用 App Engine 的平臺版本,使您能夠利用 Groovlets 而不是 servlets 來在短期內(nèi)創(chuàng)建一個有效的應(yīng)用程序。Groovlets 是一些在行為上類似 servlets 的簡單 Groovy 腳本。由于您已經(jīng)實(shí)現(xiàn)了一個可以輸出 “Hello, world” 的 servlet,因此我將展示使用 Groovlet 完成同樣的事情是多么地簡單(您將看到 Groovy 可以減少多少代碼)。
使用 Eclipse 插件在 App Engine 上部署 Groovlet 只需要很簡單的一些步驟:
- 從 http://groovy.codehaus.org/Download 下載 Groovy 的最新模板(撰寫本文時為 1.6.3 版本)。
- 找到 groovy-all-1.6.3.jar 并將它放到您的 App Engine 項(xiàng)目的 war/WEB-INF/lib 目錄中。順便說一句,在這個目錄中,您可以放置應(yīng)用程序所需的任何庫(我將在稍后給出一些注意事項(xiàng))。
- 將清單 1 中的內(nèi)容(將 Groovlets 映射到指定的請求)添加到 war/WEB-INF 目錄中的 web.xml 文件:
清單 1. 更新 web.xml 文件以支持 Groovlets< servlet> < servlet-name>GroovyServlet< /servlet-name> < servlet-class>groovy.servlet.GroovyServlet< /servlet-class> < /servlet> < servlet-mapping> < servlet-name>GroovyServlet< /servlet-name> < url-pattern>*.groovy< /url-pattern> < /servlet-mapping>
- 將 groovy 目錄添加到 WEB-INF 目錄;這是保存 Groovlets 的位置。在 groovy 目錄中,創(chuàng)建一個名為 helloworld.groovy 的新文件。在這個新文件中,輸入
println "Hello, Groovy baby!"
- 更新應(yīng)用程序的版本(假設(shè) 1-1)并重新部署。通過 Google 指示板找到相應(yīng)的 URL,然后在瀏覽器中打開 /helloworld.groovy,會看到 Groovy 在 Google 的基礎(chǔ)設(shè)施上輸出了一條 hip 消息。
非常簡單,不是嗎?您只需要添加 Groovy JAR、更新 web.xml 文件、創(chuàng)建一個新的 groovy 目錄、編寫一個 Groovlet 然后部署它。您是否還注意到 Groovlet 如何只使用一行代碼 完成與默認(rèn) servlet 插件的工作?您希望編寫并維護(hù)哪一個:一個龐大的類或是具有相同行為的很小的類?
Groovy + Java = 快速構(gòu)建有效的應(yīng)用程序
現(xiàn)在,我將展示如何結(jié)合使用 Groovy 和 Google 的 App Engine 快速創(chuàng)建一個有效的應(yīng)用程序。我將使用一個簡單的 HTTP 頁面、一個 Groovlet 以及一個增強(qiáng)了 JDO 的 Java 類來持久化事件(在本例中為 triathlon)。我將在這里保持簡單性,但是您將會看到這個應(yīng)用程序可以不斷演變來包括其他特性,并且在本系列后續(xù)文章中,您將實(shí)現(xiàn)這些特性(當(dāng)然,使用不同的基礎(chǔ)設(shè)施和技術(shù))。
快速 JDO
Google App Engine 提供了使用 JDO 持久化數(shù)據(jù)的能力,JDO 是一個 Java 持久化標(biāo)準(zhǔn)。對于大部分 Java 開發(fā)人員來說,持久化數(shù)據(jù)常常意味著將信息保存到一個關(guān)系數(shù)據(jù)庫中;然而,對于 Google 來講,底層存儲機(jī)制就是它的 Big Table,而后者并不是關(guān)系型的。也就是說,這一點(diǎn)無關(guān)緊要:Google 如何持久化特定屬性的細(xì)節(jié)在很大程度上已經(jīng)被隱藏。可以這樣說,您可以使用普通的 Java 對象(或 Groovy 對象,就本文而言)來構(gòu)建一個應(yīng)用程序,這個應(yīng)用程序可以像任何其他應(yīng)用程序那樣存儲信息。這就是 Google 的方法,您必須使用 JDO。(Hibernate 無疑是面向 Java 的最流行的 ORM 框架,但它并不能用于 App Engine)。
JDO 非常簡單。您將創(chuàng)建 POJO — 老式普通 Java 對象(可以和其他 Java 對象建立聯(lián)系),您通過類級別的 @PersistenceCapable
注釋將其聲明為具有持久能力。通過 @Persistent
注釋指定要進(jìn)行持久化的對象的屬性。例如,我希望存儲 triathlon 事件(目前而言,我將關(guān)注事件而不是與 triathlon 有關(guān)的各種結(jié)果)— 就是說,事件擁有一個名稱(triathlon 的名稱),可能還有一個描述(triathlon 的類型)和一個日期。目前為止,我的 JDO 看上去類似清單 2:
import java.util.Date; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.IdentityType; @PersistenceCapable(identityType = IdentityType.APPLICATION) public class Triathlon { @Persistent private Date date; @Persistent private String name; @Persistent private String description; } |
無論使用哪一種底層機(jī)制(即關(guān)系型或 Google 的 Big Table),數(shù)據(jù)持久性始終需要涉及鍵(key)的概念:一種為了避免數(shù)據(jù)崩潰而確保數(shù)據(jù)的不同方面具有惟一性的方法。例如,對于 triathlon,它的鍵可以是 triathlon 的名稱。如果兩個 triathlon 擁有相同的名稱,那么可以將名稱和日期組合起來作為鍵。不管您使用何種方式通過 Google App Engine 和 JDO 表示鍵,必須通過 @PrimaryKey
注釋在 JDO 對象中指定一個鍵。您還可以為鍵的生成方式選擇一些策略 — 由您或 Google 生成。我將使用 Google 生成并保持簡單性:我的 triathlon 對象的鍵被表示為一個普通的 Java Long
對象,并且我將通過指定一個值策略 來讓 Google 確定實(shí)際的值。清單 3 添加了一個主鍵:
import java.util.Date; import javax.jdo.annotations.IdGeneratorStrategy; import javax.jdo.annotations.PersistenceCapable; import javax.jdo.annotations.Persistent; import javax.jdo.annotations.PrimaryKey; import javax.jdo.annotations.IdentityType; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ReflectionToStringBuilder; @PersistenceCapable(identityType = IdentityType.APPLICATION) public class Triathlon { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Long id; @Persistent private Date date; @Persistent private String name; @Persistent private String description; public Triathlon(Date date, String name, String description) { super(); this.date = date; this.name = name; this.description = description; } //...setters and getters left out public String toString() { return ReflectionToStringBuilder.toString(this); } public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); } public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj); } } |
如清單 3 所示,我的 triathlon JDO 擁有一個由 Google 基礎(chǔ)設(shè)施管理的鍵,并且添加了一些標(biāo)準(zhǔn)的方法(toString
、hashCode
和 equals
),為調(diào)試、登錄以及適當(dāng)?shù)墓δ芴峁┝藰O大的幫助。我并沒有親自編寫這些內(nèi)容,相反,我使用了 Apache commons-lang 庫。我還添加了一個構(gòu)造函數(shù),與調(diào)用大量 setter 方法相比,這個構(gòu)造函數(shù)可以更加輕松地創(chuàng)建完全初始化的對象。
我有意維持了 JDO 的簡單性,但是正如您所見,并沒有包含多少內(nèi)容(就是說,為了保持簡單性,我去掉了所有的關(guān)系并忽略了 getter 和 setter 方法)。您只需對域進(jìn)行建模并隨后使用一些注釋來修飾模型,然后剩下的工作就由 Google 來完成。
將對象定義為具有持久性后,還剩下最后一個步驟。要與底層的數(shù)據(jù)存儲交互,需要使用 PersistenceManager
,這是一個 JDO 標(biāo)準(zhǔn)類,顧名思義,它的作用就是在一個底層數(shù)據(jù)存儲中保存、更新、檢索和刪除對象(非常類似于 Hibernate 的 Session
對象)。這個類通過一個工廠(PersistenceManagerFactory
)創(chuàng)建,這個工廠非常復(fù)雜;因此,Google 建議創(chuàng)建一個獨(dú)立的對象來管理工廠的單個實(shí)例(后者在您需要時返回一個合適的 PersistenceManager
)。相應(yīng)地,我可以定義一個簡單的獨(dú)立對象來返回 PersistenceManager
的實(shí)例,如清單 4 所示:
PersistenceManager
實(shí)例的簡單獨(dú)立對象
import javax.jdo.JDOHelper; import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManagerFactory; public class PersistenceMgr { private static final PersistenceManagerFactory instance = JDOHelper.getPersistenceManagerFactory("transactions-optional"); private PersistenceMgr() {} public static PersistenceManager manufacture() { return instance.getPersistenceManager(); } } |
可以看到,我的 PersistenceMgr
非常的簡單。manufacture
方法從 PersistenceManagerFactory
的單個實(shí)例返回一個 PersistenceManager
實(shí)例。您還會注意到,清單 4 中沒有出現(xiàn)任何特定于 Google 的代碼或任何其他利用 JDO 的代碼 — 所有引用都是指向標(biāo)準(zhǔn) JDO 類和接口的。
新添加的兩個 Java 對象位于我的項(xiàng)目的 src 目錄中,并且我將 commons-lang 庫添加到了 war/WEB-INF/lib 目錄中。
利用定義好的簡單 triathlon JDO POJO 和方便的 PersistenceMgr
對象,我已經(jīng)有了很好的起點(diǎn)。我所需要的就是能夠捕獲 triathlon 信息。
#p#
大多數(shù) Web 應(yīng)用程序都遵循相同的模式:通過 HTML 表單捕捉信息,然后將它們提交到服務(wù)器端資源以進(jìn)行處理。當(dāng)然,這一過程中還混合了許多其他技術(shù),但是不管底層技術(shù)或基礎(chǔ)設(shè)施如何,模式始終保持不變。Google App Engine 也是如此 — 我已經(jīng)編碼了服務(wù)器端資源來處理保存的 triathlon 數(shù)據(jù)。剩下的工作就是捕捉信息 — 表單 — 以及將服務(wù)器端與表單連接起來。按 Model-View-Controller (MVC) 的話說,我需要一個控制器(通常為一個 servlet);我將利用 Groovlet 替代,因?yàn)槲蚁M帉懜俚拇a。
我的 HTML 表單非常簡單:我所需做的就是創(chuàng)建一個 HTML 頁面,利用某些簡單的 Cascading Style Sheets (CSS) 代碼來創(chuàng)建表單,如圖 1 所示,看上去更接近 Web 2.0,而不是 1998 年出現(xiàn)的 HTML 頁面:
可以從圖 1 中看到,表單捕捉到一個名稱、描述和一個日期。然而,日期并不簡單 — 它實(shí)際上是一個日期的三個屬性。
快速 Groovlet
Groovlets 使得編寫控制器變得非常簡單:它們需要更少的代碼并自動提供了所需的對象。在 Groovlet 中,您分別通過 request
和 response
對象隱式地訪問 HTML 請求和響應(yīng)。在我的 Groovlet 中,我可以通過 request.getParameter("name")
調(diào)用獲得提交的 HTML 表單的所有屬性,如清單 5 所示:
def triname = request.getParameter("tri_name") def tridesc = request.getParameter("tri_description") def month = request.getParameter("tri_month") def day = request.getParameter("tri_day") def year = request.getParameter("tri_year") |
前面編寫的 JDO 使用了一個 Java Date
對象;然而,在清單 5 中,我處理了 Date
的三個不同屬性。因此我需要一個 DateFormat
對象來將 month
、day
、year
三者的組合轉(zhuǎn)換為一個普通的 Java Date
,如清單 6 所示:
def formatter = new SimpleDateFormat("MM/dd/yyyy") def tridate = formatter.parse("${month}/${day}/${year}") |
最后,從已提交 HTML 表單獲得所有參數(shù)后,我可以使用清單 7 的代碼,通過我的 JDO 和清單4的 PersistenceMgr
對象將它們持久化到 Google 的基礎(chǔ)設(shè)施中:
def triathlon = new Triathlon(tridate, triname, tridesc) def mgr = PersistenceMgr.manufacture() try { mgr.makePersistent(triathlon) } finally { mgr.close() } |
就是這么簡單!當(dāng)然,隨著更多的頁面加入到我的簡單應(yīng)用程序中(比如捕捉特定 triathlon 的結(jié)果),我可能需要轉(zhuǎn)發(fā)或重定向到另一個表單,這將捕捉額外的信息,與向?qū)诸愃?。不管怎樣,通過一些簡短的代碼片段,我快速組合了一個簡單的 Web 應(yīng)用程序,它可以通過 JDO(使用普通 Java 編碼)和一個 Groovlet(當(dāng)然,使用 Groovy 編碼)將數(shù)據(jù)持久化到 Google 的基礎(chǔ)設(shè)施中。部署應(yīng)用程序非常簡單,只需在 appengine-web.xml 文件中指定一個版本并單擊 Deploy 按鈕。
但是,這個用于捕捉 triathlon 事件的只包含一個表單的 Web 應(yīng)用程序并沒有試圖實(shí)現(xiàn)全部的功能,所以說,我僅僅是將應(yīng)用程序部署到一個不規(guī)則的、普遍存在的環(huán)境中。我不需要觸發(fā)一個 Web 容器甚至指定在哪里 部署應(yīng)用程序。(它位于 California、我的硬盤或者是月球上?)妙處在于這并不重要 — Google 負(fù)責(zé)處理這個問題。注意,是解決所有問題。此外,可以肯定的是,Google 已經(jīng)知道如何進(jìn)行全球性擴(kuò)展,這樣位于印度的用戶在查看應(yīng)用程序時會擁有和阿根廷用戶相同的體驗(yàn)。
綜上所述,您的確有必要牢記一些東西。Google 的基礎(chǔ)設(shè)施支持 Java 技術(shù),但是并不意味著所有內(nèi)容;如果您回憶一下多年前 J2ME 問世的情景,那么 App Engine 的限制可能在本質(zhì)上有些類似。也就是說,并非所有核心 Java 庫和相關(guān)開源庫都受支持。如前所述,Hibernate 就不受支持(主要是因?yàn)槭褂?App Engine 時,您無法擁有關(guān)系數(shù)據(jù)庫)。我在使用某些內(nèi)置了 base64 編碼的開源庫時還遇到了一些挑戰(zhàn)(Google 要求您使用它的 URL Fetch 服務(wù))。App Engine 是一個平臺 — 您必須以它為方向進(jìn)行開發(fā),就目前而言,這是一個單向的過程。
結(jié)束語
面向?qū)ο缶幊痰膭?chuàng)始人之一 Alan Kay 曾經(jīng)這樣說道,“預(yù)測未來的最佳方式就是實(shí)現(xiàn)它”。我同意 Alan Kay 的這個說法。不管其他人如何預(yù)測 Java 技術(shù)的未來,我認(rèn)為未來已經(jīng)在您的面前。
正如您在本文中了解的那樣,Google App Engine 正是面向未來的一個平臺 — 假設(shè)您在其沙盒中試用。(注意,我只介紹了沙盒中的部分特性;App Engine 具有大量特性)。如果您希望獲得更多的靈活性(就是說,希望擁有一個關(guān)系數(shù)據(jù)庫并且必須使用 Hibernate),但是也希望借用其他人的可擴(kuò)展基礎(chǔ)設(shè)施,那么可以使用替代解決方案。Amazon 的 EC2 實(shí)際上就是位于按需使用的混合基礎(chǔ)設(shè)施上的虛擬服務(wù)器。您將在下個月的 Java 開發(fā) 2.0 中了解它。
【編輯推薦】