發(fā)現(xiàn)多功能的模板驅(qū)動(dòng)的代碼生成器 ![]() |
![]() |
![]() |
級(jí)別: 初級(jí)
Sing Li
, 作者, Wrox Press 2004 年 11 月 05 日 開(kāi)放源代碼的 XDoclet 代碼生成引擎,是許多領(lǐng)先的 Java 框架不可缺少的組成部分,常常被用作面向?qū)傩缘木幊毯统掷m(xù)集成的引擎。但是 XDoclet 還有一些不太惹人注目的地方:對(duì)初級(jí)開(kāi)發(fā)人員來(lái)說(shuō),它太難掌握、太難精通。在這篇文章中,流行作者 Sing Li 以 XDoclet 為對(duì)象,揭示了其內(nèi)部簡(jiǎn)單卻優(yōu)雅的設(shè)計(jì),使您能夠理解這項(xiàng)技術(shù),并將它應(yīng)用在實(shí)踐當(dāng)中。 XDoclet 能夠很容易成為您的 Java 編程工具箱中的一個(gè)更加通用的跨技術(shù)代碼生成工具。不幸的是,開(kāi)發(fā)人員經(jīng)常忽視 XDoclet 的一般用途,只有將它捆綁在大型開(kāi)發(fā)框架或者 IDE 中,作為其中的一個(gè)隱藏元素時(shí),才會(huì)用到它。人們常常認(rèn)為很難將 XDoclet 應(yīng)用在定制解決方案上。這篇文章的目的就是要消除這個(gè)迷惑,把 XDoclet 從常見(jiàn)的復(fù)雜陷阱中解脫出來(lái),并向您展示了如何能夠利用這個(gè)代碼生成引擎。 我會(huì)用一個(gè)實(shí)際的例子演示 XDoclet 的用途,該例子將接收一個(gè) POJO(plain old Java object),并用 XDoclet 生成完整 Web 應(yīng)用程序的全部文件,這些文件是把數(shù)據(jù)輸入關(guān)系數(shù)據(jù)庫(kù)所必需的。該示例使用了 XDoclet 的 自定義模板代碼生成功能,以及它對(duì) Hibernate 對(duì)象關(guān)系映射工具、Struct Web 應(yīng)用程序框架和應(yīng)用程序服務(wù)器的內(nèi)部支持。(請(qǐng)參閱 參考資料)。 XDoclet 的核心功能是根據(jù)以下組合來(lái)生成代碼的(或者生成其他配置/數(shù)據(jù)文件):
與其他基于模板的代碼生成技術(shù)(例如 Velocity;請(qǐng)參閱 參考資料)相比,XDoclet 具有以下獨(dú)特優(yōu)勢(shì):
接下來(lái),我將進(jìn)一步研究 XDoclet 是如何工作的,以幫助您理解這些特性。 圖 1 顯示了 XDoclet 要求的輸入和生成的輸出。 圖 1. XDoclet 黑盒子 ![]() 您可以看到,包含嵌入式 XDoclet 標(biāo)簽的 Java 源代碼是系統(tǒng)的輸入。在 Apache Ant 的驅(qū)動(dòng)下,XDoclet 處理輸入的代碼,生成的輸出文本文件可以是 Java 源代碼、HTML 頁(yè)面、XML 文件等。為了處理輸入,XDoclet 需要使用模板(保存在 .xdt 文件中)和標(biāo)簽處理器(用 Java 編碼)。XDoclet 把模板和標(biāo)簽處理器打包成“模塊”,不同的“模塊”處理不同的問(wèn)題域。 XDoclet 對(duì)包含嵌入式 XDoclet 標(biāo)簽的輸入 Java 源代碼進(jìn)行解析,并為代碼建立非常詳細(xì)的結(jié)構(gòu)模型。結(jié)構(gòu)模型中的每個(gè)元素都代表源代碼中的一個(gè) Java 結(jié)構(gòu)。圖 2 顯示的結(jié)構(gòu)模型,揭示了 XDoclet 跟蹤的代碼構(gòu)造和關(guān)系。 圖 2. XDoclet 的解析的 Java 源代碼的內(nèi)部結(jié)構(gòu)模型 ![]() 圖 2 中的結(jié)構(gòu)模型跟蹤類(lèi)、接口、方法之類(lèi)的代碼構(gòu)造(模型元素)。該模型還跟蹤元素之間的關(guān)系,例如繼承和接口實(shí)現(xiàn)。以?xún)?nèi)聯(lián)注釋的形式嵌入在源代碼中的 XDoclet 標(biāo)簽被解析為模型元素的屬性,并被跟蹤。
圖 3 顯示了 XDoclet 的內(nèi)部結(jié)構(gòu),揭示了使其運(yùn)行的功能塊。 圖 3. XDoclet 內(nèi)部的功能塊 ![]() |
如圖 3 所示,Apache Ant 在運(yùn)行的時(shí)候控制著 XDoclet 的配置和操作。XDoclet 解析輸入的 Java 源代碼,并在內(nèi)存中生成結(jié)構(gòu)模型。模板引擎通過(guò)處理一組模板和標(biāo)簽處理器,生成輸出文件。模板和標(biāo)簽處理器可以是內(nèi)置的,也可以是定制的。在代碼生成期間,模板和標(biāo)簽處理器擁有對(duì)結(jié)構(gòu)模型的完全訪(fǎng)問(wèn)。
XDoclet 實(shí)質(zhì)上就是一個(gè)通用的 Javadoc 引擎(請(qǐng)參閱側(cè)欄, 通用的 Javadoc 引擎)。那么,是什么讓它看起來(lái)這么復(fù)雜呢?答案在于:XDoclet 幾乎從未被單獨(dú)討論過(guò),而總是藏在其他許多復(fù)雜的技術(shù)中。圖 4 顯示了了圍繞在 XDoclet 周?chē)膹?fù)雜性迷霧(請(qǐng)參閱側(cè)欄 為什么 XDoclet 看起來(lái)比實(shí)際的要復(fù)雜得多)。
![]() |
|
圖 4. XDoclet 的復(fù)雜耦合

在圖 4 中,您可以看到 XDoclet 與以下內(nèi)容是緊密相關(guān)的:
- Apache Ant,它控制著 XDoclet 的操作。XDoclet 是作為一組 Ant 任務(wù)存在的,沒(méi)有 Ant 則不能執(zhí)行。
- 與生成文件關(guān)聯(lián)的具體問(wèn)題領(lǐng)域的一些細(xì)節(jié)。
XDoclet 本身卻是驚人地簡(jiǎn)單,正如下面示例中的工作代碼所示的那樣。
![]() ![]() |
![]()
|
現(xiàn)在,您可以通過(guò)研究我向您提供的數(shù)據(jù)入口應(yīng)用程序示例,來(lái)觀察 XDoclet 的實(shí)際工作。(要下載這個(gè)示例中使用的 Java 代碼、XDoclet 模板和 Ant 腳本,請(qǐng)單擊本文頂部或底部的 Code圖標(biāo),或者請(qǐng)參閱 下載部分。)我們將從檢查清單 1 所示的 Java 代碼開(kāi)始,這部分代碼表示了一個(gè)客戶(hù)的地址。該地址被編碼成 JavaBean 組件,其中的 XDoclet 標(biāo)簽是以黑體字形式顯示的:
清單 1. 用 XDoclet 標(biāo)簽標(biāo)記的 AddressBean.java 源文件
|
在清單 1 中,需要注意的是,要把 XDoclet 標(biāo)簽嵌入到注釋中,緊放在相關(guān)代碼元素(例如字段、方法、接口或類(lèi))的前面。在解析源代碼時(shí),XDoclet 會(huì)為每個(gè)標(biāo)簽建立一個(gè)屬性,并將該屬性附加到結(jié)構(gòu)模型的代碼元素上。現(xiàn)在,請(qǐng)注意 @dw.genStruts
標(biāo)簽,因?yàn)檫@是在本例中將用到的第一個(gè)模板。
對(duì)于本例,您需要生成新的 Java 類(lèi)的代碼 —— 一個(gè) Struts 表單 bean。Struts 會(huì)用這個(gè) bean 保存并傳輸用戶(hù)輸入。bean 必須以 bean 屬性的形式包含所有數(shù)據(jù)字段,而且它必須是 org.apache.struts.action.ActionForm
的子類(lèi)。
為了生成表單 bean 的代碼,您要根據(jù)清單 2 所示的偽代碼生成 XDoclet 模板。括號(hào)中的黑體字代表控制流邏輯和您要進(jìn)行替換的文本。請(qǐng)注意模板是如何從已解析的 Java 源代碼文件的結(jié)構(gòu)模型中提取信息的:
清單 2. 建立 AddressBeanForm.java Struts 表單 bean 代碼的偽代碼模板
|
![]() |
|
在清單 2 的循環(huán)中的代碼生成了一個(gè)字段聲明和一個(gè)訪(fǎng)問(wèn)器方法,還為輸入源代碼中每個(gè)用 @dw.genStruts
標(biāo)記的訪(fǎng)問(wèn)器方法生成了一個(gè)設(shè)置器方法。
清單 2 使用了易于理解的偽代碼來(lái)表示模板替換標(biāo)簽。實(shí)際的 XDoclet 模板標(biāo)簽則相當(dāng)繁瑣。清單 3 顯示了 genformbean.xdt 模板(所有的 XDoclet 模板都保存在 .xdt 文件中)。我已經(jīng)用黑體字強(qiáng)調(diào)了 XDoclet 模板標(biāo)簽,以方便在偽代碼中對(duì)其進(jìn)行引用。
清單 3. 建立 Structs 表單 bean Java 代碼的實(shí)際 XDoclet 模板代碼
|
![]() |
|
您可以參考 XDoclet 的“模板語(yǔ)言”文檔,查找 XDoclet 所有可用標(biāo)簽的列表(請(qǐng)參閱 參考資料)。
要運(yùn)行用于 AddressBean.java 源文件的模板,請(qǐng)使用以下 Ant 命令行:
|
這個(gè)命令可以執(zhí)行定制 Ant 目標(biāo)(請(qǐng)參閱側(cè)欄 熟悉 Ant 腳本編寫(xiě))來(lái)處理 genbeanform.xdt 模板。XDoclet 提供的 Ant 任務(wù)叫作 xdoclet.DocletTask
,它被用來(lái)運(yùn)行模板文件。如果您對(duì) Ant 的細(xì)節(jié)感興趣,請(qǐng)參閱示例代碼中的 build.xml 文件,以了解更多信息。
在 XDoclet 處理模板的時(shí)候,它在名為 generated的子目錄下生成一個(gè) AddressBeanForm.java 文件。清單 4 顯示了該文件,它包含模板處理期間替換的所有文本:
清單 4. XDoclet 生成的包含 Struts 表單 bean 的 Java 源代碼
|
您可以用相同的 AddressBean.java 源文件,但是用 genformjsp.xdt 模板生成數(shù)據(jù)入口表單 JSP 頁(yè)面。清單 5 顯示了 genformjsp.xdt:
清單 5. 使用 Struts 標(biāo)簽庫(kù)生成 JSP 頁(yè)面來(lái)顯示 HTML 表單的 XDoclet 模板
|
請(qǐng)注意,代碼中用 <XDt:methodTagValue>
取得原始 AddressBean.java 代碼中在 XDoclet 標(biāo)簽中指定的屬性值。
當(dāng)您執(zhí)行 genstruts
Ant 目標(biāo)的時(shí)候,也會(huì)處理清單 5 顯示的 genformjsp.xdt 模板。您可以在 generated 子目錄中找到生成的 AddressBeanForm.jsp 文件,檢查文件內(nèi)容,可以看到要對(duì)模板進(jìn)行的替換。
![]() |
|
您可以用 XDoclet 生成任意基于文本的輸出。我向您展示的例子使用 XDoclet 生成了 Java 代碼、JSP 頁(yè)面、XML 文件、配置文件以及其他更多輸出。它從一個(gè)簡(jiǎn)單的用 XDoclet 進(jìn)行標(biāo)記的 Java 源文件 AddressBean.java,建立了一個(gè)完整的數(shù)據(jù)入口 Web 應(yīng)用程序。為了做到這一點(diǎn),它執(zhí)行了 XDoclet 的內(nèi)置模板(位于 JAR 文件中,稱(chēng)為模塊),從而生成:
- Struts 配置和支持文件。
- Hibernate 配置和支持文件。
- Web 應(yīng)用程序的部署描述符(web.xml)。
表 1 顯示了為示例應(yīng)用程序生成的所有文件(通常稱(chēng)為 工件(artifact)):
表 1. XDoclet 為 AddressBean.java 生成的工件
生成的工件 | 說(shuō)明 | 位置 |
AddressBeanForm.java | Java 源文件,包含表單 bean 類(lèi),在 Struts 的表單處理中使用 | generated目錄 |
AddressBeanForm.jsp | JSP 表單,用 Struts 標(biāo)簽庫(kù)接受用戶(hù)地址輸入 | jsp目錄 |
AddressBeanAction.java | Struts 動(dòng)作類(lèi),接受輸入值,用 Hibernate 把值保存到關(guān)系數(shù)據(jù)庫(kù) | generated目錄 |
AddressBean.hbm.xml | Hibernate 映射文件,在 AddressBean Java 對(duì)象和數(shù)據(jù)庫(kù)的關(guān)系型 ADDRESS 表之間進(jìn)行映射 | web/classes目錄 |
dwschema.sql | RDBMS 表的架構(gòu),用來(lái)對(duì) AddressBean 對(duì)象的實(shí)例進(jìn)行持久化 | sql目錄 |
hibernate.cfg.xml | Hibernate 運(yùn)行時(shí)的配置文件 | web/classes目錄 |
web.xml | 生成的 Web 應(yīng)用程序的部署描述符 | web目錄 |
struts-config.xml | Struts 框架的配置文件 | web目錄 |
在這篇文章中,您詳細(xì)了解了表 1 中所列的兩個(gè)工件中的第一個(gè)工件的生成,深入了解了生成它們的模板。工件 AdddressBeanAction.java 則用類(lèi)似的方法,利用叫作 genaction.xdt 的模板生成。XDoclet 具有內(nèi)置模板和標(biāo)簽處理器,可以生成表 1 中的其他工件。
表 2 列出了每個(gè)生成的工件對(duì)應(yīng)的 Ant 目標(biāo)和 Ant 任務(wù)。您可以執(zhí)行表格中的每個(gè) Ant 目標(biāo),生成對(duì)應(yīng)的工件。所有這些生成的工件,再加上原始和 AddressBean.java,共同構(gòu)成了示例 Web 應(yīng)用程序。您還會(huì)發(fā)現(xiàn)叫作 all
的默認(rèn) Ant 目標(biāo),它會(huì)為您做任何事,包括為應(yīng)用程序建立 WAR(可以部署的 Web 歸檔)。在進(jìn)行處理之前,一定要閱讀代碼發(fā)布包中的 README.txt 文件。
![]() |
|
表 2. 對(duì)應(yīng)于生成工件的 Ant 目錄和 Ant 任務(wù)
Ant 目標(biāo) | Ant 任務(wù) | 工件 |
genstruts | xdoclet.DocletTask | AddressBeanForm.java |
genstruts | xdoclet.DocletTask | AddressBeanForm.jsp |
genstruts | xdoclet.DocletTask | AddressBeanAction.java |
generateHIB | xdoclet.modules.hibernate.HibernateDocletTask | AddressBean.hbm.xml |
generateHIB | xdoclet.modules.hibernate.HibernateDocletTask | hibernate.cfg.xml |
createDDL | xdoclet.modules.hibernate.HibernateDocletTask | dwschema.sql |
generateDD | xdoclet.modules.web.WebDocletTask | web.xml |
generateDD | xdoclet.modules.web.WebDocletTask | struts-config.xml |
![]() ![]() |
![]()
|
XDoclet 是一個(gè)有用的、智能的代碼生成器,您可以用它自動(dòng)進(jìn)行許多日常的 Java 開(kāi)發(fā)任務(wù)。不要被它表面的復(fù)雜所嚇退。隨著逐漸精通 XDoclet(以及與之相關(guān)的 Apache Ant),您會(huì)節(jié)約您寶貴的時(shí)間,并在未來(lái)的開(kāi)發(fā)工作中,得到數(shù)倍的回報(bào)。
![]() ![]() |
![]()
|
名字 | 大小 | 下載方法 |
---|---|---|
j-xdoclet-code.zip | ? | ?FTP |
![]() | ||||
![]() | 關(guān)于下載方法的信息 | ![]() | ![]() | Get Adobe? Reader? |
![]() ![]() |
![]()
|
- 您可以參閱本文在 developerWorks 全球站點(diǎn)上的 英文原文。
- 單擊這篇文章頂部或底部的 Code圖標(biāo)(或者參閱 下載部分),下載本例中用到的 Java 代碼、XDoclet 模板和 Ant 腳本。
- 在官方的開(kāi)放源代碼站點(diǎn)上,了解更多有關(guān) XDoclet的內(nèi)容,上面提供了最新的源代碼、下載、文檔、FAQ 和郵件列表。
- 下載最新版本的 Apache Ant生成管理和自動(dòng)化工作。
- 訪(fǎng)問(wèn)官方的 Hibernate站點(diǎn),得到最新版本的 Hibernate 持久性層、文檔、郵件列表和社區(qū)新聞。
- 參閱最新版本的 StrutsMVC 框架。
- “ 編寫(xiě)自己的 secret Santa Web 應(yīng)用程序,第 1 部分:bean”( developerWorks,2003 年 12 月)展示了 XDoclet 可以怎樣加速 J2EE 應(yīng)用程序的開(kāi)發(fā)和部署。
- 教程“ Use XDoclet to generate Web service support files”( developerWorks, 2003 年 6月) 向 J2EE 開(kāi)發(fā)人員展示了如何用 XDoclet 來(lái)編寫(xiě)自己的定制模板和子任務(wù)。
- 教程“ Enhance J2EE component reuse with XDoclet”( developerWorks, 2003 年 5 月) 向 J2EE 開(kāi)發(fā)人員展示了如何用 XDoclet 來(lái)提高開(kāi)發(fā)速度。
- 要為本文的示例使用一個(gè)開(kāi)放源代碼的應(yīng)用程序服務(wù),可以嘗試 Tomcat 5服務(wù)器。
- 探索另外一個(gè)易于使用的模板語(yǔ)言,請(qǐng)參閱 Sing Li 的文章“ 使用 Velocity 實(shí)現(xiàn)客戶(hù)端和服務(wù)器端模板”( developerWorks,2004 年 2 月)。
- XDoclet in Action(Independent Pub Group; 2003)的作者是 Walls 和 Richards,它是 XDoclet 代碼生成的完整資源。
- 學(xué)習(xí) Java 5 中新的元數(shù)據(jù)功能,請(qǐng)參閱“ Tiger 中的注釋?zhuān)?1 部分: 向 Java 代碼中添加元數(shù)據(jù)”和“ Tiger 中的注釋?zhuān)?2 部分: 定制注釋"( developerWorks,2004 年 9 月)。
- 在 developerWorksJava 技術(shù)專(zhuān)區(qū)中,可以找到數(shù)百篇 Java 技術(shù)資源。
- 請(qǐng)?jiān)L問(wèn) Developer Bookstore,以獲得技術(shù)書(shū)籍的完整列表,其中包括數(shù)百本 Java 相關(guān)主題的書(shū)籍。
![]() ![]() |
![]()
|
![]() | ||
![]() | Sing Li 是 Professional Apache Tomcat 5、 Pro JSP, Third Edition、 Early Adopter JXTA、 Professional Jini,以及 Wrox Press 出版的許多其他圖書(shū)的作者。他是技術(shù)雜志的定期撰稿人,還是 P2P 發(fā)展的熱心傳播者。Sing 是一名咨詢(xún)顧問(wèn)和資深作者,您可以通過(guò)他的電子郵件 westmakaha@yahoo.com與他聯(lián)系。 |