亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

通過XDoclet定制模板進行快速開發

2019-11-18 12:47:03
字體:
來源:轉載
供稿:網友

  最近與同是開發者的朋友一起,談論各種各樣java的之外的構架。似乎有一些現象表明, Java正在因為許多原因成為Web發展的障礙,其中一個問題是代碼行(LOC)。做同一件事情,Java的某一些參數需要其他語言的2倍的代碼量,我個人以為LOC僅僅是一個問題,它讓你把一些本不該花的時間都花在你本不該去做的事情上。例如,象手工編寫你所有的Bean一樣。 或許你也正在手工的為你的構架xml定義所有的條目,以此來節約時間, 我承認, 我正是這樣。
  
  不久之前我使用RubyOnRails,一個讓我喜歡用它們的原因就是他們能很輕易產生完全的代碼,從簡單的script到復雜的代碼。 這讓我考慮我當前的工作和編碼期間我的有效情況是怎么樣的。 “我做好了多少工作VS我花費多少時間”的思想在過去的數星期內不停的在我腦子里縈繞。雖然有各種框架幫助我們使工作變的輕易一些—--比喻說在使用的SPRing—--它一些時候看起來很粗笨,為一個web應用程序做一個頁面或者一個模塊就需要很長的時間。因此在一些思考以后, 我決定了做一些東西。
  
  我多年前已經知道XDoclet,并且在它首次出現的時候試用了它。但是我沒有進行長期的考慮, 所以當時我還不是一個在代碼生成方面的大拿。我想要了解事情到底是怎么工作的, 因此我花了大量時間手工編寫任何代碼,包括config文件和deployment文件。
  
  然而,我今天發現代碼生成的兩個主要的益處:
  
  1.你在想學什么東西的時候,它將是很有幫助的。比喻說,去年我想學Hibernate 的時候,我已經有了存在的表,不想再反復的測試它是怎么工作的了,我也不想花大量的時間來填寫文檔。使用一個方便的叫做Middlegen的工具,我只要告訴它查看我的數據庫并且為我生成代碼就可以了?,F在,寫一個mapping文件對我來說已經很輕易了,可是Middlegen的幫助節省了我大量的時間并為我指明了方向。
  
  2.在對你的工程有一個清楚的概念和一個結構甚至一個框架已經搭建起來后,接下來的事情將變的十分的乏味,手工的創建beans,controllers, services 和 DAO,每次都會有一些新的需求要被創建。理想的做法是,你也許會調用一些Ant任務,比喻說, gencontrollers或者genmodules 來生成合適的controller代碼或者一個整個的包含你的beans, controllers, services和DAO的模塊.
  
  使用XDoclet 來減輕痛苦
  
  基于過去的一些經驗,我不敢確信XDoclet對我有多大的幫助。我想要尋找一個工具讓我可以花最少的時間來生成最多的代碼。我在XDoclet網站上看到的大部分的示例都是針對于EJB的生成的,其實這也是XDoclet設計的初衷。但是,情況是這樣的,我的工程不含有任何的EJB代碼,事實上Spring全部是關于POJO的東西,所以EJB方面的工具不是我需要的。同時,XDoclet不含有任何的Spring標簽,所以我一直在尋找一個不同平常的什么東西。
  
  最后我把目光投上了模板。模板是一種繼續XDoclet功能來更好的滿足你的代碼生成要求的方法。例如,你有一個非凡類型的類,與XDoclet所支持的任何一種都很不同(在我看來是一些客戶化的控制類),你就可以用XML文件來把你自己的模板加進去。理想化的,我只想定義一個含有最小量的屬性并不但產生我的控制器代碼而且另外的Spring所要求的XML文件。在實驗了幾次以后,我對結果很滿足。下面就是加標注的假設的代碼測試控制器類。長代碼行以/分開。
  
  TestController.java
  1.   package com.mytest.account.controller;
  2.
  3.   /**
  4.    * @mytest.controller mapping="/acct.ctrl"
  5.    * @mytest.controller actionmethod="create"
  6.    * @mytest.controller actionmethod="read"
  7.    * @mytest.controller actionmethod="update"
  8.    * @mytest.controller actionmethod="delete"
  9.    */
  10.   public class TestController {
  11.
  12.     /**
  13.     * @mytest.controller property="privateView" propertyValue="priv1" propertyMethod="PrivateView"propertyType="String"
  14.     */
  15.     private String privateView = null;
  16.
  17.     /**
  18.     * @mytest.controller property="publicView" propertyValue="priv2" propertyMethod="PublicView" propertyType="String"
  19.     */
  20.     public String publicView = null;21.   }
  
  你首先看到的可能是客戶化的命名空間@mytest.controller標簽。這個是在生成我們類的不同部分時,XDoclet如何知道去查找什么。標簽的位置十分的重要。一些在類要害字的上面一些在屬性定義的下面。XDoclet根據不同位置的標簽來生成在我們的模板中使用的類和屬性對象。這是一個很重要的區別,我們將在接下來研究。
  
  看一下上面的代碼,我們將做下面的操作:
  
  1.為SimpleUrlHandlerMapping建立一個Spring mapping入口,它將在一個叫做mytest-servlet.xml 文件中被描述(是Spring中與Struts中的struts-config.xml 類似的東西).
  
  2.actionmethod 屬性答應我們為一個控制器指定一個方法名,它是從Srping的MultiActionController 繼續而來 (在Struts, 對應的是 DispatchAction)。在我們的例子中,將會有 CRUD (Create, Read, Update, Delete)這么幾個方法名。 XDoclet將會重復的進行不同參數的相同方法名的方法,所以答應我們的模板輸出N個方法。
  
  3.property 標簽 讓我們 定義一個典型的Bean屬性,像你通常在XDoclet中做的一樣,因為我們在這里使用了一個定制的模板,我們增加了更多的屬性。propertyValue 是為mytest-servlet.xml 中對應的屬性所指定的值。對我們的定制的標簽來說,我們正在為控制器類設置private的和public的jsp頁面顯示,我通常管它們叫privateView和publicView—一個是針對簽發者的另一是針對每一個人的。propertyMethod 將為我們提供一種簡單的方法來類指定這個屬性屬于那一個方法,而不用去跳過bean-method-naming的約束。propertyType 屬性指定了我們將要為這個方法get/set什么類型的屬性。
  
  很有爭議的是,我可能把所有的屬性定義發在類的層次上而不是Field的層次上。這也未嘗不可,但是這將為在模板上增加額外的代碼來確定在產生一個方法的時候我使用了正確的屬性,方法,類型。我感覺使用XDoclet的Field 類比往我的模板里增加復雜的代碼要輕易和迅速。
  
  模板
  
  好了,現在讓我們開始干活吧。正像我前面提到的那樣,我選擇XDoclet來生成代碼的原因是我將定義一套定制的模板(不是一些定制的類或者更多的代碼)并使用XDoclet的XML標簽來為我填充這些空白。下面所列就是我們想要生成的模板相應的部分。長代碼已經被/ 分開。
  
  MultiController.xdt
  
  1.   package <XDtPackage:packageName/>;
  2.   import javax.servlet.http.HttpServletRequest;
  3.   import javax.servlet.http.HttpServletResponse;
  4.
  5.   import org.apache.commons.logging.Log;
  6.   import org.apache.commons.logging.LogFactory;
  7.   import org.springframework.validation.BindException;
  8.   import org.springframework.web.servlet.ModelAndView;
  9.
  10.   import com.mytest.system.spring.BaseController;
  11.
  12.   /**
  13.   * MultiAction controller class for <XDtClass:className/>.
  14.   *
  15.   * @author
  16.   * @since
  17.   * @version $Id$
  18.   */
  19.   public class <XDtClass:className/> extends BaseController {
  20.
  21.   // CUT AND PASTE THIS INTO THE mytest-servlet.xml FILE
  22.   //
  23.   //  <!-- ==== <XDtClass:className/> Bean Definition ==== -->
  24.   // <bean id="contr<XDtClass:className/>" class="<XDtPackage:packageName/>.<XDtClass:className/>">
  25.   //  <property name="methodNameResolver" ><ref bean="actionResolver"/></property>
  26.   <XDtField:forAllFields>
  27.     <XDtField:ifHasFieldTag tagName="mytest.controller">
  28.   //  <property name="<XDtField:fieldTagValue tagName="mytest.controller" paramName="property"/>"><value><XDtField:fieldTagValue tagName="mytest.controller" paramName="propertyValue"/></value></property>
  29.     </XDtField:ifHasFieldTag>
  30.     </XDtField:forAllFields>
  31.   // </bean>
  32.   //
  33.   // === PUT THIS UNDER THE URL MAPPINGS SECTION ===
  34.   // <prop key="<XDtClass:classTagValue tagName="mytest.controller" paramName="mapping"/>">contr<XDtClass:className/></prop>
  35.   //
  36.
  37.     protected final Log log = LogFactory.getLog(getClass());
  38.
  39.    <XDtField:forAllFields>
  40.     <XDtField:ifHasFieldTag tagName="mytest.controller">
  41.       public <XDtField:fieldTagValue tagName="mytest.controller" paramName="propertyType"/> get<XDtField:fieldTagValue tagName="mytest.controller" paramName="propertyMethod"/>(){
  42.           return <XDtField:fieldTagValue tagName="mytest.controller" paramName="property"/>;
  43.       }
  44.
  
  45.       public void set<XDtField:fieldTagValue tagName="mytest.controller" paramName="propertyMethod"/>(<XDtField:fieldTagValue tagName="mytest.controller" paramName="propertyType"/> value) {
  46.       <XDtField:fieldTagValue tagName="mytest.controller" paramName="property"/> = value;
  47.       }
  48.    </XDtField:ifHasFieldTag>
  49.    </XDtField:forAllFields>
  50.
  51.     public ModelAndView init(HttpServletRequest request, HttpServletResponse response)
  52.       throws ServletException, IOException {
  53.       if(log.isDebugEnabled()) log.debug("entered");
  54.       // YOUR INIT CODE GOES HERE
  55.       if(log.isDebugEnabled()) log.debug("exited");
  56.       // REPLACE THIS HERE IN YOUR CODE
  57.       return null;
  58.     }
  59.
  60.    <XDtClass:forAllClassTags tagName="mytest.controller">
  61.     <XDtClass:ifHasClassTag tagName="mytest.controller" paramName="actionmethod">
  62.     public ModelAndView <XDtClass:classTagValue tagName="mytest.controller" paramName="actionmethod"/>(HttpServletRequest request, HttpServletResponse response)
  63.       throws ServletException, IOException {
  64.       if(log.isDebugEnabled()) log.debug("entered");
  65.
  66.       if(log.isDebugEnabled()) log.debug("exited");
  67.       // RETURN THE PROPER VIEW HERE
  68.       return null;
  69.     }
  70.
  71.     </XDtClass:ifHasClassTag>
  72.    </XDtClass:forAllClassTags>
  73.
  74.     // Your (other) multiaction methods go here
  75.
  76.   } // <XDtClass:className/>
  
  恩,當這些都完成的時候,我們擁有了一個控制器類,包含對應于Spring中定義bean和URL mapping的mytest-servlet.xml的XML代碼,為視圖屬性提供了適當的get/set方法,我的多action 方法,完整的Debug日志語句。從21行開始,包含了XML(將會被清除)的76行代碼,可以為我們節省大量的敲代碼的時間和排除錯誤。
  
  同時需要注重的是 XDtField 和 XDtClass 標簽?,F在應該很清楚的是我們為什么把不同的標簽值給替換了。我們所有的類級的標簽或者定義了類方法或者是XML配置文件的值,而field級別的標簽為我們產生get/set方法。像我前面說到的那樣,我們在這里對field的使用略有不同,因為我們在mytest-servlet.xml 中還利用它來做一些控制器的mapping值。當我們的控制器啟動的時候,Spring會為privateView 和 publicView方法注入合適的值。
  
  把他們整合到一起
  
  問題的最后就是如何把所有的這些東西整合到一起,而且讓我們可以看到產生的代碼。這就是為什么要把Ant引入的原因所在,我們將做下面3件事情:
  
  1.創建一個文件夾,從code base 分離出來,這將是我們保存假的源文件的地方和自動產生的源文件的地方。
  
  2.為我們的模板創建一個目錄。
  
  3.為代碼生成創建一個Ant任務。
  
  在我開發的機器上有如下的文件夾結構
  trunk
  
  +----+- src
  +- xdoclet
  
  +- build
  +- src
  +- com/mytest/account/controller
  +- template
  
  起初,看起來可能有點糊涂,因為這里有兩個src。但是我感覺有個重要的原因就是,我在xdoclet下有一個單獨的src可以讓我把假的源代碼(譯者按,就是要被填充的java文件)和產生的代碼分開。在我運行Ant任務以后,有一個文件就是怎么把文件拷貝到主src目錄(與xdoclet同一級別的)并且把產生的代碼加進去。為達到這篇文章的目的,我把這些東西從source code 分離出來,這也許能防止把在把所有的生成混成一團的時候帶來的各種問題。
  
  根據上面的文件夾結構,這是我們的文件應該在的地方:
  
  trunk/src/xdoclet/src/com/mytest/account/controller/TestController.java
  
  trunk/src/xdoclet/template/MultiController.xdt
  
  .java文件需要包名來與文件夾對應,這樣XDoclet才能熟悉它,并根據它來運行模板。我發現XDoclet只是把log4j的Debug級別設置到INFO, 當我沒有把.java文件放到正確的位置的時候,XDoclet不會顯示任何的錯誤信息,也發現不了也生成不了文件。只有我查看了.jar文件并修改了log4j.properties 以后正確的顯示沒有要處理的錯誤信息才被顯示。從技術角度說,這不是一個錯誤,但是它讓我琢磨了很長的時間,所以要注重這一點。
  
  接下來的Ant任務,使用上面的樹并且在正確的目錄里生成代碼。
  
  1.   <!-- ========Xdoclet Target ======== -->
  2.
  3. <target name="xdoclet">
  4.
  5. <path id="xdoclet.classpath">
  6.  <fileset dir="${xdoc.home}/lib">
  7.   <include name="*.jar"/>
  8.  </fileset>
  9. </path>
  10.
  11. <echo>+------------------------------------+</echo>
  12. <echo>Generating sources from xdoclet tree</echo>
  13. <echo>+------------------------------------+</echo>
  14.
  15. <taskdef name="doclet" classname="xdoclet.DocletTask" classpathref="xdoclet.classpath" />
  16. <doclet destdir="${jxdoc.dir}/build"
  17.   verbose="true">
  18.  <fileset dir="${jxdoc.dir}/src">
  19.   <include name="**/*Controller.java" />
  20.  </fileset>
  21.  <template
  22.    templateFile="${jxdoc.dir}/template/MultiController.xdt"
  23.    destinationFile="{0}.java"
  24.    suBTaskName="Create Controller file(s).." />
  25. </doclet>
  26.
  27. </target>
  
  想要運行這個,需要做一些配置。
  
  1.第6行xdoc.home 應該指向你的XDoclet的安裝目錄。
  
  2.22行為我們的模板文件定義了一個位置和名字。
  
  3.24行指定當doclet運行的時候XDoclet要輸出到控制臺的任務的名稱信息。這只是為了方便而已。
  
  你可以通過下面的命令來運行: ant xdoclet.
  
  假如一切運行正常的話,你應該能看到BUILD SUCCESSFUL的消息。在xdoclet/build/com/mytest/account/controller 目錄下,你的新的文件就應該出現,文件中有必要的骨架屬性和方法。
  
  這個模板可以別修改成不單單產生控制器而且可以產生Bean,Form,Service等等。在xdoclet 中,你只需要為每一個你想要生成的對象類型增加一個新的taskdef然后提供一個不同的模板。比喻說,假如你想產生service對象,你可以使用下面的taskdef:
  
  1. <taskdef name="servicedoclet" classname="xdoclet.DocletTask" classpathref="xdoclet.classpath" />
  2. <servicedoclet destdir="${jxdoc.dir}/build"
  3.    verbose="true">
  4.  <fileset dir="${jxdoc.dir}/src">
  5.   <include name="**/*Service.java" />
  6.  </fileset>
  7.  <template
  8.    templateFile="${jxdoc.dir}/template/Service.xdt"
  9.    destinationFile="{0}.java"
  10.    subTaskName="Create Service files(s).." />
  11. </doclet>
  
  在上面的代碼中,我們看到我把taskdef 的名字改成servicedoclet,并且包含的fileset屬性由*.Controller.java變成*.Service.java, 這將導致任務只去查找以"Service.java."結尾的文件。
  
  在第8行,我們告訴XDoclet使用Service.xdt模板。所以假如我們已經完成初始化工作的話,我們很輕易就能增加一個特定的代碼生成器。完全可能的是(我也正是這樣做的),我們可以在xdoclet任務下生成很多的模板,在這個任務下,讓它一次把每一個對象類型都讀到然后一次性的把每樣東西都生成完畢。
  
  Maven 2.0 和原型的一句話: Maven 2.0 包含了一種稱為原型的機制,它答應基于模板驅動的工程代碼生成。但是實現方式有所不同--Maven使用Velocity 來生成模板--與我們上面講的那些相比,基本上完成同樣的事情,但是工作范圍是在更大的project范圍。
  
  我試過很多次使用Maven ,我很欣賞這個做法。但是我感覺,從上面的例子來說,Maven 需要花費更多的程序員的努力時間(在剛開始的時候)。但Maven 正好說明了我前面提出的我關心的問題,我喜歡基于Rails在project級別和其他程序員合作。當然,Maven,也可以在project級別工作,通過配置參數來生成代碼,從而為程序員節省大量的時間。這才是最有實際意義的一件事情。對于已經存在的工程,這里講到的方法都是一種更快的有著更少結構沖突的實現方式。
  
  結論
  
  下面就是我們這篇文章所提到的:
  
  1.創建了一個不但能生成類,而且能為我們的框架生成必要的XML配置文件的定制的pseudo-Java文件。在我們的例子里,我們定義了一個定制的可以用在Spring Web服務器里的控制器。
  
  2.定義了一個包含了一些我們的類的靜態元素和一些可以在運行的時候提供動態類代碼的組合的XDoclet XML 標簽的模板文件。
  
  3.建立一個文件夾結構和Ant任務,它將調用XDoclet來產生我們的骨干控制器類。
  
  這只討論了XDoclet的皮毛。我們只看到一個小型的,還有點作用的例子,它展示了模板幫助你不但成為一個更有效率的程序員,并且是成為更聰明的一個。我希望它可以為你節省更多的時間。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美性猛交xxxx免费看| 亚洲成人中文字幕| 欧美一级淫片播放口| 欧美精品日韩www.p站| 久久精品视频中文字幕| 亚洲欧洲成视频免费观看| 精品久久久精品| 97在线免费观看| 国产精品户外野外| 欧美成人午夜激情在线| 欧美精品www在线观看| 日韩美女视频免费看| 精品国产区一区二区三区在线观看| 91精品国产九九九久久久亚洲| 国产在线观看精品| 国产精品mp4| 一区二区三区久久精品| 最新国产精品拍自在线播放| 久久伊人免费视频| 久久人人爽人人爽爽久久| 成人免费观看49www在线观看| www.色综合| 丝袜亚洲另类欧美重口| 欧美小视频在线观看| 日韩大陆欧美高清视频区| 伊人久久久久久久久久久| 九九久久精品一区| 国产精品爽爽爽爽爽爽在线观看| 亚洲欧美另类自拍| 一区二区三区在线播放欧美| 欧美日韩国产麻豆| 亚洲精选中文字幕| 中文字幕日韩高清| 高清在线视频日韩欧美| 成人福利网站在线观看11| 国产精品久久999| 亚洲成人免费在线视频| 激情成人在线视频| 国产91色在线免费| 精品国内产的精品视频在线观看| 日本久久精品视频| 在线电影av不卡网址| 成人h视频在线| 91社区国产高清| 色婷婷av一区二区三区在线观看| 国产美女主播一区| 久久久av网站| 日韩视频―中文字幕| 亚洲精品美女久久久久| 97精品国产97久久久久久免费| 日韩福利伦理影院免费| 久久香蕉国产线看观看网| 日韩成人在线视频网站| 国产一区二中文字幕在线看| 欧美性猛交xxxx黑人| 国产精品美女免费| 亚洲天堂网站在线观看视频| 国产精品一区av| 久久精品国产69国产精品亚洲| 精品久久久久久久久国产字幕| 国产精品久久久久久亚洲影视| 亚洲综合社区网| 中日韩美女免费视频网站在线观看| 欧美激情videoshd| 久久九九有精品国产23| 亚洲精品中文字幕av| 欧美在线日韩在线| 国产99久久精品一区二区 夜夜躁日日躁| 中文字幕在线看视频国产欧美在线看完整| 日韩精品视频免费专区在线播放| 欧美日韩激情美女| 色爱精品视频一区| 久久好看免费视频| 亚洲精品成人久久电影| 亚洲色无码播放| 欧美性xxxxx极品娇小| xxav国产精品美女主播| 2019亚洲日韩新视频| 欧美激情按摩在线| 国产精品色午夜在线观看| 久久精品视频中文字幕| 伊人伊成久久人综合网站| 一本一道久久a久久精品逆3p| 日韩av一区在线| 一区二区日韩精品| 亚洲国产精久久久久久久| 日韩av第一页| 色悠悠久久88| 久久久久久国产三级电影| 成人信息集中地欧美| 亚洲精品色婷婷福利天堂| 在线播放亚洲激情| 亚洲free性xxxx护士hd| 亚洲一区二区中文| 欧美日韩亚洲视频| 日本高清视频一区| 国产成人精品电影久久久| 久久高清视频免费| 成人黄色在线观看| 欧美丰满片xxx777| 欧美精品一二区| 国产99久久精品一区二区 夜夜躁日日躁| 日韩hd视频在线观看| 日产精品久久久一区二区福利| 红桃视频成人在线观看| 精品国产网站地址| 日韩欧美主播在线| 中文字幕视频在线免费欧美日韩综合在线看| 欧美高清激情视频| 亚洲香蕉av在线一区二区三区| 久久久久女教师免费一区| 91视频免费网站| 欧美国产日韩xxxxx| 性金发美女69hd大尺寸| 亚洲已满18点击进入在线看片| 精品国产一区二区三区久久狼5月| 国产精品中文在线| 亚洲级视频在线观看免费1级| 久久精品国产欧美亚洲人人爽| 欧美高清视频免费观看| 国产精品一区久久久| 亚洲经典中文字幕| 搡老女人一区二区三区视频tv| 久久久久www| 欧美成人四级hd版| 日韩电影大全免费观看2023年上| 日韩电影免费观看在线观看| 国产一区二区美女视频| 日韩av最新在线| 国产丝袜精品视频| 91经典在线视频| 精品成人久久av| 在线看日韩欧美| 亚洲一区二区三区视频| 欧美视频免费在线| 成人在线视频网站| 亚洲精品欧美日韩| 国产精品露脸自拍| 国产一区二区精品丝袜| 欧美xxxwww| 国产精品1234| 欧美在线视频a| 热久久这里只有精品| 欧美成人精品一区二区三区| 懂色av一区二区三区| 国产精品久久久久久久久久久久久久| 日韩高清电影免费观看完整| 久久久久久久97| 55夜色66夜色国产精品视频| 国产99久久精品一区二区 夜夜躁日日躁| 欧美性受xxx| 日本久久精品视频| 欧美大片在线看| 北条麻妃久久精品| 色综合色综合网色综合| 97在线免费视频| 欧美电影在线观看高清| 亚洲a成v人在线观看| 国产在线播放91| 国产91精品不卡视频| 欧美成人一区二区三区电影| 亚洲一区中文字幕在线观看| 日韩av网站大全| 韩国精品久久久999|