技术开发 频道

单元测试指导


  
四.AppFuse中的xdoclet
Xdoclet是一个自动生成代码的工具。它的任务就是Ant的自定义任务。XdocletAnt紧密关联。它有两个重要的组件:即进行特殊标记的Java 源文件和预先定义的模板。
Apache Ant 在运行的时候控制着 XDoclet 的配置和操作。XDoclet 解析输入的 Java 源代码,并在内存中生成结构模型。模板引擎通过处理一组模板和标签处理器,生成输出文件。
1.进行特殊标记的Java源文件
AppGen生成的文件缺少hbm.xml、Action Form Bean、web.xml、struts-config.xml和validation.xml等文件,那这些文件是怎么生成的呢?
原来,这些文件都是在我们执行ant setup命令时build.xml使用xdoclet自动生成的。 甚至连数据库和表、表里的数据也可以自动生成。
XDoclet 对包含嵌入式 XDoclet 标签的输入 Java 源代码进行解析,并为代码建立非常详细的结构模型。结构模型中的每个元素都代表源代码中的一个 Java 结构。
    查看User.java、Role.java以及Address.java发现,这些POJO文件中有很多注释,有@hibernate开头的,@struts开头的,这些都是xdoctlet的标签。AppFuse中主要用到的xdoclet标签如下:
  1@struts.form:用来生成Form Bean。
include-all="true":表示该POJO中每一个属性在Form Bean中都要有;
extends="BaseForm":表示生成的Form Bean文件要继承BaseForm;@struts.form-field:表示该属性要在FormBean中生成。如果我们要在FormBean中添加一些POJO没有的属性或方法怎么做呢?打开metadata\web文件夹,可以看到有一个xdoclet-UserForm.java文件,里面是User.java在生成Form Bean时新加入的代码,我们同样可以把我们自己在FormBean中增加的代码新建到一个xdoclet-POJOFrom.java文件中就好了。
2@struts.validator:用来生成validation.xml文件。
type="required":表示该属性在表单中需要有必填的验证。validation还有一项配置是自定义的校验规则,使用正则表达式表示。metadata\web中有一个文件validation-global.xml,里面就有邮编等规则的配置。
3@hibernate:用来生成hbm.xml文件。内容与hbm.xml基本一致。
4@struts.action/@struts.action-forward:POJO不能生成struts-config.xml,这个标签是要写到Action中的。如果使用AppGen生成Action,你会看到@struts.action已经写好了,这个标签的作用就是生成当前Action在struts-config.xml中的映射代码,写法与struts-config.xml中一致,其实就是把xml中的配置移植到Action中。还有一个问题,如果我们要在struts-config.xml中进行与Action无关的全局的配置,如global-forwards呢?浏览metadata\web文件夹你会发现里面有多个xml文件,其中以global和struts开头的文件就是写这些配置的。build.xml在setup时会自动将这些文件联合Action中的注释生成一个完整的struts-config.xml文件。
    接下来还有web.xml文件,它需要在metadata\web中配置。除了刚才提到的那些xml文件,剩下的基本都是用于配置web.xml的了。我们自定义的filter和listener是有具体类的,所以我们同样可以在这些filter和listener类中添加注释。
    进行了所有配置后,运行ant setup,build.xml会生成对应的xml文件和form bean等,并在数据库中创建相应的表。
2.预先定义的模版
   XDoclet使用代码模板来生成代码。模板(template)是你想生成文件的原型。模板里使用一些XML标签来指导模板引擎如何根据输入类以及它们的元数据来调整代码的生成。
模板包含文件和XML标签,生成输出文件时XML标签会被解析,然后生成文本并显示在XML标签所处的位置上。除了以xdt为命名空间打头的XML标签会被XDoclet引擎解析以外,其余的XML标签XDoclet会忽略不管。
AppFuse中用到很多预先定义的模版,例如AppFuse中生成Action类的XDoclet模板,部分内容如下所示:
public final class <XDtClass:className/>Action extends BaseAction { public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { if (log.isDebugEnabled()) { log.debug("Entering 'delete' method"); } ActionMessages messages = new ActionMessages(); <XDtClass:className/>Form <XDtForm:classNameLower/>Form = (<XDtClass:className/>Form) form; // Exceptions are caught by ActionExceptionHandler Manager mgr = (Manager) getBean("manager"); mgr.removeObject(<XDtClass:className/>.class, new Long(<XDtForm:classNameLower/>Form.getId())); messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("<XDtForm:classNameLower/>.deleted")); // save messages in session, so they'll survive the redirect saveMessages(request.getSession(), messages); return search(mapping, form, request, response); } … … }

 
在如上的模版中,可看到<XDtClass:className/>、<XDtForm:classNameLower/>等标签,在生成代码的时候,这些标签会被解析,解析后在这些位置会填上对应的代码。
 
五.总结
AppFuse是个大杂烩,在它里面有很多开源库,主要分类如下:
编译相关:AntAnt Contrib TasksCheckstyleJava2HtmlPMD
测试框架:DbUnitjMockJUnit
数据库驱动程序:MySQL PostgreSQL
持久层框架:Hibernate iBATIS
IoCAOP 框架:Spring
Web MVC框架:JSF、Spring MVC、Struts、Tapestry 和 WebWork
安全:Acegi Security
除了这些库之外,AppFuse 还使用 Log4j 来记录日志,使用 Velocity 来构建 e-mail 和菜单模板等。
另外,AppFuse 并不会将我们限定到任何特定的 API 上。它只是简单地对可用的非常好的开放源码解决方案重新进行打包和预先集成。AppFuse 中的代码可以处理这种集成,并实现了 AppFuse 的基本安全性和可用性特性。只要可能,就会减少代码,以便向 AppFuse 的依赖框架添加一个特性。
   从本文可以看来,AppFuse通过减少编写CRUD代码的时间,大大提高了我们编码的效率,是我们开发项目时的好帮手。
0
相关文章