用 Groovlet 和 GSP 進行動態(tài)服務(wù)器端編程
級別: 中級 |
首席技術(shù)官, Vanward Technologies
2005 年 3 月
Groovlet 和 GroovyServer Pages(GSP)框架都是建立在 Java Servlet API 基礎(chǔ)之上。不過,與 Strut 和 JSF 不同,Groovy 的服務(wù)器端實現(xiàn)不意味著適用于所有情況。相反,它提供了一種快速而又方便地開發(fā)服務(wù)器端應(yīng)用程序的簡化方法。下面請跟隨 Groovy 的鼓吹者 Andrew Glover,聽聽他如何介紹這些框架,并展示它們的應(yīng)用。
Java 平臺為自己贏得了服務(wù)器端應(yīng)用程序開發(fā)的首選平臺的名聲。Servlet 是服務(wù)器端 Java 技術(shù)的強大支柱,因此有無數(shù)的框架是圍繞著 Servlet API 建立起來的,其中包括 Strut、JavaServer Faces (JSF) 和 Tapestry。您可能已經(jīng)猜到,Groovy 也是以 Servlet API 為基礎(chǔ)建立起來的框架,不過,這個框架的目的是簡化開發(fā)。
Groovlet 和 GroovyServer Pages(GSP)框架的目的是提供一種優(yōu)雅而又簡單的平臺,將它用于構(gòu)建復(fù)雜程度不高的 Web 應(yīng)用程序。就像 GroovySql 不是數(shù)據(jù)庫開發(fā)的惟一選擇一樣,Groovlet 框架也不是 像 Strut 那樣具有更豐富功能的框架的替代品。Groovlet 只是開發(fā)人員尋求容易配置和產(chǎn)生工作代碼的快速方法時的一種選擇。
例如,不久前,我需要 —— 快速地 —— 提供一個 stub 應(yīng)用程序,以測試像 xml-rpc
API 這樣的客戶端。顯然可以用一個 servlet 快速編寫出所需要的功能,但是我從沒想過鉆研 Strut,一秒鐘也沒有。我考慮過使用基本的普通 Java Servlet API 編寫 servlet 及其相關(guān)的邏輯,但是由于需要盡快地使用這項功能,所以我選擇了使用 Groovlet 快速完成它。
很快您就可看到,這種選擇是顯而易見的。
在深入研究使用 Groovlet 進行編程之前,我想簡單介紹一個在示例代碼中會用到的 Groovy 特性。在幾個月前的 alt.lang.jre: 感受 Groovy 一文中,我第一次介紹了 def
關(guān)鍵字。
關(guān)于本系列 |
在腳本中定義函數(shù)
在普通 Java 編程中,方法必須存在于類對象中。事實上,所有行為都必須在類的上下文中定義。不過在 Groovy 中,行為可以在函數(shù) 中定義,而函數(shù)可以在類定義之外定義。
這些函數(shù)可以直接用名稱引用,并且可以在 Groovy 腳本中定義,這樣非常有助于它們的重復(fù)使用。Groovy 函數(shù)需要 def
關(guān)鍵字,可以將關(guān)鍵字想像為在腳本范圍內(nèi)可用的全局靜態(tài)方法。因為 Groovy 是動態(tài)類型的語言,所以 def
不需要對參數(shù)作任何類型聲明,def
也不需要 return
語句。
例如,在清單 1 中,我定義了一個簡單的函數(shù),它將輸出一個集合的內(nèi)容,而不管這個集合是 list
還是 map
。然后我定義一個 list
,填充它,并調(diào)用我新定義的 def
。之后,我創(chuàng)建一個 map
,并對這個集合做了同樣的操作。
|
def
不需要 return
語句,因此如果最后一行產(chǎn)生某個值,那么這個值由 def
返回。例如,在清單 2 中,代碼定義了一個 def
,它返回傳遞進來的變量的名稱。我可以編寫它,讓它帶有或者不帶 return
語句,得到的結(jié)果是相同的。
|
在編寫簡單的腳本時,def
關(guān)鍵字會非常好用。您很快就會看到,在開發(fā) Groovlet 時,這個關(guān)鍵字也會派上用場。
Groovlet 和 GSP
使用 Groovlet 和 GSP 的前提條件相當簡單:需要一個 servlet 容器,以及最新、最偉大版本的 Groovy。這些框架的好處是它們通過一個 web.xml 文件將所選模式的所有 URL 映射到特定的 servlet。因此,建立 Groovlet 和 GSP 的實現(xiàn)的第一步是定義一個 Web 應(yīng)用程序上下文,并更新它的相關(guān) web.xml 文件。這個文件將包括特定的 servlet 類定義以及它們對應(yīng)的 URL 模式。
我將使用 Apache Jakarta Tomcat,并且已創(chuàng)建了一個名為 groove 的上下文。目錄結(jié)構(gòu)如清單 3 所示:
清單 3. groove 上下文的目錄列表
|
在 WEB-INF 目錄中要有一個 web.xml 文件,它至少有一個清單 4 中的元素:
清單 4. 一個完全配置的 web.xml 文件
|
上述 web.xml 文件中的定義聲明了以下內(nèi)容:所有以 .groovy
結(jié)尾的請求(如 http://localhost:8080/groove/hello.groovy
)都將發(fā)送給類 groovy.servlet.GroovyServlet
,而所有以 .gsp
結(jié)尾的請求都將送給類 groovy.servlet.TemplateServlet
。
下一步是將兩個 jar 放到 lib 目錄中:groovy 發(fā)行版本的 jar(在這里是 groovy-1.0-beta-9.jar)和對應(yīng)的 asm
jar (對于 groovy beta-9 來說是 asm-1.5.2.jar)。
瞧,就是這么簡單 —— 我已經(jīng)準備好了。
Groovlet,請出場
編寫 Groovlet 無疑很簡單,因為 Groovy 只有很少的幾個對類繼承擴展的要求。使用 Groovlet 不需要擴展 javax.servlet.http.HttpServlet
、javax.servlet.GenericServlet
或者一些華而不實的 GroovyServlet
類。事實上,創(chuàng)建 Groovlet 就像創(chuàng)建一個 Groovy 腳本一樣簡單。甚至不必創(chuàng)建一個類。在清單 5 中,我編寫了一個簡單的 Groovlet,它做兩件事:打印一些 HTML,然后提供一些關(guān)于它所在的容器的信息。
|
如果在瀏覽器中觀看這個 Groovy,它看起來與圖 1 所示類似。
仔細觀察清單 5 中的 Groovlet,會讓您回想起第一次編寫 Groovy 腳本的時候。首先,沒有 main
方法或者類定義,只有一些簡單的代碼。而且,Groovlet 框架隱式地提供實例變量,比如 ServletRequest
、ServletResponse
、ServletContext
和 HttpSession
。注意我是如何通過 application
變量引用 ServletContext
的實例的。如果想獲得 HttpSession
的實例,那么就要使用 session
變量名。與此類似,可以對 ServletRequest
和 ServletResponse
分別使用 request
和 response
。
一個診斷 Groovlet
編寫 Groovlet 不僅像創(chuàng)建一個 Groovy 腳本那樣簡單,而且還可以用 def
關(guān)鍵字定義函數(shù),并在 Groovlet 中直接調(diào)用它們。為了展示這一點,我將創(chuàng)建一個非凡的 Groovlet,它將對 Web 應(yīng)用程序進行一些診斷。
假設(shè)您編寫了一個 Web 應(yīng)用程序,它被世界上不同的客戶所購買。您有一個大客戶群,并且不斷發(fā)布這個應(yīng)用程序有一段時間了。從過去的支持問題中,您注意到許多急切的客戶電話都與錯誤的 JVM 版本和錯誤的對象關(guān)系映射(ORM)所導(dǎo)致的問題有關(guān)。
您很忙,所以讓我拿出一個解決方案。我用 Groovlet 迅速地 創(chuàng)建了一個簡單的診斷腳本,它將驗證 VM 版本,并試圖創(chuàng)建一個 Hibernate 會話(請參閱參考資料)。我首先創(chuàng)建兩個函數(shù),并在瀏覽器連接腳本時調(diào)用它們。清單 6 定義了這個診斷 Groovlet:
清單 6. 一個診斷 Groovlet
|
這個 Groovlet 的驗證邏輯非常簡單,但是它可以完成這項工作。只要將診斷腳本綁定到 web 應(yīng)用程序即可,當客戶服務(wù)臺收到電話時,它們將指點客戶用瀏覽器訪問 Diagnostics.groovy
腳本,并讓這些腳本報告它們的發(fā)現(xiàn)。結(jié)果可能看起來像圖 2 這樣。
那些 GSP 呢?
到目前為止,我主要關(guān)注于編寫 Groovlet。不過,正如您將會看到的那樣,很容易用 Groovy 的 GSP 頁對 Groovlets 框架進行補充,就像 JSP 補充 Servlet API 一樣。
表面上,GSP 看起來很像 JSP,實際上它們不可能有太大的差別,因為 GSP 框架其實就是一個模板引擎。如果不熟悉模板引擎,那么可能需要快速地回顧一下上月的文章。
雖然 GSP 和 JSP 是根本不同的技術(shù),但是 GSP 是加入表達 Web 應(yīng)用程序的視圖的很好候選人,這一點它們是類似的。您可能會想起來,在上月的文章中,有一項促進視圖的技術(shù)可以將應(yīng)用程序的業(yè)務(wù)邏輯問題與其相應(yīng)的視圖分離。如果快速查看一下清單 6 中的診斷 Groovlet,就可以看出 GSP 代碼改進了哪些地方。
是的,Groovlet 有些簡陋,不是嗎?問題在于它混合了應(yīng)用程序邏輯和大量輸出 HTML 的 println
。幸運的是,可以通過創(chuàng)建一個簡單的 GSP 來補充這個 Groovlet,從而解決這個問題。
示例 GSP
創(chuàng)建 GSP 與創(chuàng)建 Groovlet 一樣容易。GSP 開發(fā)的關(guān)鍵是認識到 GSP 實質(zhì)上是一個模板,因此,它最適合有限的邏輯。我將在清單 7 中創(chuàng)建一個簡單的 GSP 作為開始:
|
觀察上面的 GSP 可能很容易讓您回想起標準 Groovy 模板開發(fā)。像 JSP 一樣,它使用 <%
, 但是,與 Groovlet 框架類似,它允許您訪問常用 servlet 對象,比如 ServletRequest
、ServletResponse
、ServletContext
和 HttpSession
對象。
重構(gòu)應(yīng)用程序 ...
在練習編程語言或者平臺發(fā)展的時候,重構(gòu)老的代碼可以學到很多東西。我將重構(gòu)一月份專欄中的簡單報告應(yīng)用程序,那時候您才剛開始學習 GroovySql。
您還記得嗎,我構(gòu)建了一個快速但不完善的報告應(yīng)用程序,它可以在組織中有多次使用。但結(jié)果是,它變成了研究公司數(shù)據(jù)庫活動的相當流行的應(yīng)用程序。現(xiàn)在,非技術(shù)人員希望可以訪問這個巨大的報告,但是他們不想很費事地在自已的計算機上安裝 Groovy 來運行它。
我多少預(yù)計到了這種情況的發(fā)生,解決方案實際上 是顯而易見的:讓報告應(yīng)用程序支持 Web。很幸運,Groovlet 和 GSP 使重構(gòu)變成小事一樁。
重構(gòu)報告應(yīng)用程序
首先,我將處理 > GroovySql 一文的清單 12 中的簡單應(yīng)用程序。重構(gòu)這個應(yīng)用程序很容易:只要將所有 println
替換成用 setAttribute()
方法,然后將實例變量放入 HttpRequest
對象的邏輯中即可。
下一步是用 RequestDispatcher
將 request
轉(zhuǎn)發(fā)給 GSP,它會處理報告應(yīng)用程序的視圖部分。清單 8 定義了新的報告 Groovlet:
|
清單 8 中的代碼應(yīng)當是您相當熟悉的。我只是將以前應(yīng)用程序中的所有 println
替換掉,并添加了 forward
函數(shù)來處理報告的視圖部分。
添加視圖部分
下一步是創(chuàng)建 GSP 來處理報告應(yīng)用程序的視圖。因為我是工程師而不是一個藝術(shù)家,所以我的視圖是相當簡單的 —— 一些 HTML 加上一個表,如清單 9 所示:
|
運行新的報告應(yīng)當生成如圖 3 所示的輸出,數(shù)字會有變化。
結(jié)束語
如您所見,當所需要的功能相當簡單并且需要盡快完成時,Groovlet 和 GSP 是進行服務(wù)器端開發(fā)的當然之選。這兩個框架都特別靈活,并且其代碼到視圖的轉(zhuǎn)化時間事實上是無可匹敵的。
不過,需要強調(diào)的是,Groovlet 不是 Strut 的替代品。GSP 框架不是直接 在速度上與其他產(chǎn)品競爭。GroovySql 不是 Hibernate 的替代品。而 Groovy 也不是 Java 語言的替代品。
無論如何,這些技術(shù)是補充,在大多數(shù)情況下,Groovy 是快速開發(fā)的更簡單的一種選擇。就像 GroovySql 是直接使用 JDBC 的替代方法一樣,Groovlet 和 GSP 實際上是直接使用 Servlet API 的替代品。
下個月,我將探討 GroovyMarkup 的奇妙世界。
- 您可以參閱本文在 developerWorks 全球站點上的 英文原文。
- 不要錯過 實戰(zhàn) Groovy 的所有文章,每一篇都是在前一篇的基礎(chǔ)上編寫的。
- Hibernate 對于 Groovysql, 就像 Velocity 對于 GSP 框架、Java 語言對于 Groovy。最重要的還是為您的工作選擇正確的工具。通過 dW 教程 Hibernate 簡化繼承映射(developerWorks, 2004 年 12 月)學習更多關(guān)于 Hibernate 的內(nèi)容。
- 從 Sing Li 撰寫的 使用 Velocity 實現(xiàn)客戶端和服務(wù)器端模板(developerWorks,2004 年 2 月)學習了關(guān)于 Velocity 的內(nèi)容。
- Malcolm Davis 撰寫的 Struts,MVC 的一種開放源碼實現(xiàn) (developerWorks,2001 年 2 月)仍然是對 Strut 的最好介紹之一。
- 可以從 Groovy 開放源代碼項目頁 下載 Groovy,在那里還可以學習更多關(guān)于像編譯、單元測試、正責表達式這類主題的內(nèi)容。
- 可以在 developerWorks Java 技術(shù)專區(qū) 找到關(guān)于 Java 編程的各個方面的文章。
- 還請參閱 Java 技術(shù)專區(qū)教程,以獲得 developerWorks 上的免費 Java 主題教程的完整清單。
- 通過參與 developerWorks blogs 加入 developerWorks 社區(qū)。
- 請參閱 The Developer Bookstore,以獲得技術(shù)書籍的完整清單,其中包括數(shù)百本 Java 相關(guān)主題的書籍。
關(guān)于作者 Andrew Glover 是 Vanward Technologies 的首席技術(shù)官,該公司位于華盛頓特區(qū)的大都會地區(qū) ,公司的專業(yè)領(lǐng)域是專門從事自動測試工具和框架的構(gòu)造 ,自動測試框架可以幫助降低軟件 bug 數(shù)量,縮短集成和測試的時間,并改進代碼的整體穩(wěn)定性。Andrew Glover 還是 Java Testing Patterns(Wiley,2004 年 9 月)一書的合著者之一。 |