<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-314  評論-209  文章-0  trackbacks-0

    發現多功能的模板驅動的代碼生成器

    developerWorks
    文檔選項
    將此頁作為電子郵件發送

    將此頁作為電子郵件發送


    最新推薦

    Java 應用開發源動力 - 下載免費軟件,快速啟動開發


    級別: 初級

    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 的核心功能是根據以下組合來生成代碼的(或者生成其他配置/數據文件):

    • 進行特殊標記的 Java 源文件。
    • 預先定義的模板。

    與其他基于模板的代碼生成技術(例如 Velocity;請參閱 參考資料)相比,XDoclet 具有以下獨特優勢:

    • XDoclet 與 Apache Ant(請參閱 參考資料)緊密集成,從而提供了高度自動化的操作。

    • 把控制代碼生成和模板處理的 XDoclet 標簽作為內聯注釋嵌入到 Java 源代碼文件中。這消除了同步多個相關文件和控制文件的需要。

    • XDoclet 的內置 Java 解析器使用它對 Java 代碼結構的深入理解,為輸入的 Java 代碼建立內部 結構模型。該結構模型又經常被叫作 元數據(metadata),因為它包含與關聯代碼有關的數據。

    • XDoclet 的模板生成邏輯擁有對輸入 Java 代碼的內部結構模型的完全訪問權。

    接下來,我將進一步研究 XDoclet 是如何工作的,以幫助您理解這些特性。

    XDoclet 操作

    圖 1 顯示了 XDoclet 要求的輸入和生成的輸出。


    圖 1. XDoclet 黑盒子
    圖 1

    您可以看到,包含嵌入式 XDoclet 標簽的 Java 源代碼是系統的輸入。在 Apache Ant 的驅動下,XDoclet 處理輸入的代碼,生成的輸出文本文件可以是 Java 源代碼、HTML 頁面、XML 文件等。為了處理輸入,XDoclet 需要使用模板(保存在 .xdt 文件中)和標簽處理器(用 Java 編碼)。XDoclet 把模板和標簽處理器打包成“模塊”,不同的“模塊”處理不同的問題域。

    XDoclet 生成的結構模型

    XDoclet 對包含嵌入式 XDoclet 標簽的輸入 Java 源代碼進行解析,并為代碼建立非常詳細的結構模型。結構模型中的每個元素都代表源代碼中的一個 Java 結構。圖 2 顯示的結構模型,揭示了 XDoclet 跟蹤的代碼構造和關系。


    圖 2. XDoclet 的解析的 Java 源代碼的內部結構模型
    圖 2

    圖 2 中的結構模型跟蹤類、接口、方法之類的代碼構造(模型元素)。該模型還跟蹤元素之間的關系,例如繼承和接口實現。以內聯注釋的形式嵌入在源代碼中的 XDoclet 標簽被解析為模型元素的屬性,并被跟蹤。

    通用的 Javadoc 引擎

    能夠理解 Java 代碼結構模型的智能代碼生成引擎不是什么新概念。實際上,它是 JDK 自帶的 Javadoc 工具的運作方式。通過解析帶有特殊 Javadoc 標簽的 Java 源文件,Javadoc 工具可以為所有 Java 程序的內置結構元素(包括類、接口、字段和方法)生成 HTML 文檔。Javadoc 還具有特殊 Java 語言概念方面的知識,例如繼承、抽象類、存儲類和修飾符。

    XDoclet 的誕生,來自這樣一個觀察:適用于任意代碼生成的 Javadoc 的通用版本,在許多編程場合下會極為有用。但是,實際的 Javadoc 源代碼不是為通用的代碼生成設計的,而只是為了生成 HTML 文檔。由于無法重用現有代碼,XDoclet 開發小組從頭開始重寫了引擎,并顯著優化了它的性能。





    回頁首


    深入 XDoclet

    圖 3 顯示了 XDoclet 的內部結構,揭示了使其運行的功能塊。


    圖 3. XDoclet 內部的功能塊
    圖 3
    ?

    如圖 3 所示,Apache Ant 在運行的時候控制著 XDoclet 的配置和操作。XDoclet 解析輸入的 Java 源代碼,并在內存中生成結構模型。模板引擎通過處理一組模板和標簽處理器,生成輸出文件。模板和標簽處理器可以是內置的,也可以是定制的。在代碼生成期間,模板和標簽處理器擁有對結構模型的完全訪問。

    XDoclet 虛假的復雜性

    XDoclet 實質上就是一個通用的 Javadoc 引擎(請參閱側欄, 通用的 Javadoc 引擎)。那么,是什么讓它看起來這么復雜呢?答案在于:XDoclet 幾乎從未被單獨討論過,而總是藏在其他許多復雜的技術中。圖 4 顯示了了圍繞在 XDoclet 周圍的復雜性迷霧(請參閱側欄 為什么 XDoclet 看起來比實際的要復雜得多)。

    為什么 XDoclet 看起來比實際的要復雜得多

    Apache Ant 自動進行 Java 軟件的生成過程。構建管理過程通常是生產項目中更復雜過程中的一部分。構建管理的術語和概念被集成到 Apache Ant 中,而且是理解其操作的先決條件。成熟的 Ant 腳本可能會非常復雜。Ant 的每個新版本,都會引入一些新的特性集,從而進一步增加了復雜性。這形成了 XDoclet 表面的復雜性,因為 XDoclet 需要 Ant 才能執行。

    XDoclet 處理的問題領域是復雜性的另一個來源。在發布 XDoclet 的時候,XDoclet 已經可以為 EJB 組件集成、J2EE Web 容器集成、Hibernate 持久性層、Struts 框架、Java 管理擴展(JMX)等生成代碼。這些問題領域中的每一個領域都有一大套該領域專用的行話和概念。從這些復雜的問題領域出來的問題,經常主導著 XDoclet 的討論,這也提高了 XDoclet 表面的復雜性。可能是“只見森林,不見樹木”。


    圖 4. XDoclet 的復雜耦合
    Figure 4

    在圖 4 中,您可以看到 XDoclet 與以下內容是緊密相關的:

    • Apache Ant,它控制著 XDoclet 的操作。XDoclet 是作為一組 Ant 任務存在的,沒有 Ant 則不能執行。
    • 與生成文件關聯的具體問題領域的一些細節。

    XDoclet 本身卻是驚人地簡單,正如下面示例中的工作代碼所示的那樣。





    回頁首


    使用 XDoclet

    現在,您可以通過研究我向您提供的數據入口應用程序示例,來觀察 XDoclet 的實際工作。(要下載這個示例中使用的 Java 代碼、XDoclet 模板和 Ant 腳本,請單擊本文頂部或底部的 Code圖標,或者請參閱 下載部分。)我們將從檢查清單 1 所示的 Java 代碼開始,這部分代碼表示了一個客戶的地址。該地址被編碼成 JavaBean 組件,其中的 XDoclet 標簽是以黑體字形式顯示的:


    清單 1. 用 XDoclet 標簽標記的 AddressBean.java 源文件
    package com.ibm.dw.beans;import java.io.Serializable;/**        * @dw.genStrutsAction action="/addAddress.do"* @hibernate.class table="ADDRESS"*/public class AddressBean implements Serializable {private String streetNumber = "";private String street = "";private String city = "";private String country = "";private String postalCode = "";private long id = 0;public AddressBean() {}/**        * @dw.genStruts formlabel="Street Number"* @hibernate.property length="10"*/public String getStreetNumber() {   return streetNumber;}public void setStreetNumber(String inpStreetNumber) {   streetNumber = inpStreetNumber;}/**        * @dw.genStruts formlabel="Street"* @hibernate.property  length="40"*/public String getStreet() {    return street;}public void setStreet(String inpStreet) {   street = inpStreet;}        ...... more Address bean properties ....../**        * @hibernate.id generator-class="native"*/public long getId(  ){        return id;}public void setId(long inId) {   id = inId;}}      

    在清單 1 中,需要注意的是,要把 XDoclet 標簽嵌入到注釋中,緊放在相關代碼元素(例如字段、方法、接口或類)的前面。在解析源代碼時,XDoclet 會為每個標簽建立一個屬性,并將該屬性附加到結構模型的代碼元素上。現在,請注意 @dw.genStruts 標簽,因為這是在本例中將用到的第一個模板。

    生成另外一個 Java 類

    對于本例,您需要生成新的 Java 類的代碼 —— 一個 Struts 表單 bean。Struts 會用這個 bean 保存并傳輸用戶輸入。bean 必須以 bean 屬性的形式包含所有數據字段,而且它必須是 org.apache.struts.action.ActionForm 的子類。

    為了生成表單 bean 的代碼,您要根據清單 2 所示的偽代碼生成 XDoclet 模板。括號中的黑體字代表控制流邏輯和您要進行替換的文本。請注意模板是如何從已解析的 Java 源代碼文件的結構模型中提取信息的:


    清單 2. 建立 AddressBeanForm.java Struts 表單 bean 代碼的偽代碼模板
    package         {package name of source class};import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionMapping;import org.apache.struts.upload.FormFile;/** * Form Bean class for         {name of source class};. * * @struts.form name="        {name of source class}Form" */public class         {name of source class}Form extends ActionForm {        {loop through all the methods in the source class}   {if the method is a JavaBean "getter" method}      {if the method has been marked with the @dw.genStruts tag }	private         {return type of method}{name of the JavaBean property}; 	public         {return type of method}{name of the getter method for this property}(){		return         {name of JavaBean property};	}	public void         {name of the setter method for this property}(	                                    {return type of method} value) {                    {name of the JavaBean property} = value;      			}               {end of if @dw.genStruts}    {end of if JavaBean getter}{end of loop}

    用 XDoclet 建立 XDoclet 標簽

    請注意在 清單 2 的模板中生成的 XDoclet @struts.form 標簽。您可以用 XDoclet 在 Java 源代碼中生成 XDoclet 標簽,XDoclet 會在后面的操作中再次處理這些標簽。在示例后面建立 structs-config.xml 的時候,XDoclet 會使用 @struts.form 標簽。



    在清單 2 的循環中的代碼生成了一個字段聲明和一個訪問器方法,還為輸入源代碼中每個用 @dw.genStruts 標記的訪問器方法生成了一個設置器方法。

    清單 2 使用了易于理解的偽代碼來表示模板替換標簽。實際的 XDoclet 模板標簽則相當繁瑣。清單 3 顯示了 genformbean.xdt 模板(所有的 XDoclet 模板都保存在 .xdt 文件中)。我已經用黑體字強調了 XDoclet 模板標簽,以方便在偽代碼中對其進行引用。


    清單 3. 建立 Structs 表單 bean Java 代碼的實際 XDoclet 模板代碼
    package         <XDtPackage:packageName/>;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionMapping;import org.apache.struts.upload.FormFile;/** * Form Bean class for         <XDtClass:className/>. * * @struts.form name="        <XDtClass:className/>Form" */public class         <XDtClass:className/>Form extends ActionForm {        <XDtMethod:forAllMethods>   <XDtMethod:ifIsGetter>      <XDtMethod:ifHasMethodTag tagName="dw.genStruts">	private         <XDtMethod:methodType/> <XDtMethod:propertyName/>; 	public         <XDtMethod:methodType/> <XDtMethod:getterMethod/>(){		return         <XDtMethod:propertyName/>;	}	public void         <XDtMethod:setterMethod/>(        <XDtMethod:methodType/> value) {                    <XDtMethod:propertyName/> = value;      			}             </XDtMethod:ifHasMethodTag>   </XDtMethod:ifIsGetter></XDtMethod:forAllMethods>

    熟悉 Ant 腳本編寫

    Ant 腳本 build.xml(我已經隨本文的示例代碼提供了這個文件,請參閱 下載部分找到代碼的鏈接)定義了示例應用程序使用的全部必要 Ant 目標。如果您想修改腳本,就需要熟悉 Ant。請參閱 參考資料 了解 Ant 的更多信息。

    您可以參考 XDoclet 的“模板語言”文檔,查找 XDoclet 所有可用標簽的列表(請參閱 參考資料)。

    要運行用于 AddressBean.java 源文件的模板,請使用以下 Ant 命令行:

    ant -Dbase.class.java=Address genstruts

    這個命令可以執行定制 Ant 目標(請參閱側欄 熟悉 Ant 腳本編寫)來處理 genbeanform.xdt 模板。XDoclet 提供的 Ant 任務叫作 xdoclet.DocletTask ,它被用來運行模板文件。如果您對 Ant 的細節感興趣,請參閱示例代碼中的 build.xml 文件,以了解更多信息。

    在 XDoclet 處理模板的時候,它在名為 generated的子目錄下生成一個 AddressBeanForm.java 文件。清單 4 顯示了該文件,它包含模板處理期間替換的所有文本:


    清單 4. XDoclet 生成的包含 Struts 表單 bean 的 Java 源代碼
    package         com.ibm.dw.beans;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionMapping;import org.apache.struts.upload.FormFile;/** * Form Bean class for         AddressBean. * * @struts.form name="        AddressBeanForm" */public class         AddressBeanForm extends ActionForm {	private         java.lang.String streetNumber; 	public         java.lang.String getStreetNumber(){		return         streetNumber;	}	public void         setStreetNumber(        java.lang.String value) {                    streetNumber = value;      			}	private         java.lang.Stringstreet; 	public         java.lang.String getStreet(){		return         street;	}	public void         setStreet(        java.lang.String value) {                    street = value;      			}           ...... more bean properties .....}      

    為數據表單輸入生成 JSP 頁面

    您可以用相同的 AddressBean.java 源文件,但是用 genformjsp.xdt 模板生成數據入口表單 JSP 頁面。清單 5 顯示了 genformjsp.xdt:


    清單 5. 使用 Struts 標簽庫生成 JSP 頁面來顯示 HTML 表單的 XDoclet 模板
    <%@ page language="java" %><%@ taglib  uri="/WEB-INF/struts-html.tld" prefix="html" %><html:html><head></head><body bgcolor="white"><html:errors/><html:form action="        <XDtClass:classTagValue tagName='dw.genStrutsAction'  paramName='action' /> >"<table border="0" width="100%">        <XDtMethod:forAllMethods>   <XDtMethod:ifIsGetter>      <XDtMethod:ifHasMethodTag tagName="dw.genStruts" >    <tr>        <th align="right">                   <XDtMethod:methodTagValue                    tagName="dw.genStruts" paramName="formlabel"/>        </th>        <td align="left">            <html:text  property="        <XDtMethod:propertyName/>"              size="        <XDtMethod:ifHasMethodTag tagName="hibernate.property" >              <XDtMethod:methodTagValue tagName="hibernate.property" paramName="length"/>              </XDtMethod:ifHasMethodTag>"/>        </td>    </tr>             </XDtMethod:ifHasMethodTag>   </XDtMethod:ifIsGetter></XDtMethod:forAllMethods>    <tr>        <td align="right">            <html:submit>                Submit            </html:submit>        </td>        <td align="left">            <html:reset>              Reset            </html:reset>        </td>    </tr></table></html:form></body></html:html>      

    請注意,代碼中用 <XDt:methodTagValue> 取得原始 AddressBean.java 代碼中在 XDoclet 標簽中指定的屬性值。

    當您執行 genstruts Ant 目標的時候,也會處理清單 5 顯示的 genformjsp.xdt 模板。您可以在 generated 子目錄中找到生成的 AddressBeanForm.jsp 文件,檢查文件內容,可以看到要對模板進行的替換。

    試驗示例,但是首先...

    要試驗本文示例中的模板化代碼生成,您需要安裝并測試好 Ant 和 XDoclet。本文中的代碼全都基于 Ant 1.5.4 和 XDoclet 1.2.1。要生成所有的工件,并試驗生成的 Web 應用程序,還需要安裝 Hibernate,Struts,以及應用程序服務器,還需要能夠訪問關系數據庫。示例基于 Hibernate 2.1.4,Struts 1.1,以及 Servlet 2.3。請參閱 參考資料 了解有關這些技術的更多信息。請一定要閱讀我隨源代碼一起提供的 README 文件。

    生成其他工件

    您可以用 XDoclet 生成任意基于文本的輸出。我向您展示的例子使用 XDoclet 生成了 Java 代碼、JSP 頁面、XML 文件、配置文件以及其他更多輸出。它從一個簡單的用 XDoclet 進行標記的 Java 源文件 AddressBean.java,建立了一個完整的數據入口 Web 應用程序。為了做到這一點,它執行了 XDoclet 的內置模板(位于 JAR 文件中,稱為模塊),從而生成:

    • Struts 配置和支持文件。
    • Hibernate 配置和支持文件。
    • Web 應用程序的部署描述符(web.xml)。

    表 1 顯示了為示例應用程序生成的所有文件(通常稱為 工件(artifact)):


    表 1. XDoclet 為 AddressBean.java 生成的工件
    生成的工件說明位置
    AddressBeanForm.javaJava 源文件,包含表單 bean 類,在 Struts 的表單處理中使用generated目錄
    AddressBeanForm.jspJSP 表單,用 Struts 標簽庫接受用戶地址輸入jsp目錄
    AddressBeanAction.javaStruts 動作類,接受輸入值,用 Hibernate 把值保存到關系數據庫generated目錄
    AddressBean.hbm.xmlHibernate 映射文件,在 AddressBean Java 對象和數據庫的關系型 ADDRESS 表之間進行映射 web/classes目錄
    dwschema.sqlRDBMS 表的架構,用來對 AddressBean 對象的實例進行持久化 sql目錄
    hibernate.cfg.xmlHibernate 運行時的配置文件web/classes目錄
    web.xml生成的 Web 應用程序的部署描述符web目錄
    struts-config.xmlStruts 框架的配置文件web目錄

    在這篇文章中,您詳細了解了表 1 中所列的兩個工件中的第一個工件的生成,深入了解了生成它們的模板。工件 AdddressBeanAction.java 則用類似的方法,利用叫作 genaction.xdt 的模板生成。XDoclet 具有內置模板和標簽處理器,可以生成表 1 中的其他工件。

    表 2 列出了每個生成的工件對應的 Ant 目標和 Ant 任務。您可以執行表格中的每個 Ant 目標,生成對應的工件。所有這些生成的工件,再加上原始和 AddressBean.java,共同構成了示例 Web 應用程序。您還會發現叫作 all 的默認 Ant 目標,它會為您做任何事,包括為應用程序建立 WAR(可以部署的 Web 歸檔)。在進行處理之前,一定要閱讀代碼發布包中的 README.txt 文件。

    XDoclet 中的合并點

    在 XDoclet 的文檔中,您會非常頻繁地看到術語 合并點(merge point)合并文件(merge file)。合并文件是文本文件,您可以把它合并到 XDoclet 生成代碼的指定位置——“合并點”上(由模板指定)。可以用合并文件來包含靜態文本(例如代碼片斷和 XML 片斷),這些文本可能很難或者不能用 XDoclet 的能力生成。例如,在示例代碼的 merge/web 目錄下,您會找到 struts-action.xml 文件。在代碼生成期間,可以用該文件合并到 Struts 的動作映射中,構成生成的 struts-config.xml 文件的一部分。


    表 2. 對應于生成工件的 Ant 目錄和 Ant 任務
    Ant 目標Ant 任務工件
    genstrutsxdoclet.DocletTaskAddressBeanForm.java
    genstrutsxdoclet.DocletTaskAddressBeanForm.jsp
    genstrutsxdoclet.DocletTaskAddressBeanAction.java
    generateHIBxdoclet.modules.hibernate.HibernateDocletTaskAddressBean.hbm.xml
    generateHIBxdoclet.modules.hibernate.HibernateDocletTaskhibernate.cfg.xml
    createDDLxdoclet.modules.hibernate.HibernateDocletTaskdwschema.sql
    generateDDxdoclet.modules.web.WebDocletTaskweb.xml
    generateDDxdoclet.modules.web.WebDocletTaskstruts-config.xml




    回頁首


    結束語

    XDoclet 是一個有用的、智能的代碼生成器,您可以用它自動進行許多日常的 Java 開發任務。不要被它表面的復雜所嚇退。隨著逐漸精通 XDoclet(以及與之相關的 Apache Ant),您會節約您寶貴的時間,并在未來的開發工作中,得到數倍的回報。






    回頁首


    下載

    名字大小下載方法
    j-xdoclet-code.zip??FTP
    關于下載方法的信息Get Adobe? Reader?




    回頁首


    參考資料





    回頁首


    關于作者

    Author photo

    Sing Li 是 Professional Apache Tomcat 5Pro JSP, Third EditionEarly Adopter JXTAProfessional Jini,以及 Wrox Press 出版的許多其他圖書的作者。他是技術雜志的定期撰稿人,還是 P2P 發展的熱心傳播者。Sing 是一名咨詢顧問和資深作者,您可以通過他的電子郵件 westmakaha@yahoo.com與他聯系。


    posted on 2006-11-05 08:30 xzc 閱讀(452) 評論(0)  編輯  收藏 所屬分類: Xdoclet
    主站蜘蛛池模板: 成人午夜大片免费7777| 中文字幕亚洲综合久久菠萝蜜| 亚洲熟伦熟女专区hd高清| 蜜臀91精品国产免费观看| 一级做性色a爰片久久毛片免费| 亚洲国产精品无码久久久秋霞2 | 免费看男女下面日出水视频| 一区二区三区免费视频观看| 久久久久亚洲av无码专区喷水| 在线jlzzjlzz免费播放| WWW免费视频在线观看播放| 亚洲国产av美女网站| 亚洲第一网站男人都懂| 精品无码AV无码免费专区| 国产精品无码亚洲精品2021| 亚洲国产精品无码成人片久久| 成年人网站在线免费观看| 三级黄色在线免费观看| 亚洲日韩一区二区一无码| 国产亚洲无线码一区二区| 青青青国产免费一夜七次郎| 黄色免费在线网站| 看全免费的一级毛片| 亚洲永久永久永久永久永久精品| 日本xxwwxxww在线视频免费| 国产真人无码作爱视频免费| 无码色偷偷亚洲国内自拍| 久久精品国产亚洲AV网站| 日本成人免费在线| 在线永久看片免费的视频| 你是我的城池营垒免费看| 菠萝菠萝蜜在线免费视频| 亚洲中文字幕无码一去台湾| 亚洲成AV人在线观看天堂无码| 国产真人无遮挡作爱免费视频| 永久免费在线观看视频| 光棍天堂免费手机观看在线观看| 黄色a级免费网站| ww亚洲ww在线观看国产| 久久精品九九亚洲精品| 亚洲真人无码永久在线|