Shale 不是什么?Shale 不是打包好的、有編制好的文檔并經(jīng)過嚴(yán)格測(cè)試的產(chǎn)品,也沒有附帶自動(dòng)安裝程序和優(yōu)雅的管理界面。那么 Shale 到底是什么呢?Brett McLaughlin 在本文中將揭開這個(gè) Struts 后代的面紗。在本文中,Brett 解釋了 Shale 是什么,Shale 與 Struts 框架的不同之處,以及如何在開發(fā)環(huán)境中安裝和設(shè)置它。
在過去 5 年間出現(xiàn)的所有 Web 框架中,Jakarta Struts 是 Java™ 開發(fā)人員使用得最多的一種框架,因此其后代的問世是一件值得注意的事情。雖然 Shale 還不是最流行的框架,也不是最為人熟悉的框架,但是出自名門的背景仍給人以深刻印象。更令人興奮的是,Shale 并不僅僅是 Struts 的重大升級(jí)和新的發(fā)行版:它徹底更新了 Struts 中的很多核心原則,并且加入了 Web 開發(fā)中最新的思想。
您將了解到,Shale 與 Struts 的背離是一柄雙刃劍。一方面,Shale 是經(jīng)過精心設(shè)計(jì)的 Struts 的后代。Shale 的創(chuàng)立者綜合考慮了 Struts 的優(yōu)點(diǎn)和不足,提出可與其前輩媲美的下一代框架。另一方面,正如您很快就可以在這個(gè)系列中看到的一樣,Shale 是 一種完全不同于 Struts 的框架,其中隱含著很多新的開發(fā)工作!
Shale 不僅僅是 Struts 的又一個(gè)修正版,它已擴(kuò)展到超出 Struts 所能達(dá)到的高度。它包含 Java Web 程序設(shè)計(jì)中一些最重要的、最近的開發(fā)成果,包括 JSP Standard Tag Library(JSTL)和 JavaServer Faces(JSF),并建立在這些開發(fā)成果之上。Shale 完全應(yīng)該被看作是與 Struts 不同的一種框架,在這個(gè)系列中,我將還 Shale 框架以本來面目。在這個(gè)月的文章中,將首先對(duì) Shale 與 Struts 之間的區(qū)別作一個(gè)概述,然后帶您體驗(yàn)安裝 Shale 并測(cè)試安裝情況的步驟。最后,我將給出一些思想,令您能進(jìn)一步參與到 Shale 項(xiàng)目(它是開放源碼的)中,并提供一些相關(guān)的信息。整個(gè)系列的目的就是要向您展示如何安裝 Shale 以及如何使用 Shale 構(gòu)建和開發(fā)項(xiàng)目,同時(shí)很少涉及 Shale 的前輩,即 Struts 框架。
評(píng)價(jià) Shale
任何新的 Web 開發(fā)框架要想在這個(gè)競(jìng)爭(zhēng)已經(jīng)很激烈的領(lǐng)域占得一席之地,最好能夠經(jīng)受住巨大壓力下的評(píng)測(cè)。好消息是,Shale 獨(dú)力經(jīng)受住了細(xì)致的考察。但是,壞消息是,由于 Shale 完全是對(duì) Struts 重新構(gòu)建的產(chǎn)物,因此必須重新編寫和重新測(cè)試您所有基于 Struts 的代碼,以便實(shí)現(xiàn)這些代碼。您將花同樣多的精力來編寫一個(gè)新的 Shale 應(yīng)用程序,或?qū)⒁粋€(gè) Struts 應(yīng)用程序轉(zhuǎn)換成 Shale 應(yīng)用程序,就好像 Shale 與 Struts 完全無關(guān)一樣。
所以接下來我們?nèi)滩蛔∫獑?,為什么還要采用 Shale 呢?為了得出答案,我首先解釋一下 Shale 的偉大之處 ?? 這在很大程度上是由于它的 Struts 血統(tǒng),但這又不是惟一的原因 ?? 然后討論 Shale 之所以沒有 被發(fā)布為 Struts 框架的重要修正版的兩大原因。這樣,您就會(huì)更好地理解從 Shale 身上可以得到什么,這將有助于評(píng)價(jià)使用這種下一代的框架是否值得。
Struts 血統(tǒng)
Shale 重用了大量的 Struts 代碼基,并聲稱 Struts 是它的 “父” 框架,因此如果您要相信 Shale 的價(jià)值,就得相信 Struts 的價(jià)值。首先,Struts 作為第一個(gè)真正意義上的 Web 開發(fā)框架,擁有巨大的價(jià)值。據(jù) Shale 和 Struts 網(wǎng)站報(bào)道,第一批代碼是在 2000 年 6 月提交給 Struts CVS 存儲(chǔ)庫(kù)的,而Struts 1.0 是在 2001 年末才發(fā)布的。當(dāng)很多開發(fā)人員正在艱難地使用 JavaServer Pages(JSP)和不斷變化的 servlet 規(guī)范時(shí),Struts 提供了一種易于使用的 Model 2 方法來構(gòu)建基于 servlet 和 JSP 的 Web 應(yīng)用程序。換句話說,Struts 使 Web 開發(fā)人員可以開發(fā)健壯的 Web 應(yīng)用程序,而不必精于日志記錄、分布式計(jì)算、JDBC、Servlet、JSP、JNDI、RMI 和 大量其他的 API 和技術(shù)。
接下來,Struts 要做的事情就是保持它的強(qiáng)大性:從寫出第一批代碼開始,Struts 連續(xù) 6 年一直是最流行的 Web 開發(fā)框架之一。至今它仍然是人們口中的談資,筆下的素材,使用得不比任何競(jìng)爭(zhēng)對(duì)手少。由于 Struts 是如此流行,如此長(zhǎng)壽,如今它已經(jīng)有豐富的功能,有良好的文檔,被廣泛地支持,并且易于使用,在它上面進(jìn)行開發(fā)和管理也很容易。數(shù)千名開發(fā)人員對(duì) Struts 郵件列表上的問題作出答復(fù),數(shù)萬名開發(fā)人員試用 Struts 并報(bào)告問題,這使得這些問題很容易得到修復(fù)。
最后,Struts 是不斷發(fā)展的。很多框架一開始比較強(qiáng)大,然后就停滯不前(商業(yè)產(chǎn)品和開放源碼項(xiàng)目都存在這樣的現(xiàn)象),而 Struts 總是不斷提供新的特性。當(dāng)您下載 Struts 時(shí),核心發(fā)行版中還包含一個(gè)健壯的確認(rèn)引擎(validation engine),并且 Struts 已經(jīng)與 JavaServer Faces 集成,擁有廣泛的標(biāo)記庫(kù)和一個(gè)不斷發(fā)展的 Model 2 架構(gòu),其中引入了在分布式 n-層應(yīng)用程序領(lǐng)域中最新的思想。而且告訴您,Struts 還緊跟程序設(shè)計(jì)中出現(xiàn)的新模式,例如 IoC(Inversion of Control)。Struts 與 WebWork 和 Spring 框架自然地集成,后兩者都是具有最佳血統(tǒng)的、為使用 Web 開發(fā)中的新方法提供入口的框架。
簡(jiǎn)而言之,您很難發(fā)現(xiàn)在 Struts 中有做不成 或不支持的事。所以顯然我們就要問,為什么 Shale 要另起爐灶呢?為什么 Shale 沒有成為 Struts 的下一個(gè)版本呢?這有兩個(gè)主要原因:一個(gè)原因與鮮為人知的新軟件發(fā)行慣例有關(guān),另一個(gè)原因則與眾所周知的 Struts 根基中的弱點(diǎn)有關(guān)。讓我們分別來考慮這兩個(gè)原因。
發(fā)行版辨析
要理解 Shale 為什么沒有成為 Struts 的一個(gè)新的發(fā)行版,首先需要理解關(guān)于新軟件發(fā)行的一兩件事。對(duì)于一個(gè)新的軟件發(fā)行版,大多數(shù)用戶首先看的是一組新的特性。版本升級(jí)的幅度越大,用戶對(duì)新特性的期待就越大。因此,如果軟件版本從 2.1 升級(jí)到 2.2,就應(yīng)該有一些新的特性,但是如果從版本 2.2 升級(jí)到版本 3.0,那么就應(yīng)該有很多 新特性。這就是為什么當(dāng)一些大型產(chǎn)品(例如 Microsoft Word)或操作系統(tǒng)(例如 Windows 和 Mac OS X )出了新版本的時(shí)候,用戶總是對(duì)它們很挑剔。對(duì)于每一個(gè)新的發(fā)行版,用戶總是期待有更多新的特性。
由于大多數(shù)用戶一味地將注意力放在特性上,他們沒有意識(shí)到向后兼容性(backward compatibility)才是真正最有價(jià)值的東西。雖然每個(gè)人都希望 Excel 中加入新的、很好的選項(xiàng),希望 Panther 與 iTunes 有更好的集成,希望 Gnome 中對(duì) XUL 有更好的支持,但是如果那些用戶現(xiàn)有的程序和文件在新版本下突然不能運(yùn)行的話,相信他們會(huì)尖叫,“這是血腥謀殺”。在這種情況下,新特性毫無價(jià)值。
對(duì)于 Struts 也一樣。一般來說,Struts 的每個(gè)新版本都增加了新的特性,同時(shí)保持了與之前版本的向后兼容性。此外,新版本的 Struts 還需要支持舊版本的 Java 平臺(tái)和 Servlet 規(guī)范,因?yàn)橐寻惭b的舊的 Struts 要在這些平臺(tái)上運(yùn)行。這兩個(gè)需求 ?? 向后兼容性和對(duì)舊版本的 Java API 的支持 ?? 對(duì)于 Shale 來說已經(jīng)是一個(gè)嚴(yán)重的約束。尤其是,至少就 Java 平臺(tái)而言,JSF API 已經(jīng)成為 Web 的中心組件。雖然 Struts 也支持 JSF,但是 Shale 卻是完全依賴于 JSF 的 ?? 這對(duì)于需要維持向后兼容性的 Struts 來說簡(jiǎn)直是不可能的。
最后,派生出一個(gè)像 Shale 這樣的新項(xiàng)目,同時(shí)繼續(xù)在 Struts 這種已有的項(xiàng)目上進(jìn)行開發(fā)活動(dòng),這樣做具有無與倫比的優(yōu)勢(shì)。如果 Struts 只是簡(jiǎn)單地升級(jí)到 2.0(或者 3.0 或 4.0),并在不考慮向后兼容性的情況下實(shí)現(xiàn) Shale,那么對(duì)于很多人來說,由此造成的移植工作將是令人痛苦的,可能有人干脆連 Struts 也不再使用了。即使仍然維護(hù)更舊的代碼基,也難于吸引開發(fā)人員花時(shí)間來修復(fù) bug,他們也不愿意為一個(gè) “遭到廢棄” 的或者 “舊” 版本的軟件增加特性。
由于這些原因,讓 Shale 成為一個(gè)全新的項(xiàng)目,使其建立在一個(gè)新的代碼基之上,是很有意義的。
Shale 的面向服務(wù)架構(gòu)
Shale 之所以沒有成為 Struts 的一個(gè)新的發(fā)行版,其最后一個(gè)原因與邏輯沒有關(guān)系:而是與該框架將新方法接納到 Web 開發(fā)中的能力有關(guān)系。Shale 在很多方面與 Struts 存在不同之處,其中有兩點(diǎn)最為突出:
Struts 與 JSF 集成,而 Shale 則是建立在 JSF 之上。
Struts 實(shí)質(zhì)上是一個(gè)巨大的、復(fù)雜的請(qǐng)求處理器;而 Shale 則是一組可以以任何方式進(jìn)行組合的服務(wù)。
Shale 對(duì) JSF 的依賴性具有深遠(yuǎn)的、令人驚訝的意義,而且大部分情況下是積極的意義。隨著這個(gè)系列的深入,我將深入研究這些意義。在討論其他方面之前,有必要對(duì)造成 Shale 與 Struts 之間差異的第二個(gè)方面進(jìn)行詳細(xì)的討論。
如果您多次使用過 Struts,那么會(huì)意識(shí)到它很大程度上可以看作一個(gè)請(qǐng)求處理器,通過它可以接受請(qǐng)求,并指示框架如何處理請(qǐng)求。您可以指出采取哪種動(dòng)作,使用什么模型,將哪種視圖顯示給用戶,采用什么驗(yàn)證規(guī)則,顯示哪種表單 ... Struts 是完全可以配置的。然而,所有這些的核心是一個(gè)請(qǐng)求處理器,為每個(gè)請(qǐng)求提供服務(wù)。這樣的處理器是 Struts 中最重要、也是最復(fù)雜的部分,因?yàn)閷?duì)于在處理一個(gè)請(qǐng)求的過程中涉及的所有工作,它都必須進(jìn)行處理或托管,在 Struts 代碼基中幾乎沒有哪一部分與這個(gè)請(qǐng)求處理器沒有關(guān)系或不受它的影響。
因此,Struts 基本上難于作出改變。如果想修改處理請(qǐng)求的方式,或改變處理請(qǐng)求過程中各部分的順序,那么將面臨巨大的困難。實(shí)際上,不得不重新編寫 Struts 代碼基。更改請(qǐng)求處理器的行為倒是稍微可行,但是大部分是不容變動(dòng)的。這是 Shale 試圖解決的關(guān)鍵問題之一(如果您需要 Web 框架有那種程度的靈活性的話)。
Shale 沒有像 Struts 請(qǐng)求處理器那樣的中心組件,它只是一組數(shù)量很多的服務(wù)??梢宰杂山M合這些服務(wù),每個(gè)服務(wù)與其他服務(wù)之間是松散耦合的。通過一組良好定義的接口(有時(shí)候?qū)嶋H上就是 Java 接口類,有時(shí)候只是組件之間某種形式的契約),配置 Shale 的行為很容易。這使得 Shale 是可擴(kuò)展的、靈活的,甚至是 “聰明的”。很容易更改它,不費(fèi)吹灰之力就可以擴(kuò)展它,并可以使它迅速適應(yīng)新的編程方法。像這樣松散地組裝組件或服務(wù)通常被稱作面向服務(wù)的架構(gòu),或簡(jiǎn)稱 SOA。當(dāng)然,這聽起來有點(diǎn)兒玄乎,不過您大可不必因此而覺得 Shale 不好!
安裝 Shale
可以從邏輯上和概念上理解 Shale 與 Struts 的不同之處,但是要想在腦海里弄清楚這兩種偉大的框架有什么不同,則需要親自動(dòng)手去實(shí)踐一番。很自然,每一種 Web 框架首先都需要下載和安裝。不過幸好,在這個(gè)過程中通常可以了解到很多東西。那些安裝和設(shè)置起來比較困難的項(xiàng)目和產(chǎn)品,通常也難于配置,難于在它上面進(jìn)行部署,并且(最壞的情況)難于長(zhǎng)久運(yùn)行。雖然安裝過程很難作為評(píng)價(jià)一個(gè) Web 框架好壞的最可靠手段,但是至少肯定應(yīng)該成為這個(gè)標(biāo)準(zhǔn)的一部分。在這一節(jié)中,您將學(xué)習(xí)手動(dòng)地安裝 Shale,對(duì)于一些難點(diǎn)有一定的體會(huì),并了解為了使 Shale 運(yùn)行,系統(tǒng)上需要些什么東西。
注意,我還提到了 Shale 的 簡(jiǎn)便安裝 選項(xiàng),但是我強(qiáng)烈建議您至少試一試手動(dòng)安裝,了解它提供的較深層的信息。
先決條件
Shale 的先決條件和需求相當(dāng)多。和大多數(shù)與 Apache 和 Jakarta 相關(guān)的項(xiàng)目一樣,Shale 的安裝要依賴于一些其他的 Jakarta 項(xiàng)目。下面是為了使 Shale 得以運(yùn)行所需的所有東西的完整列表:
Java Runtime Environment(JRE)和 Java Development Kit(JDK) 1.4 或更高版本
Java Servlet API 2.4 或更高版本
JSP 2.0 或更高版本
JSF 1.1 或更高版本
JSP Standard Tag Library(JSTL) 1.1 或更高版本
Jakarta Commons BeanUtils 1.7 或更高版本
Jakarta Commons Chain 1.0 或更高版本
Jakarta Commons Digester 1.7 或更高版本
Apache Logging 1.0.4 或更高版本
Apache Ant 1.6.3 或更高版本
Apache Ant 只是在構(gòu)建 Shale 時(shí)要用到,但是無論如何,如果您要進(jìn)行較多的 Java 開發(fā),那么系統(tǒng)上還是需要(很可能已經(jīng)有了)一個(gè)版本的 Ant。如果想跟蹤 Shale 中的 bug,那么需要 FindBugs 0.8.5 或更高版本和 JUnit 3.8.1 或更高版本。由于在第 1 部分中我只是討論 Shale 的安裝和使用,因此您還不必關(guān)心 FindBugs 或 JUnit,除非您想早點(diǎn)兒裝上這兩個(gè)項(xiàng)目。
附件和它們的依賴項(xiàng)
和 Struts 一樣,Shale 還有一些附件(在 Shale 中常被稱作可選 Shale 組件),這些附件各自又有其依賴項(xiàng):
Jakarta Commons Validator 1.2 或更高版本
Spring Framework 1.2.2 或更高版本
Struts Tiles Framework(獨(dú)立版本)
如果說這份列表顯得有些長(zhǎng)并且令人生畏的話,那么沒錯(cuò)!Shale 使用大量較低級(jí)的庫(kù)、helper 類、實(shí)用程序組件和來自其他項(xiàng)目的類。如果必須逐個(gè)安裝這些組件,配置 Shale 使用它們,并將所有這些組件組裝成可以部署的某種形式的話,即使是最專業(yè)的開發(fā)人員也會(huì)對(duì) Shale 望而生畏。此外,由于 Shale 在它的開發(fā)圈子內(nèi)仍然相當(dāng)年輕,對(duì)于這些依賴項(xiàng)的獲得和配置仍然有些稚嫩;然而,Shale 確實(shí)是非??尚械?,而且不需要花費(fèi)您想象中那么多的精力。
首先,如果您正在用某種框架從事某種 Web 開發(fā),那么應(yīng)該已經(jīng)有了一些作為依賴項(xiàng)的項(xiàng)目。所以這份列表比它初看上去要容易管理得多。例如,任何 Web 開發(fā)人員都應(yīng)該已經(jīng)有 JRE 和 JDK,也應(yīng)該有一個(gè) servlet 引擎,例如 Jakarta Tomcat。如果已經(jīng)有一個(gè) servlet 引擎,那么也應(yīng)該有 Servlet API 和 JSP 引擎。另外,大部分 servlet 引擎(至少就當(dāng)前版本而言)都包括一個(gè) JSTL,并且很多都附帶了 JSF。最后,大多數(shù)開發(fā)人員很可能在他們的機(jī)器上已經(jīng)安裝了 Ant。因此,這份列表很快就只剩下這些了:
JSF 1.1 或更高版本 (servlet 引擎中可能已經(jīng)附帶了)
JSTL 1.1 或更高版本 (servlet 引擎中可能已經(jīng)附帶了)
Jakarta Commons BeanUtils 1.7 或更高版本
Jakarta Commons Chain 1.0 或更高版本
Jakarta Commons Digester 1.7 或更高版本
Apache Logging 1.0.4 或更高版本
考慮到 Tapestry 實(shí)際上提供了將它的所有依賴項(xiàng)附帶下載的選項(xiàng),因此 “太多依賴項(xiàng)” 的問題很快就不成為問題了。
現(xiàn)在您已經(jīng)知道了大概,現(xiàn)在我們來看看下載、安裝和配置 Shale 及其依賴項(xiàng)的步驟。
1. 下載 Shale
要下載 Shale,可訪問 Shale 項(xiàng)目主頁(yè)。您可以看到一個(gè) “Shale Download” 區(qū)域,其中有 Shale 框架的每晚構(gòu)建的鏈接。單擊這個(gè)鏈接,便可以進(jìn)入如圖 1 所示的一個(gè)站點(diǎn):
圖 1. 來自 Shale CVS 存儲(chǔ)庫(kù)的每晚構(gòu)建
為了使 Shale 運(yùn)行,需要下載 “framework” 文件和 “dependencies” 文件。例如,在撰寫本文時(shí)我下載了以下兩個(gè)文件:
shale-framework-20060204.zip
shale-dependencies-20060204.zip
當(dāng)然,如果您需要或者更愿意下載 .tar.gz 版本,那么可以不選擇 .zip 版本,而選擇 .tar.gz 版本。由于 Shale 的開發(fā)還在進(jìn)行中,目前還沒有發(fā)行的構(gòu)建,因此您應(yīng)該盡量下載最近的每晚構(gòu)建(具有最近的日期)。
下載完這兩個(gè)文件后,首先解壓這兩個(gè)歸檔文件。對(duì)于核心框架,解壓后可以得到一個(gè)具有形如 shale-framework-20060204/ 的名稱的文件夾;對(duì)于 dependencies 歸檔文件,解壓后可以得到一個(gè)名為 lib/ 的文件夾。將核心框架目錄 shale-framework-20060204/ 轉(zhuǎn)移到您希望保存 Java 項(xiàng)目的地方。例如,在我的系統(tǒng)上,我將 shale-framework-20060204/ 移動(dòng)到 /usr/local/java 目錄中。接下來,將 lib/ 目錄移動(dòng)到 Shale 目錄中,所以最后的目錄結(jié)構(gòu)與 shale-framework-20060204/lib/ 類似。
2. 添加 Shale 庫(kù)到 Web 應(yīng)用程序中
下一步是將所有 Shale JAR 文件和庫(kù)添加到 Web 應(yīng)用程序可以訪問和使用它們的位置。步驟如下:
1. 如果在 servlet 引擎中沒有包含 JSF,那么將 shale-framework-20060204/lib/jsf-ri/jsf-api.jar 和 shale-framework-20060204/lib/jsf-ri/jsf-impl.jar 復(fù)制到應(yīng)用程序的 WEB-INF/lib 目錄中。
2. 將 shale-core.jar、shale-clay.jar、shale-tiles.jar 和 tiles-core.jar 從 shale-framework-20060204/dist/ 目錄復(fù)制到 Web 應(yīng)用程序的 WEB-INF/lib 目錄。
3. 將以下 Shale 依賴項(xiàng)復(fù)制到 Web 應(yīng)用程序的 WEB-INF/lib 目錄:
o shale-framework-20060204/lib/commons-beanutils/commons-beanutils.jar
o shale-framework-20060204/lib/commons-chain/commons-chain.jar
o shale-framework-20060204/lib/commons-digester/commons-digester.jar
o shale-framework-20060204/lib/commons-logging/commons-logging.jar
o shale-framework-20060204/lib/commons-validator/commons-validator.jar
4. 如果要使用 Shale 的 Spring 集成特性,那么將 shale-spring.jar 從 shale-framework-20060204/dist/ 復(fù)制到 Web 應(yīng)用程序的 WEB-INF/ 目錄。要完成這個(gè)步驟,還必須確保 Spring 的打包 JAR 文件也在 Web 應(yīng)用程序的 WEB-INF/lib 目錄中。這個(gè) JAR 文件名為 spring.jar,如果您還沒有這個(gè)文件的話,可以在 shale-framework-20060204/lib/shaleframework/ 目錄中找到它。
5. 如果正在使用 Java 5.0,那么將 shale-tiger.jar 從 shale-framework-20060204/dist/ 復(fù)制到 Web 應(yīng)用程序 的 WEB-INF/lib 目錄中。只有在使用 Java 5.0 的時(shí)候才需要執(zhí)行這一步;否則,servlet 引擎和使用 Shale 的 Web 應(yīng)用程序就會(huì)出問題。
再往后走就開始復(fù)雜起來(是的,這些復(fù)制操作是較容易的一部分)。接下來的事情未必都要用最難的方式去做,至少我應(yīng)該讓您有機(jī)會(huì)選擇 試試容易的方法。使 Shale 在系統(tǒng)上運(yùn)行這個(gè)任務(wù)的確存在捷徑;您已經(jīng)知道手動(dòng)設(shè)置 Shale 的過程比較復(fù)雜,接下來有必要看看 “簡(jiǎn)便” 方法。
更容易的方法
重新訪問 Shale 下載站點(diǎn),并下載名稱類似于 shale-starter-20060204.zip 的 “starter” 應(yīng)用程序。解壓這個(gè)歸檔文件,將得到一個(gè)名為 shale-starter/ 的目錄。這是一個(gè)基本上配置好的 Shale Web 應(yīng)用程序,用于幫助避免前一節(jié)詳細(xì)介紹的復(fù)制和配置工作。首先要做的是將 shale-starter/ 目錄重新命名成應(yīng)用程序以后要使用的名稱,例如可以將它命名為 first-shale/。進(jìn)入 first-shale/ 目錄,在這里可以看到一些文件和子目錄。
在 first-shale/ 目錄中,創(chuàng)建一個(gè)名為 build.properties 的新文件。通過這個(gè)文件可以定制如何構(gòu)建 Shale starter 應(yīng)用程序,并確保該應(yīng)用程序適合您的環(huán)境設(shè)置。清單 1 展示了一個(gè)基本的 build.properties 文件,可以根據(jù)自己的環(huán)境對(duì)其進(jìn)行定制。
清單 1. Shale starter 應(yīng)用程序的示例 build.properties
# Basic project information
project.copyright=My project, Copyright ? 2006
project.name=My First Shale Application
project.vendor=IBM DeveloperWorks
project.vendor.id=com.ibm.dw
# Java package and context path for servlet engine
project.package=com.ibm.dw.firstShale
project.path=first-shale
# Directory for Shale distribution - change this for your system
shale.dir=/usr/local/java/shale-framework-20060204
# Directory for all your libraries - change this for your system
lib.dir=/usr/local/java/shale-framework-20060204/lib
根據(jù)系統(tǒng)設(shè)置好這些屬性后,便可以運(yùn)行 ant。Shale starter 應(yīng)用程序開始構(gòu)建 并(假設(shè)已經(jīng)正確地設(shè)置了路徑)創(chuàng)建一個(gè)示例應(yīng)用程序。如果有問題,則構(gòu)建腳本輸出錯(cuò)誤消息;這些錯(cuò)誤消息都描述得很清楚,所以您應(yīng)該可以更正任何錯(cuò)誤。
構(gòu)建過程的最后將生成一個(gè)名為 target/ 的新目錄。進(jìn)入這個(gè)目錄,可以看到一個(gè)名為 first-app(即您在 build.properties 中為項(xiàng)目指定的名稱)的子目錄。大多數(shù) servlet 引擎都允許將這個(gè)目錄整個(gè)地復(fù)制到 servlet 引擎的 webapps/ 目錄。例如,我使用的是 Tomcat,于是我將構(gòu)建腳本創(chuàng)建的整個(gè) first-shale 目錄復(fù)制到 /usr/local/java/tomcat/webapps。
構(gòu)建 WAR 文件
如果使用的 servlet 引擎要求提供 WAR 文件,那么可以使用相同的 Shale starter 應(yīng)用程序的構(gòu)建文件,只需略微修改一下。由于還沒有為這個(gè) Shale 應(yīng)用程序編寫任何 Java 文件,當(dāng)您請(qǐng)求一個(gè) WAR 文件時(shí),構(gòu)建腳本將出現(xiàn)錯(cuò)誤(在 build.xml 中有查找文件的 JavaScript 命令,但是沒有找到任何文件)。為了修復(fù)這個(gè)問題,打開 build.xml 文件,找到以 “javadoc” 開頭且如下所示的代碼:
description="Create JavaDocs">
sourcepath="${src.java.dir}"
destdir="${build.docs.dir}"
author="false"
private="true"
version="true"
source="${project.source}"
packagenames="${project.package}.*"
windowtitle="${project.name} (Version ${project.version})"
doctitle="${project.name} (Version ${project.version})"
bottom="${project.copyright}">
includes="**/*.gif"/>
現(xiàn)在,注釋掉 javadoc 任務(wù),如下所示:
description="Create JavaDocs">
<
sourcepath="${src.java.dir}"
destdir="${build.docs.dir}"
author="false"
private="true"
version="true"
source="${project.source}"
packagenames="${project.package}.*"
windowtitle="${project.name} (Version ${project.version})"
doctitle="${project.name} (Version ${project.version})"
bottom="${project.copyright}">
-->
includes="**/*.gif"/>
一旦開始為 Shale 應(yīng)用程序開發(fā) Java 代碼,便不必這樣做。不過對(duì)于現(xiàn)在,這樣做可以解決上述問題。保存修改后的 build.xml 并運(yùn)行 ant dist。Ant 編譯和裝配 starter 應(yīng)用程序,并在 dist/ 目錄中創(chuàng)建一個(gè)新的 WAR 文件。例如,我運(yùn)行 ant dist 后得到一個(gè) dist/first-shale-0.1.war 文件?,F(xiàn)在可以將這個(gè) WAR 文件復(fù)制到 servlet 引擎的 webapps/ 目錄。
測(cè)試安裝情況
如果完成了以上步驟,不管選擇的安裝路徑是什么,都應(yīng)該可以啟動(dòng) servlet 引擎并通過地址
http://your.host.name/first-shale 訪問 Shale 應(yīng)用程序。例如,如果在本地機(jī)器上運(yùn)行 Tomcat,那么最終可以訪問的地址是
http://localhost:8080/first-shale。如果一切正常,那么應(yīng)該可以看到如圖 2 所示的簡(jiǎn)單頁(yè)面:
圖 2. Shale starter 應(yīng)用程序證明一切沒問題
看起來似乎做了這么多工作卻所得甚少,但是要考慮到,通過打開并編輯一個(gè)簡(jiǎn)單的 build.properties 文件,可以避免大量繁雜的復(fù)制和配置工作。您將發(fā)現(xiàn),從空白的 Shale starter 應(yīng)用程序開始總是開發(fā)新的 Shale 應(yīng)用程序最容易的方式。實(shí)際上,當(dāng)在下一篇文章中開始開發(fā) Shale 應(yīng)用程序的時(shí)候,將使用空白的 starter 應(yīng)用程序作為開始的基礎(chǔ)。
Shale 用例
關(guān)于 Shale 的下載和安裝就介紹到這里,不過我們還是再花點(diǎn)兒時(shí)間從 Shale 主下載站點(diǎn)下載 Shale 的用例 WAR 應(yīng)用程序。找到一個(gè)文件名形如 shale-usecases-20060204.war 的文件。下載該文件,并將它放入 servlet 引擎的 webapps/ 目錄,然后進(jìn)入到這個(gè) WAR。在我的系統(tǒng)上,訪問
http://localhost:8080/shale-usecases-20060204/ 并得到如圖 3 所示的屏幕:
圖 3. Shale 用例應(yīng)用程序
您應(yīng)該花些時(shí)間來看看這個(gè)用例應(yīng)用程序。它有關(guān)于 Shale 中 Validator 和遠(yuǎn)程報(bào)告等特性的很好的演示,并有一個(gè)簡(jiǎn)單的 Ajax 應(yīng)用程序。通過瀏覽這些用例,您可以了解到即使是簡(jiǎn)單的 Shale 應(yīng)用程序也可以做許多事情。
不過這里要提一個(gè)忠告:有些用例仍在開發(fā)中,取決于您何時(shí)下載每晚構(gòu)建,可能發(fā)現(xiàn)有些用例不能正常工作。不過總是可以晚些時(shí)候再下載這些用例應(yīng)用程序,看看有些問題是否已經(jīng)被修復(fù)。雖然存在這些小問題,但是用例應(yīng)用程序仍然是取得對(duì) Shale 的基本印象的一種好途徑。
深入研究 Shale!
大多數(shù) Web 開發(fā)人員向來只是使用已有的框架(例如 Shale、Struts 或 Spring)來開發(fā)他們的 Web 應(yīng)用程序,而沒有做別的事情。當(dāng)然這沒有什么錯(cuò),但是如果想理解一種框架以及它所涉及的技術(shù),那么只能對(duì)框架本身做深入的研究。
對(duì)于 Shale(當(dāng)然也包括 Struts),通過查看框架的內(nèi)部,您可以學(xué)到大量關(guān)于 servlet 和 Web 開發(fā)的知識(shí)。如果想在自己的項(xiàng)目中使用一些 Shale 依賴項(xiàng),這樣做還可以獲得難以置信的幫助。如果您對(duì)通過 Java 應(yīng)用程序進(jìn)行日志管理感興趣,那么通過 Shale 來熟悉 Apache Logging 項(xiàng)目比閱讀任何文章都要有效得多。對(duì)于 Jakarta Commons BeanUtils、Chain 或 Digester 項(xiàng)目也是一樣。這些都是很好的工具,對(duì)于開發(fā)人員很有用,所以花幾個(gè)星期或幾個(gè)月的時(shí)間探索一下 Shale 對(duì)于這些領(lǐng)域是一個(gè)很好的學(xué)習(xí)經(jīng)歷。
由于本文是對(duì) Shale 進(jìn)行深入探討的系列中的第一期,因此如果我不對(duì)幾個(gè)對(duì)于 Shale 項(xiàng)目入門來說至關(guān)重要的方面進(jìn)行討論的話,就是不負(fù)責(zé)任了。
親密接觸源代碼
不幸的是,關(guān)于 Shale 中涉及的開發(fā)過程的文檔并不多,所以如果您想直接使用 Shale 源代碼的話,需要用點(diǎn)兒技巧。一般來說,我這里給出的關(guān)于下載 Shale 并將它作為框架使用的說明也適用于下載 Shale 的源代碼。每晚構(gòu)建包含 Shale 的所有源代碼,并且代碼的每個(gè)目錄中都有一個(gè) build.xml 文件。
需要將下載的 Shale 的根目錄下的 build.properties.sample 文件復(fù)制到一個(gè)名為 build.properties 的文件中(去掉原始文件名尾部的 “.sample”)。清單 2 展示了這個(gè)文件的一個(gè)示例,為了簡(jiǎn)潔起見,這里省略了其中一些注釋:
清單 2. 示例 Shale 構(gòu)建文件
# This file contains example property settings that you would use to customize
# your build environment to build the Struts Shale Library from
# source code. To use this file, make a copy of it in "build.properties" and
# customize the values as required.
# Root directory into which you have unpacked the Shale Framework release.
root.dir=${basedir}
# Fully qualified pathname of the directory into which you have unpacked
# a binary distribution of the JavaServer Faces Reference Implementation
jsfri.dir=/usr/local/jsf-1_1_01
findbugs.outputFile=${root.dir}/find-bugs.html
lib.dir=${root.dir}/lib
jsf.home = ${lib.dir}/myfaces
jsf-api.jar = ${jsf.home}/myfaces-api.jar
jsf-impl.jar = ${jsf.home}/myfaces-impl.jar
# The absolute or relative pathname of the Apache Struts
# distribution
struts.home = /usr/local/jakarta-struts
spring.home=${lib.dir}/springframework
findbugs.home = /usr/local/findbugs-0.8.6
為了與您的系統(tǒng)相匹配,需要更改這個(gè)構(gòu)建文件中大部分的路徑。默認(rèn)情況下,${basedir} 指向運(yùn)行 Ant 時(shí)所在的目錄,因此如果是從下載的 Shale 的根目錄下運(yùn)行 Ant,那么就剛好不用改路徑了。但是對(duì)于其他路徑,應(yīng)該改為適當(dāng)?shù)呐c系統(tǒng)相匹配的路徑。例如,如果您的 JSF 參考實(shí)現(xiàn)在 c:/java/jsf-1_1_02 中,那么使用 jsfri.dir 目錄所在的路徑。大多數(shù)默認(rèn)路徑都適合于使用 MyFaces(請(qǐng)參閱 “MyFaces 還是 JavaServer Faces”),但是當(dāng)然也可以使用 Sun 的 JSF 實(shí)現(xiàn),并對(duì)這些路徑作相應(yīng)的更改。另外還需要設(shè)置 Struts、Spring(這是可選的,對(duì)于核心 Shale 框架來說不必要)和 FindBugs 項(xiàng)目的路徑。
Ant 登場(chǎng)
設(shè)置好這些文件的路徑后,就可以在 Shale 的根目錄中運(yùn)行 Ant。但是,首先應(yīng)該運(yùn)行 ant download-dependencies。您當(dāng)然也已經(jīng)注意到,Shale 有很多 依賴項(xiàng),而通過使用 Ant 自動(dòng)下載這些依賴項(xiàng)可以為您節(jié)省很多時(shí)間,也令您輕松不少。Ant 腳本還負(fù)責(zé)設(shè)置路徑,以便使 Shale 與那些依賴項(xiàng)連接起來。還應(yīng)該運(yùn)行 ant copy-jsf-ri 來處理一些特定于 JSF 的任務(wù)(具體細(xì)節(jié)不必關(guān)心,因?yàn)?nbsp;Ant 會(huì)為您打點(diǎn)一切)。
在構(gòu)建主 Shale 發(fā)行版之前,應(yīng)該運(yùn)行 ant clean 刪除之前已有的構(gòu)建后的代碼。雖然這意味著整個(gè)構(gòu)建時(shí)間會(huì)更長(zhǎng),但是可以確保所有代碼將一致地構(gòu)建。最后,運(yùn)行 ant release,以便從頭開始構(gòu)建 Shale。當(dāng)這個(gè) Ant 腳本運(yùn)行完成后(這要花一點(diǎn)兒時(shí)間),就可以得到一個(gè)完整的、從源代碼構(gòu)建的 Shale 發(fā)行版。
關(guān)于郵件列表的只言片語
開發(fā)源碼項(xiàng)目幾乎完全是通過電子郵件(再加上 Apache bug 跟蹤數(shù)據(jù)庫(kù),在 參考資料 小節(jié)中有這方面的內(nèi)容)來運(yùn)作的。Shale 在這方面也是一樣的,不過它仍然使用 Struts 的郵件列表。如果在使用 Shale 時(shí)有什么疑問,可以發(fā)送電子郵件到 user@struts.apache.org。但是當(dāng)您開始開發(fā)真正的 Shale 內(nèi)部組件時(shí),應(yīng)該將電子郵件發(fā)送到 dev@struts.apache.org。不管將電子郵件發(fā)送到哪里,都應(yīng)該以 “[shale]” 開頭,這樣別人一下子就明白您是要問關(guān)于 Shale 的問題,而不是關(guān)于 Struts 的問題。預(yù)期在幾個(gè)月后,當(dāng) Shale 開始成為獨(dú)立的項(xiàng)目時(shí),它也會(huì)有它自己的郵件列表。
這里稍微提醒一下,尤其是在發(fā)送電子郵件到開發(fā)列表的時(shí)候:做好自己的工作,問題要有的放矢。那些飄忽不定、模棱兩可或缺乏思想的郵件很可能不會(huì)收到回復(fù)。如果您到處發(fā)送 “我想學(xué)習(xí) Shale,請(qǐng)給我發(fā)送一些例子應(yīng)用程序” 之類的郵件,甚至還可能得到粗魯?shù)幕卮?。雖然這種提醒看上去有些傻,但事實(shí)就是這樣。開發(fā)列表中總是充斥著這一類的問題,這些問題都是不受歡迎 的。通常,花點(diǎn)兒時(shí)間認(rèn)真地斟酌您的問題,解釋一下您使用的平臺(tái)和軟件的版本,并說明您已經(jīng)試過了一些常用的步驟。這樣一來,您的請(qǐng)求才會(huì)得到尊重并受到歡迎,也就更容易得到答案。開發(fā)人員的列表并不是令人生畏的,但最起碼這樣做顯得您尊重別人。
結(jié)束語
這個(gè)關(guān)于 Shale 的系列中的第一期文章說明,Shale 并不適合每一個(gè)人。Shale 沒有提供一個(gè)打包好的、有編制好的文檔并經(jīng)過良好測(cè)試的產(chǎn)品,也沒有附帶自動(dòng)安裝程序和優(yōu)雅的管理界面,這些都是很多 Web 開發(fā)人員期待 Tapestry 時(shí)代能提供的東西。雖然在以后版本的框架中會(huì)體現(xiàn)這些東西(除了完全打包),但目前 Shale(從 2006 年初起)仍在開發(fā)過程中,并且 Shale 站點(diǎn)也基本上將它稱為處于 “alpha” 狀態(tài)的項(xiàng)目。Shale 中使用的很多組件是穩(wěn)定和成熟的,但 Shale 本身仍然很年輕。如果您不能接受一些麻煩和困惑,那么可能會(huì)想過一年左右再開始使用它。
另一方面,如果您是一名對(duì) Web 開發(fā)的前沿技術(shù)感興趣的 Java 開發(fā)人員,那么真應(yīng)該看看 Shale 項(xiàng)目。雖然安裝 Shale 并使之工作要花費(fèi)更多的精力,但是它完全有條件成為特別流行的 Web 開發(fā)框架。Shale 繼承了 Struts,同時(shí)也提供了一些全新的東西,這本身就值得作一番調(diào)查。對(duì)于有興趣成為開放源碼項(xiàng)目中的一員的開發(fā)人員,Shale 也是值得投入精力的一個(gè)項(xiàng)目。