用XDoclet快速而容易的开发客户化模板

<!----><!----> <!-- /* Font Definitions */ @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:Verdana; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:536871559 0 0 0 415 0;} @font-face {font-family:"\@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:848981233; mso-list-template-ids:802194774;} @list l0:level1 {mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt;} @list l1 {mso-list-id:990063059; mso-list-template-ids:-1985988758;} @list l1:level1 {mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt;} @list l2 {mso-list-id:1050421959; mso-list-template-ids:-1951515512;} @list l2:level1 {mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt;} @list l3 {mso-list-id:1488664008; mso-list-template-ids:-496185514;} @list l3:level1 {mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt;} @list l4 {mso-list-id:1498499988; mso-list-template-ids:1329344206;} @list l4:level1 {mso-level-number-format:bullet; mso-level-text:; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt; mso-ansi-font-size:10.0pt; font-family:Symbol;} @list l5 {mso-list-id:1766685587; mso-list-template-ids:849530270;} @list l5:level1 {mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} --> <!---->

最近与同是开发者的朋友一起,谈论各种各样Java 的之外的构架。似乎有一些现象( 我不会讨论任何现象, 但是Googling 能很快的给你一些符合条件的结果) 表明, Java 正在因为许多原因成为Web 的老警卫( 译者按,应该是不成作用的没有成效的意思) ,其中一个是代码行(LOC) 。做同一件事情Java 的某一些参数需要其他语言的2 倍的代码量,我个人以为LOC 仅仅是一个问题,它让你把一些本不该花的时间都花在你本不该去做的事情上。例如,象手工编写你所有的Bean 一样, 或许你也正在手工的为你的构架XML 定义所有的条目! 我承认, 我正是这样。

不久之前我使用RubyOnRails ,一个让我喜欢用它们的原因就是他们能很容易产生完全的代码,从简单的script 到复杂的代码。 这让我考虑我的当前的工作和编码期间我的有效情况是怎么样的。 多少工作我做好VS 多少时间被做我花费试着把工作做好 的思想在过去的数星期内不停的在我脑子里萦绕。虽然有各种框架帮助我们使工作变的容易一些—-- 比喻说在使用的Spring—-- 它一些时候看起来很笨重,为一个web 应用程序做一个页面或者一个模块就需要很长的时间。因此在一些思考以后, 我决定了做一些东西。

我多年前已经知道XDoclet 并且在它首次出现的时候试用了它。但是我没有进行长期的考虑, 所以当时我还不是一个在代码生成方面的大拿。我想要了解事情到底是怎么工作的, 因此我花了大量时间手工编写任何代码,包括config 文件和deployment 文件。

然而,我今天发现代码生成的两个主要的益处:

 

  1. 你在想学什么东西的时候,它将是很有帮助的。比喻说,去年我想学Hibernate 的时候, 我已经有了存在的表,不想再反复的测试它是怎么工作的了,我也不想花大量的时间来填写文档。使用一个方便的叫做Middlegen 的工具,我只要告诉它查看我的数据库并且为我生成代码就可以了。现在,写一个mapping 文件对我来说已经很容易了,可是Middlegen 的帮助节省了我大量的时间并为我指明了方向。
  2. 在对你的工程有一个清晰的概念和一个结构甚至一个框架已经搭建起来后,接下来的事情将变的十分的乏味,手工的创建beanscontrollers, services DAO ,每次都会有一些新的需求要被创建。理想的做法是,你也许会调用一些Ant 任务,比喻说, gencontrollers 或者 genmodules 来生成合适的controller 代码或者一个整个的包含你的beans, controllers, servicesDAO 的模块.

使用 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 的和publicJSP 页面显示,我通常管它们叫 privateView publicView 一个是针对签发者的另一是针对每一个人的。 propertyMethod   将为我们提供一种简单的方法来类指定这个属性属于那一个方法,而不用去跳过bean-method-naming 的约束。 propertyType 属性指定了我们将要为这个方法get/set 什么类型的属性。

很有争议的是,我可能把所有的属性定义发在类的层次上而不是 Field 的层次上。这也未尝不可,但是这将为在模板上增加额外的代码来确定在产生一个方法的时候我使用了正确的属性,方法,类型。我感觉使用XDoclet Field 类比往我的模板里增加复杂的代码要容易和迅速。

模板

好了,现在让我们开始干活吧。正像我前面提到的那样,我选择XDoclet 来生成代码的原因是我将定义一套客户化的模板( 不是一些客户化的类或者更多的代码) 并使用XDocletXML 标签来为我填充这些空白。下面所列就是我们想要生成的模板相应的部分。长代码已经被 \ 分开。

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.             }

你可能感兴趣的:(spring,bean,xml,struts,servlet)