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

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