麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

通過XDoclet定制模板進(jìn)行快速開發(fā)

2019-11-18 12:47:03
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  最近與同是開發(fā)者的朋友一起,談?wù)摳鞣N各樣java的之外的構(gòu)架。似乎有一些現(xiàn)象表明, Java正在因?yàn)樵S多原因成為Web發(fā)展的障礙,其中一個(gè)問題是代碼行(LOC)。做同一件事情,Java的某一些參數(shù)需要其他語(yǔ)言的2倍的代碼量,我個(gè)人以為L(zhǎng)OC僅僅是一個(gè)問題,它讓你把一些本不該花的時(shí)間都花在你本不該去做的事情上。例如,象手工編寫你所有的Bean一樣。 或許你也正在手工的為你的構(gòu)架xml定義所有的條目,以此來(lái)節(jié)約時(shí)間, 我承認(rèn), 我正是這樣。
  
  不久之前我使用RubyOnRails,一個(gè)讓我喜歡用它們的原因就是他們能很輕易產(chǎn)生完全的代碼,從簡(jiǎn)單的script到復(fù)雜的代碼。 這讓我考慮我當(dāng)前的工作和編碼期間我的有效情況是怎么樣的。 “我做好了多少工作VS我花費(fèi)多少時(shí)間”的思想在過去的數(shù)星期內(nèi)不停的在我腦子里縈繞。雖然有各種框架幫助我們使工作變的輕易一些—--比喻說(shuō)在使用的SPRing—--它一些時(shí)候看起來(lái)很粗笨,為一個(gè)web應(yīng)用程序做一個(gè)頁(yè)面或者一個(gè)模塊就需要很長(zhǎng)的時(shí)間。因此在一些思考以后, 我決定了做一些東西。
  
  我多年前已經(jīng)知道XDoclet,并且在它首次出現(xiàn)的時(shí)候試用了它。但是我沒有進(jìn)行長(zhǎng)期的考慮, 所以當(dāng)時(shí)我還不是一個(gè)在代碼生成方面的大拿。我想要了解事情到底是怎么工作的, 因此我花了大量時(shí)間手工編寫任何代碼,包括config文件和deployment文件。
  
  然而,我今天發(fā)現(xiàn)代碼生成的兩個(gè)主要的益處:
  
  1.你在想學(xué)什么東西的時(shí)候,它將是很有幫助的。比喻說(shuō),去年我想學(xué)Hibernate 的時(shí)候,我已經(jīng)有了存在的表,不想再反復(fù)的測(cè)試它是怎么工作的了,我也不想花大量的時(shí)間來(lái)填寫文檔。使用一個(gè)方便的叫做Middlegen的工具,我只要告訴它查看我的數(shù)據(jù)庫(kù)并且為我生成代碼就可以了。現(xiàn)在,寫一個(gè)mapping文件對(duì)我來(lái)說(shuō)已經(jīng)很輕易了,可是Middlegen的幫助節(jié)省了我大量的時(shí)間并為我指明了方向。
  
  2.在對(duì)你的工程有一個(gè)清楚的概念和一個(gè)結(jié)構(gòu)甚至一個(gè)框架已經(jīng)搭建起來(lái)后,接下來(lái)的事情將變的十分的乏味,手工的創(chuàng)建beans,controllers, services 和 DAO,每次都會(huì)有一些新的需求要被創(chuàng)建。理想的做法是,你也許會(huì)調(diào)用一些Ant任務(wù),比喻說(shuō), gencontrollers或者genmodules 來(lái)生成合適的controller代碼或者一個(gè)整個(gè)的包含你的beans, controllers, services和DAO的模塊.
  
  使用XDoclet 來(lái)減輕痛苦
  
  基于過去的一些經(jīng)驗(yàn),我不敢確信XDoclet對(duì)我有多大的幫助。我想要尋找一個(gè)工具讓我可以花最少的時(shí)間來(lái)生成最多的代碼。我在XDoclet網(wǎng)站上看到的大部分的示例都是針對(duì)于EJB的生成的,其實(shí)這也是XDoclet設(shè)計(jì)的初衷。但是,情況是這樣的,我的工程不含有任何的EJB代碼,事實(shí)上Spring全部是關(guān)于POJO的東西,所以EJB方面的工具不是我需要的。同時(shí),XDoclet不含有任何的Spring標(biāo)簽,所以我一直在尋找一個(gè)不同平常的什么東西。
  
  最后我把目光投上了模板。模板是一種繼續(xù)XDoclet功能來(lái)更好的滿足你的代碼生成要求的方法。例如,你有一個(gè)非凡類型的類,與XDoclet所支持的任何一種都很不同(在我看來(lái)是一些客戶化的控制類),你就可以用XML文件來(lái)把你自己的模板加進(jìn)去。理想化的,我只想定義一個(gè)含有最小量的屬性并不但產(chǎn)生我的控制器代碼而且另外的Spring所要求的XML文件。在實(shí)驗(yàn)了幾次以后,我對(duì)結(jié)果很滿足。下面就是加標(biāo)注的假設(shè)的代碼測(cè)試控制器類。長(zhǎng)代碼行以/分開。
  
  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標(biāo)簽。這個(gè)是在生成我們類的不同部分時(shí),XDoclet如何知道去查找什么。標(biāo)簽的位置十分的重要。一些在類要害字的上面一些在屬性定義的下面。XDoclet根據(jù)不同位置的標(biāo)簽來(lái)生成在我們的模板中使用的類和屬性對(duì)象。這是一個(gè)很重要的區(qū)別,我們將在接下來(lái)研究。
  
  看一下上面的代碼,我們將做下面的操作:
  
  1.為SimpleUrlHandlerMapping建立一個(gè)Spring mapping入口,它將在一個(gè)叫做mytest-servlet.xml 文件中被描述(是Spring中與Struts中的struts-config.xml 類似的東西).
  
  2.actionmethod 屬性答應(yīng)我們?yōu)橐粋€(gè)控制器指定一個(gè)方法名,它是從Srping的MultiActionController 繼續(xù)而來(lái) (在Struts, 對(duì)應(yīng)的是 DispatchAction)。在我們的例子中,將會(huì)有 CRUD (Create, Read, Update, Delete)這么幾個(gè)方法名。 XDoclet將會(huì)重復(fù)的進(jìn)行不同參數(shù)的相同方法名的方法,所以答應(yīng)我們的模板輸出N個(gè)方法。
  
  3.property 標(biāo)簽 讓我們 定義一個(gè)典型的Bean屬性,像你通常在XDoclet中做的一樣,因?yàn)槲覀冊(cè)谶@里使用了一個(gè)定制的模板,我們?cè)黾恿烁嗟膶傩?。propertyValue 是為mytest-servlet.xml 中對(duì)應(yīng)的屬性所指定的值。對(duì)我們的定制的標(biāo)簽來(lái)說(shuō),我們正在為控制器類設(shè)置private的和public的jsp頁(yè)面顯示,我通常管它們叫privateView和publicView—一個(gè)是針對(duì)簽發(fā)者的另一是針對(duì)每一個(gè)人的。propertyMethod 將為我們提供一種簡(jiǎn)單的方法來(lái)類指定這個(gè)屬性屬于那一個(gè)方法,而不用去跳過bean-method-naming的約束。propertyType 屬性指定了我們將要為這個(gè)方法get/set什么類型的屬性。
  
  很有爭(zhēng)議的是,我可能把所有的屬性定義發(fā)在類的層次上而不是Field的層次上。這也未嘗不可,但是這將為在模板上增加額外的代碼來(lái)確定在產(chǎn)生一個(gè)方法的時(shí)候我使用了正確的屬性,方法,類型。我感覺使用XDoclet的Field 類比往我的模板里增加復(fù)雜的代碼要輕易和迅速。
  
  模板
  
  好了,現(xiàn)在讓我們開始干活吧。正像我前面提到的那樣,我選擇XDoclet來(lái)生成代碼的原因是我將定義一套定制的模板(不是一些定制的類或者更多的代碼)并使用XDoclet的XML標(biāo)簽來(lái)為我填充這些空白。下面所列就是我們想要生成的模板相應(yīng)的部分。長(zhǎng)代碼已經(jīng)被/ 分開。
  
  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/>
  
  恩,當(dāng)這些都完成的時(shí)候,我們擁有了一個(gè)控制器類,包含對(duì)應(yīng)于Spring中定義bean和URL mapping的mytest-servlet.xml的XML代碼,為視圖屬性提供了適當(dāng)?shù)膅et/set方法,我的多action 方法,完整的Debug日志語(yǔ)句。從21行開始,包含了XML(將會(huì)被清除)的76行代碼,可以為我們節(jié)省大量的敲代碼的時(shí)間和排除錯(cuò)誤。
  
  同時(shí)需要注重的是 XDtField 和 XDtClass 標(biāo)簽。現(xiàn)在應(yīng)該很清楚的是我們?yōu)槭裁窗巡煌臉?biāo)簽值給替換了。我們所有的類級(jí)的標(biāo)簽或者定義了類方法或者是XML配置文件的值,而field級(jí)別的標(biāo)簽為我們產(chǎn)生get/set方法。像我前面說(shuō)到的那樣,我們?cè)谶@里對(duì)field的使用略有不同,因?yàn)槲覀冊(cè)趍ytest-servlet.xml 中還利用它來(lái)做一些控制器的mapping值。當(dāng)我們的控制器啟動(dòng)的時(shí)候,Spring會(huì)為privateView 和 publicView方法注入合適的值。
  
  把他們整合到一起
  
  問題的最后就是如何把所有的這些東西整合到一起,而且讓我們可以看到產(chǎn)生的代碼。這就是為什么要把Ant引入的原因所在,我們將做下面3件事情:
  
  1.創(chuàng)建一個(gè)文件夾,從code base 分離出來(lái),這將是我們保存假的源文件的地方和自動(dòng)產(chǎn)生的源文件的地方。
  
  2.為我們的模板創(chuàng)建一個(gè)目錄。
  
  3.為代碼生成創(chuàng)建一個(gè)Ant任務(wù)。
  
  在我開發(fā)的機(jī)器上有如下的文件夾結(jié)構(gòu)
  trunk
  
  +----+- src
  +- xdoclet
  
  +- build
  +- src
  +- com/mytest/account/controller
  +- template
  
  起初,看起來(lái)可能有點(diǎn)糊涂,因?yàn)檫@里有兩個(gè)src。但是我感覺有個(gè)重要的原因就是,我在xdoclet下有一個(gè)單獨(dú)的src可以讓我把假的源代碼(譯者按,就是要被填充的java文件)和產(chǎn)生的代碼分開。在我運(yùn)行Ant任務(wù)以后,有一個(gè)文件就是怎么把文件拷貝到主src目錄(與xdoclet同一級(jí)別的)并且把產(chǎn)生的代碼加進(jìn)去。為達(dá)到這篇文章的目的,我把這些東西從source code 分離出來(lái),這也許能防止把在把所有的生成混成一團(tuán)的時(shí)候帶來(lái)的各種問題。
  
  根據(jù)上面的文件夾結(jié)構(gòu),這是我們的文件應(yīng)該在的地方:
  
  trunk/src/xdoclet/src/com/mytest/account/controller/TestController.java
  
  trunk/src/xdoclet/template/MultiController.xdt
  
  .java文件需要包名來(lái)與文件夾對(duì)應(yīng),這樣XDoclet才能熟悉它,并根據(jù)它來(lái)運(yùn)行模板。我發(fā)現(xiàn)XDoclet只是把log4j的Debug級(jí)別設(shè)置到INFO, 當(dāng)我沒有把.java文件放到正確的位置的時(shí)候,XDoclet不會(huì)顯示任何的錯(cuò)誤信息,也發(fā)現(xiàn)不了也生成不了文件。只有我查看了.jar文件并修改了log4j.properties 以后正確的顯示沒有要處理的錯(cuò)誤信息才被顯示。從技術(shù)角度說(shuō),這不是一個(gè)錯(cuò)誤,但是它讓我琢磨了很長(zhǎng)的時(shí)間,所以要注重這一點(diǎn)。
  
  接下來(lái)的Ant任務(wù),使用上面的樹并且在正確的目錄里生成代碼。
  
  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>
  
  想要運(yùn)行這個(gè),需要做一些配置。
  
  1.第6行xdoc.home 應(yīng)該指向你的XDoclet的安裝目錄。
  
  2.22行為我們的模板文件定義了一個(gè)位置和名字。
  
  3.24行指定當(dāng)doclet運(yùn)行的時(shí)候XDoclet要輸出到控制臺(tái)的任務(wù)的名稱信息。這只是為了方便而已。
  
  你可以通過下面的命令來(lái)運(yùn)行: ant xdoclet.
  
  假如一切運(yùn)行正常的話,你應(yīng)該能看到BUILD SUCCESSFUL的消息。在xdoclet/build/com/mytest/account/controller 目錄下,你的新的文件就應(yīng)該出現(xiàn),文件中有必要的骨架屬性和方法。
  
  這個(gè)模板可以別修改成不單單產(chǎn)生控制器而且可以產(chǎn)生Bean,F(xiàn)orm,Service等等。在xdoclet 中,你只需要為每一個(gè)你想要生成的對(duì)象類型增加一個(gè)新的taskdef然后提供一個(gè)不同的模板。比喻說(shuō),假如你想產(chǎn)生service對(duì)象,你可以使用下面的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, 這將導(dǎo)致任務(wù)只去查找以"Service.java."結(jié)尾的文件。
  
  在第8行,我們告訴XDoclet使用Service.xdt模板。所以假如我們已經(jīng)完成初始化工作的話,我們很輕易就能增加一個(gè)特定的代碼生成器。完全可能的是(我也正是這樣做的),我們可以在xdoclet任務(wù)下生成很多的模板,在這個(gè)任務(wù)下,讓它一次把每一個(gè)對(duì)象類型都讀到然后一次性的把每樣?xùn)|西都生成完畢。
  
  Maven 2.0 和原型的一句話: Maven 2.0 包含了一種稱為原型的機(jī)制,它答應(yīng)基于模板驅(qū)動(dòng)的工程代碼生成。但是實(shí)現(xiàn)方式有所不同--Maven使用Velocity 來(lái)生成模板--與我們上面講的那些相比,基本上完成同樣的事情,但是工作范圍是在更大的project范圍。
  
  我試過很多次使用Maven ,我很欣賞這個(gè)做法。但是我感覺,從上面的例子來(lái)說(shuō),Maven 需要花費(fèi)更多的程序員的努力時(shí)間(在剛開始的時(shí)候)。但Maven 正好說(shuō)明了我前面提出的我關(guān)心的問題,我喜歡基于Rails在project級(jí)別和其他程序員合作。當(dāng)然,Maven,也可以在project級(jí)別工作,通過配置參數(shù)來(lái)生成代碼,從而為程序員節(jié)省大量的時(shí)間。這才是最有實(shí)際意義的一件事情。對(duì)于已經(jīng)存在的工程,這里講到的方法都是一種更快的有著更少結(jié)構(gòu)沖突的實(shí)現(xiàn)方式。
  
  結(jié)論
  
  下面就是我們這篇文章所提到的:
  
  1.創(chuàng)建了一個(gè)不但能生成類,而且能為我們的框架生成必要的XML配置文件的定制的pseudo-Java文件。在我們的例子里,我們定義了一個(gè)定制的可以用在Spring Web服務(wù)器里的控制器。
  
  2.定義了一個(gè)包含了一些我們的類的靜態(tài)元素和一些可以在運(yùn)行的時(shí)候提供動(dòng)態(tài)類代碼的組合的XDoclet XML 標(biāo)簽的模板文件。
  
  3.建立一個(gè)文件夾結(jié)構(gòu)和Ant任務(wù),它將調(diào)用XDoclet來(lái)產(chǎn)生我們的骨干控制器類。
  
  這只討論了XDoclet的皮毛。我們只看到一個(gè)小型的,還有點(diǎn)作用的例子,它展示了模板幫助你不但成為一個(gè)更有效率的程序員,并且是成為更聰明的一個(gè)。我希望它可以為你節(jié)省更多的時(shí)間。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 午夜国产成人 | 亚洲免费视频一区二区 | 日本视频网| 国产一级免费av | 国产精品亚洲一区二区三区久久 | 一级毛片特黄 | 综合网日日天干夜夜久久 | 久久99国产精品久久99果冻传媒 | 97视频 | 久久精品一区二区三 | 国产一级一区二区 | 一级电影免费 | 成年免费在线视频 | 日韩黄色免费在线观看 | 亚洲第一色婷婷 | 亚洲成人伊人 | 美女在线观看视频一区二区 | 成人免费午夜视频 | 亚洲成人中文字幕在线 | 色99久久 | 91久久久国产精品 | 久久骚 | 欧美一级性 | 国产亚洲精品精 | 免费观看高清视频网站 | 成人富二代短视频 | 国产一级在线看 | 黄色电影免费网址 | 黄色久 | 孕妇体内谢精满日本电影 | www.17c亚洲蜜桃 | 2021狠狠操 | 亚洲va久久久噜噜噜久久男同 | 国产欧美亚洲精品a | 久久成人福利 | 一区二区三视频 | 久久久久久久久久久国产精品 | 在线免费黄色网 | 毛片视频网站在线观看 | 日韩精品一区二区三区中文 | 国产精品久久久久久久午夜片 |