使用 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.java | Java 源文件,包含表单 bean 类,在 Struts 的表单处理中使用 | generated 目录 |
AddressBeanForm.jsp | JSP 表单,用 Struts 标签库接受用户地址输入 | jsp 目录 |
AddressBeanAction.java | Struts 动作类,接受输入值,用 Hibernate 把值保存到关系数据库 | generated 目录 |
AddressBean.hbm.xml | Hibernate 映射文件,在 AddressBean Java 对象和数据库的关系型 ADDRESS 表之间进行映射 | web/classes 目录 |
dwschema.sql | RDBMS 表的架构,用来对 AddressBean 对象的实例进行持久化 | sql 目录 |
hibernate.cfg.xml | Hibernate 运行时的配置文件 | web/classes 目录 |
web.xml | 生成的 Web 应用程序的部署描述符 | web 目录 |
struts-config.xml | Struts 框架的配置文件 | 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 任务 | 工件 |
genstruts | xdoclet.DocletTask | AddressBeanForm.java |
genstruts | xdoclet.DocletTask | AddressBeanForm.jsp |
genstruts | xdoclet.DocletTask | AddressBeanAction.java |
generateHIB | xdoclet.modules.hibernate.HibernateDocletTask | AddressBean.hbm.xml |
generateHIB | xdoclet.modules.hibernate.HibernateDocletTask | hibernate.cfg.xml |
createDDL | xdoclet.modules.hibernate.HibernateDocletTask | dwschema.sql |
generateDD | xdoclet.modules.web.WebDocletTask | web.xml |
generateDD | xdoclet.modules.web.WebDocletTask | struts-config.xml |