正如您從 “Java 開發 2.0:您也可以租用 EC2” 中了解到的一樣, Amazon 的 Elastic Compute Cloud (EC2) 是一個用於托管(Linux®、OpenSolaris 甚至 Windows®)虛擬機的通用基礎設施服務,您可以在這些虛擬機上運行任何程序 。假如您創建或借用了一個虛擬機,也可以將其稱為 Amazon Machine Image (AMI) 或實 例,那麼您可以運行任何 Java 應用程序 — 包括使用 Hibernate 和 Spring 的 Web 應用程序,正如我將在本文所展示的一樣。
圍繞 Amazon 的 Web 服務產品的社區在過去幾年中一度非常活躍,並且您可以從一組 完整的公共虛擬機分類中選擇一種虛擬機來使用。Linux 提供了許多不同版本的虛擬機, 因此可以想象得到虛擬機分類附帶了各種軟件配置和相關工具。對於本文來講,我將選擇 符合以下條件的 AMI:
已經安裝了某種 Java 版本(最好是一個較新的版本)
具有一個 servlet 容 器,例如 Tomcat
具有一個免費可用的數據庫,例如 MySQL
尋找 AMI
通過浏覽 Amazon 的擴展分類,您不僅可以尋找符合需求的 AMI,某 些 AMI 提供商還在 Web 上提供了它們獨有的實例,包括免費的和商用的。例如,Java Web Apps in a Box 就非常適合本文的 Java Web 開發項目。我在 Java Web Apps in a Box 站點中找到了啟動該實例所需的所有重要 AMI ID(我將在本文後面演示這一過程) 。
我還有另外一個選擇,那就是使用一種 “空白” 虛擬機,然後在 其中安裝這些組件。但是您需要花些時間尋找大量的配置。事實上,在大多數情況下, EC2 供應中最困難的部分在於尋找符合您的要求的特定虛擬機。一旦找到這樣的虛擬機後 ,那麼您將開始從中獲得樂趣!我真的 找到一個 符合我的要求的虛擬機,我將展示如何 使用它。這非常簡單,如果您已經安裝了我在 前一篇文章 中提及的 Eclipse AWS 插件 的話,那麼就更簡單了。
Eclipse AWS 插件允許您搜索、啟動和終止實例;並且,假如您已經正確配置了一個 鍵對(插件可以很好地處理),那麼您可以通過一個特定映像的終端窗口執行 ssh,以進 行進一步的配置。
然而,就像上一次一樣,當我開始展示 EC2 的細節時,在啟動公共 AMI 之前,最好 構建一個快速 Java 應用程序。通過使用 Grails 框架,應用程序將利用 Spring 和 Hibernate(並因此使用一個底層的持久化存儲)。
關於本系列
自 Java 技術出現伊始,Java 開發領域發生了巨大的變化。得益於成熟的開源框架和 可靠的外部(for-rent)部署基礎設施,現在我們能夠以很低的成本快速組裝、測試、運 行和維護 Java 應用程序。在本系列文章中,Andrew Glover 探討了使這種新的 Java 開 發范例成為可能的技術和工具。
速度是關鍵
在使用借來的基礎設施的過程中,Java 開發 2.0 的一個重要方面就是利用開源技術 以自上而下的方式構建應用程序。通過使用開源工具、框架甚至是解決方案,公司可以迅 速地組裝應用程序,因為他們自身不需要編寫大量代碼。當談到能夠使開發變得迅速並且 更加簡單的開源解決方案時,首先想到的兩個框架就是 Spring 和 Hibernate。
實際上,世界上的所有 Java 組織都使用 Spring 框架構建應用程序。盡管它主要以 一種反轉控制(IoC)框架而著稱,但是它確實成為了 Java 開發的主力。(Spring 是一 種面向方面的編程 [AOP] 框架、一種 OSGi 容器、一個 Web 框架等)。Hibernate 亦不 遜色,它是 Java 對象-關系映射(ORM)領域中的重量級框架。Java Data Objects (JDO)(我在本系列 第一期 中已經使用 Google App Engine 進行了演示)的采用率在任 何方面都不及 Hibernate。因此,當我思考當前以及未來的 Java 開發時,很可能會想到 結合使用 Spring 和 Hibernate。(這並不表示您需要同時使用這兩者來完成某項特定工 作,只是說明在大部分情況下,這兩個框架基本上可以滿足您的全部需求)。
與此同時,Groovy 是一種可以大大簡化 Java 開發的開發平台。 Groovy 實際上就是 簡化了語法的 Java 語言。它允許您將重心放在快速構建解決方案上,而不是周而復始地 編寫大量 Java 代碼來解決相同的問題。(Groovy 在這方面並非獨樹一幟。運行在 JVM 上的許多其他語言都可以處理相同的問題)。對於我來說,Groovy 僅僅是我的工具箱中 的另一個 JAR 文件。
因此,當我考慮快速構建應用程序時,我想到了 Groovy、Spring 和 Hibernate。對 於 Web 應用程序,有一種特殊的框架可以將這三者完美地結合在一起,該框架就是 Grails。Grails 構建在 Spring 之上並基於 Groovy。並且 Grails Object Relational Mapping (GORM) — Grails ORM 實現 — 在內部使用 Hibernate。
本文並不會重點介紹 Grails。(如果您希望精通 Grails 的話,我建議您閱讀 Scott Davis 的 精通 Grails 系列)。也就是說,使用 Grails 構建簡單 Web 應用程序將超乎 尋常地簡單。
使用 Grails!
Grails 的入門非常簡單。跟隨本文的步驟,您很快就會得到一個利用數據庫的基本 Web 應用程序(通過 Spring 和 Hibernate)。首先,下載 Grails,將其解壓縮,然後 設置一個指向安裝目錄的 GRAILS_HOME 環境變量來對環境進行配置。隨後將 GRAILS_HOME/bin 添加到您的路徑。同樣,確保您得到了一個 JAVA_HOME 環境變量。
現在打開一個控制台窗口或 shell(根據您的操作系統)並在命令提示中輸入以下內 容:
grails create-app mytri
這將毫無意外地創建一個名為 mytri 的 Grails Web 應用程序,這與我在 本系列早 期文章 中展示如何使用 Google App Engine 進行構建時使用的 triathlon-tracking 應 用程序的通用主題相一致。
接下來,將目錄切換到新創建的 Web 應用程序(cd mytri/)並輸入:
grails create-domain-class Triathlon
您應當會發現 Grails 輸出了一些代碼行,其結尾類似如下內容:
Created DomainClass for Triathlon
Created Tests for Triathlon
現在,將目錄切換到 grails-app/domain。在該目錄中,您將發現一個文件被命名為 Triathlon.groovy。在任意一種編輯器中打開這個文件。正如本系列早期文章一樣,我不 會花太多時間關注這類內容。也就是說,從現在起,我將進行非常扼要的介紹(您總是可 以在稍後進行補充);我將忽略鐵人三項賽(triathlon)的各種關系,而是關注它的一 些屬性:
日期
類型(短跑、半程鐵人三項賽等)
名稱
位置
因此,將清單 1 中的代碼添加到您的 Triathlon.groovy 文件:
清單 1. 表示一個 triathlon 的樣例域對象
class Triathlon {
static constraints = {
classification(inList:["Sprint", "Olympic", "1/2 Iron Man", "Iron Man"] )
}
String name
String location
Date eventDate
String classification
}
注意對象的 constraints 部分是如何指定 classification 只能為四種類型的其中之 一的。保存並關閉文件。
接下來,返回到項目的主目錄(mytri)並輸入以下內容:
grails generate-all Triathlon
該命令將創建模型-視圖-控制器(MVC)的視圖和控制器部分。Triathlon 對象就是模 型。
現在可以深呼吸一下了,因為您已經完成了工作。您剛剛創建了一個簡單的 Web 應用 程序,它可以在數據庫中創建、更新、移除和讀取 triathlon。很令人振奮,不是嗎?要 運行此應用程序,輸入以下命令:
grails run-app
打開浏覽器並訪問 http://localhost:8080/mytri。您將看到在我的域對象中, Grails 生成了一些支持 CRUD(創建、讀取、更新、刪除)的通用接口。
例如,當 mytri 應用程序加載時(參見圖 1),應當會看到一個指向 TriathlonController 對象的鏈接,該對象是在您運行 generate-all 命令時由 Grails 生成的:
圖 1. 默認 Grails 應用程序主頁
單擊 TriathlonController 鏈接將顯示底層數據存儲為空。但是如果隨後單擊 New Triathlon 鏈接,您將看到一個用於創建 triathlons 的表單,如圖 2 所示:
圖 2. 用於創建 triathlon 的表單
使用一些數據填充該表單,然後單擊 Create 鏈接,您將被帶回到可用 triathlons 列表。您新創建的對象現在已經顯示在列表中,如圖 3 所示:
圖 3. 成功的 triathlon 創建
在內部,Grails 使用了一個名為 HSQL 的內存數據庫;然而,您接下來將導出 Grails 正在使用的模式並做好准備,以便在 MySQL 內部創建一個數據庫表。
將 Grails 配置為與數據庫交互(而不是與 HSQL 交互)將非常簡單。訪問 mytri/grails-app/conf 目錄並使用您喜歡的編輯器打開 DataSource.groovy 文件。在 文件的 dataSource 部分,添加如下代碼:
dialect=org.hibernate.dialect.MySQLDialect.class
這行代碼將告訴 Grails 使用 Hibernate 的 MySQL 方言(dialect);特別是,您希 望 Grails 生成一個有效的 MySQL Data Definition Language (DDL) 文件。因此,接下 來,在您的控制台中,確保您位於項目的主目錄並輸入如下內容:
grails schema-export
這一處理將生成一個復制的 sql.ddl 文件,其中包含您用來在 MySQL 內創建相應表 的語句(您將在稍後執行這一步驟)。最後,從 DataSource.groovy 文件中刪除 dialect 行 — 稍後將把它放回到一個不同的位置。
供應 Amazon 實例
好了,您現在已經完成了許多工作,但是尚未觸及 EC2。但是,這是一件好事。EC2 以及類似服務的魅力在於它們非常簡單,並且可以被立刻觸發。相應地,打開 Eclipse( 安裝 AWS 插件並配置它,如果還沒有這樣做的話 — 如有必要,參見 上一個月的文章 獲得指導)並打開 Amazon EC2 Management 透視圖。從該透視圖中,單擊 EC2 AMIs 視 圖。您應當會看到一個非常奇怪的列表,其中包含 ID 和清單,並且視圖的右上角有一個 文本框,如圖 4 所示:
圖 4. AMI 清單
在不顯眼的文本框中,輸入 ami-aa5abac3。這是 Java Web Apps in a Box 提供的方 便的 AMI 的 ID。圖 5 顯示了結果:
圖 5. 我需要的 AMI
可以從圖 5 中看到,ami-aa5abac3 AMI 已經被找到,並且它的清單包含有 tomcat 和 mysql 幾個詞 — 不算壞,我們取得了一些進展。接下來,選擇 AMI,右鍵單擊,然 後選擇 launch 選項。您將看到一個新的對話框顯示出來,其中允許您配置 AMI 的啟動 。在啟動 AMI 時,應當選擇一對鍵和一個安全組(就像在 “Java 開發 2.0:您也可以 租用 EC2” 中所做的一樣),如圖 6 所示:
圖 6. 配置 AMI 啟動選項
單擊 Finish 按鈕,正如您猜想的一樣,這將在 Internet 中的某個位置啟動 AMI。 您可以在 Eclipse AWS EC2 Instances 視圖中看到,如圖 7 所示,您的實例的啟動處於 待定狀態:
圖 7. Eclipse AWS EC2 Instances 視圖
AMI 的狀態將由啟動變為運行。這可能需要一些時間,因此耐心些。一旦實例進入運 行狀態,您將注意到 Eclipse AWS EC2 Instances 視圖顯示出針對您的 AMI 的公共 DNS 。這可以幫助您稍後導航到您的 Web 應用程序。
您需要一個終端會話來進一步配置 MySQL。選擇實例,右鍵單擊,然後選擇 Open Shell 選項。根據本地機器的操作系統,您可能需要尋找一個支持 SSH 的 shell。
配置 MySQL 和 Grails
在從 Eclipse 內部打開的、指向新啟動的 AMI 的 shell 中,通過以下命令登錄到 MySQL:
mysql -u root --password=root
隨後為您的 Grails 實例創建一個新用戶:
mysql> CREATE USER 'grails'@'localhost' IDENTIFIED BY 'groovy';
然後向此用戶授予數據庫權限:
mysql> GRANT ALL ON *.* to 'grails'@'localhost';
接下來,創建一個數據庫(或模式,根據您看待數據庫中事物的方式):
mysql> create database mytri;
您必須隨後開始使用新創建的數據庫,以創建一些表:
mysql> use mytri;
最後,執行 sql.ddl 文件中的最後一行代碼(不要出現任何中斷):
mysql> create table triathlon (
id bigint not null auto_increment, version bigint not null, classification varchar(12)
not null, event_date datetime not null, location varchar(255) not null,
name varchar(255) not null, primary key (id));
現在您的 MySQL 數據庫已經可以投入使用了。剩下的工作就是配置 Grails 以使用它 。
配置 Grails 以使用 MySQL
下載 MySQL JDBC 驅動程序並將其放到 mytri/lib 目錄中。接下來,打開 DataSource.groovy 文件並更新 production 部分,如清單 2 所示:
清單 2. 將 MySQL 驅動器和 dialect 配置添加到 DataSource.groovy
production {
dataSource {
driverClassName = "com.mysql.jdbc.Driver"
username = "grails"
password = "groovy"
dialect=org.hibernate.dialect.MySQLDialect.class
url = "jdbc:mysql://localhost/mytri"
}
}
這一修改將指向在同一台機器(本地主機)上運行的底層 MySQL 數據庫上的 Grails 生產實例。當然,本地主機實例是一個在某處運行的 AMI。
通過 Tomcat 管理接口部署 Grails 應用程序
本地測試
僅僅是出於節省時間的考慮,我將跳過對 Grails 的配置了 MySQL 的實例進行本地測 試的內容。也就是說,我假設您並未對 MySQL 進行本地安裝,因此我將利用 EC2 映像上 的一個現有 MySQL 實例來保持簡單性。讓我再講清楚一些:如果您計劃在生產中使用 MySQL,那麼在雲中啟動它之前,您應該進行本地安裝並在本地測試應用程序是否正常工 作。
Grails 應用程序 — 就如同任何 Java Web 應用程序一樣 — 的部署方式和 WAR 文 件沒什麼兩樣。相應地,回到您的計算機的 shell 中(即您用來處理 Grails 的 shell ,而不是指向 EC2 實例的 shell),輸入下面的內容:
grails -Dgrails.env=prod war mytri.war
這將創建一個名為 mytri.war 的文件。現在,需要使用 Tomcat 的管理接口在新觸發 的 AMI 上加載應用程序。或者,您也可以將 mytri.war scp 到目標 AMI。選擇權在您手 中;在這裡,我傾向於使用 Tomcat 的接口,因為 Tomcat 已經在運行中,並且我不必尋 找它在底層文件系統中的路徑。
配置 Tomcat 的管理接口
在使用 Tomcat 的管理接口之前,您必須在 EC2 映像上恰當地啟用它,因為 AMI 已 經被默認配置為禁用此接口(出於安全考慮):
返回到指向 AMI 接口的 shell 會話,並查找位於 /usr/local/tomcat-6.0.20/conf 目錄的 tomcat-users.xml 文件。
打開該文件並添加一個名為 manager 的新角色。
創建一個新用戶(或使用現有用戶)並確保該用戶具有 manager 角色。
重啟 Tomcat。您可以通過 Eclipse 控制台重啟您的實例,或是返回到 /usr/local/tomcat-6.0.20/bin 目錄並先後運行停止腳本和啟動腳本 — 由您決定。
返回到 Eclipse EC2 Instances 視圖,右鍵單擊實例,然後選擇 Copy Public DNS Name。然後將名稱粘帖到浏覽器的位置框。您應該會看到一個可愛的 Tomcat 歡迎屏幕 — 如果沒有的話,等待幾分鐘然後重試,因為網絡可能需要幾分鐘的時間才能作出響應 。
加載完頁面後,單擊左側菜單的 Tomcat Manager 鏈接。您將被要求輸入用戶名和密 碼。輸入您此前配置的用戶名和密碼。一旦加載管理接口,下翻到 War 文件以部署表單 ,單擊 Browse 按鈕,尋找 mytri.war。最後,單擊 Deploy 按鈕。這是一個龐大的 WAR 文件,因此如果部署時間過長的話,不要對此感到擔心。
上傳完成後,您應當會看到 mytri 應用程序已列出在 Applications 部分中。單擊 mytri 應用程序鏈接。您應當有一種似曾相識 的感覺,因為它看上去極像 圖 2 的屏幕 。從這裡開始,您應當能夠創建新的 triathlon — 只是這一次,它們位於 Internet 某 個位置中的 EC2 實例上的 MySQL 中。是不是很簡單?
當您覺得一切都很滿意時,不要忘記關閉 AMI。記住,Amazon 是按小時收費的(盡管 費用不是很多)。您可以在 Eclipse 的 EC2 Instances 視圖中右鍵單擊實例來終止 AMI 。關閉 AMI 將清除所有內容 — 也就是說,您必須重新設置 MySQL 數據庫,比如,您需 要再一次處理 triathlon。(另一個 Amazon 服務 Elastic Block Storage,通過允許將 數據暫時保存到活動 AMI 實例中,使這些數據能夠長期保存下來。)
結束語
您再一次看到了 Java 開發 2.0 的幾個方面在 EC2 中體現出來:您可以在借來的基 礎設施上充分地利用開源包,比如 MySQL、Tomcat 和 Grails(在內部使用 Spring 和 Hibernate),這樣做的成本要遠遠低於親自購買硬件資源。此外,EC2 的設置非常高效 ,並且大大擴展了您使用自己的硬件在相同成本的條件下可以完成的功能。事實上,如果 您曾經覺得自己無法實現本文介紹的這麼多功能,那就對了!
下一個月,我將帶您了解 CouchDB,一個面向文檔的 數據庫,這是一個完全不同於 MySQL 的數據庫。您將了解到為什麼有些人將之稱為未來數據庫。