NetBeans UML 定制代码生成
注意:当前的发行版为 NetBeans IDE 6.5。如果您使用的是 NetBeans IDE 6.1,请参见 NetBeans UML 定制代码生成。
内置代码生成机制是 NetBeans 6.1/6.5 发行版的一个重要的新增 UML 功能。
使用“新建项目”向导创建 Java 类时,NetBeans IDE 使用代码生成模板生成源代码,使用适当的信息代替标记变量:作者名字、创建日期、许可证、类名称、构造函数名称和其他属性。NetBeans 6.1 之前,这些代码生成模板不支持开发者可能提供的定制行为。
但是,NetBeans 6.1/6.5 利用一个名为 Freemarker 的开源模板引擎来帮助生成定制代码。旧的 NetBeans 模板与这些采用 Freemarker 的模板的区别在于,能否在模板中使用脚本代码定制内容生成。如果此性能可以应用于其他 NetBeans 功能,您现在就能通过 UML 模块代码生成功能,使用模板定制代码,从而在利用 UML 功能生成代码方面提供更大的的灵活性。
目录

所需的软件
要学习本教程,您需要具备以下软件和资源。
Freemarker 模板文件和模型驱动开发
使用 NetBeans 6.5 UML 功能,可以向 IDE 中添加一组 Freemarker 模板文件。(有关 Freemarker 的信息,请参见 http://freemarker.org/。关于可以与 Freemarker 源代码一起使用的 NetBeans Freemarker 插件的信息请参见 http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=3755)。
这些模板支持使用标准 Java 源文件模板从模型元素生成标准 Java 源文件(类、接口和枚举类型)。与 NetBeans 中的其他模板一样,Freemarker 模板可用于定制。另外请参见 http://wiki.netbeans.org/FaqFreeMarker。
模型驱动开发
将 UML 与 Freemarker 配对使用的主要好处在于能够进行模型驱动开发(MDD)。MDD 表示您可以通过将元素属性映射到 Freemarker 模板的方式进行开发,然后可以创建标记为构造型的模型元素,从而允许您生成复杂的编程设计模式。
例如,可以使用一个带有构造型 ejb-stateless 的 Class 元素生成 Bean 类,以及 EJB 应用程序的 Home 接口和 Remote 接口源文件。
可以为独立的方法添加构造型 business,以指示将这些方法向客户端公开。要想更见特定于域,可以使用构造型 shopping-cart 来表示一个购物车 EJB 的完整实现。这些构造型中的每一个都可以映射到用于生成所需代码的特定模板。
成功创建 Freemarker 模板的背景知识
尽管本文不会关注脚本本身,但是以下三种技巧对于成功编写定制脚本和创建相应模板很有帮助:
- Freemarker 脚本编写知识
- 源数据模型知识
- 熟悉目标输出格式域
Freemarker 脚本编写
第一种技巧也就是熟悉 Freemarker 脚本语言。Freemarker 与其他脚本编写语言类似。有关 Freemarker 的信息,请参阅 SourceForge Web 站点上的 Freemarker 联机手册。
源数据模型
在 UML 数据模型中,有两个元素:在 UML 数据模型中,有两个元素: 一个元素的类型为 ClassInfo,而 classInfo 是另一个模型元素的名称,该元素类型为 Classifier,modelElement 是该模型的名称。这些元素可以在通过模板查看可用的脚本时看到。
目标输出格式域
输出格式是代码生成的结果。选择目标编程语言并不是一件简单任务。需要从语言解析器的角度来考虑。对于 Java,必须确保以一个包声明作为目标语言的开始,然后导入语句。类声明有许多变量需要考虑:作用域、类名称、扩展子句和实现。
类声明还可能带有注释。还需要考虑属性和方法,以及它们的签名和注释。空白也需要考虑。
继续之前,必须确保已经获得了“软件需求”一节中列出的压缩的发行版。此发行版包括 Freeemarker 代码生成模板和 NetBeans 项目。
使用 BankApp 样例项目和定制代码生成
继续之前,必须确保已经获得了“软件需求”一节中列出的压缩的发行版。此发行版包括 Freeemarker 代码生成模板和 NetBeans 项目。还将使用与 IDE 绑定的 BankApp 样例项目。
本文包含一个定制代码生成的教程。要创建定制代码生成教程的起点,可以使用 IDE 中与 UML 功能绑定的样例项目。
开始之前,需要为绑定的 BankApp 样例项目创建一个 Java 和 UML 项目。
- 从 IDE 的主菜单中,选择“文件”>“新建项目”。
- 在“选择项目”页中,展开“类别”面板中的“样例”节点,并选择 "UML" 节点。“项目”面板更新为可用的 UML 样例项目。
- 在项目面板中,选择“UML 银行应用程序样例”,然后单击“下一步”。
- 在“名称和位置”页中,将 Java 项目名称保留为缺省值 UMLBankAppSample,如果该项目已存在,可以修改项目名称。
- 单击“完成”。NetBeans IDE 将创建两个项目:一个 Java 项目和一个 UML 项目。如果选择缺省名称,则 Java 项目的名称为 UMLBankAppSample,UML 项目的名称为 UMLBankAppSample-Model。
- 展开 UML 项目以显示“模型”节点的所有子节点。其中有一个包、bankpack,几个 Class 元素和一个 Interface 元素。这些元素是从 Java 项目逆向工程得来的。
- 右键单击这些元素中的任何一个并选择“导航至源”,Java 项目中的源文件将会在 NetBeans 编辑器中打开。
- 对这些元素进行更改并执行“生成代码”,Java 项目中的源文件会进行适当地更新。(了解 Java 项目和 UML 项目之间的关系会很有帮助)。现在的重点是如何生成每个元素的代码,以及如何定制代码生成。
创建了将要使用的 Java 和 UML 项目之后,就可以查看 UML 代码生成过程中要使用的工具了。
UML 代码生成过程中使用的 NetBeans UML 工具
开始创建定制模板并将其映射到模型元素前,了解 NetBeans IDE 中将要使用的工具及其之间的关系非常重要。
这些工具包括面板、定制器和一个对话框:
- NetBeans 模板管理器:使用此工具访问文件夹中的模板。
- NetBeans UML 模板选项面板:使用此工具将模板文件映射到模型元素。
- NetBeans UML 项目定制器(用于项目属性):使用此工具启用域模板
- “生成代码”对话框:使用此对话框从模板创建代码。
这些工具中的每一个都在 UML 代码生成过程中扮演着模板的配置和使用中的一个特定角色。
使用 NetBeans 模板管理器管理模板文件
NetBeans 6.1 中的所有模板都基于 Freemarker 模板引擎。
在 IDE 中,可以使用 NetBeans 模板管理器管理 Freemarker 模板。要访问模板:
- 从 IDE 的主菜单中,选择“工具”>“模板”。IDE 打开“模板管理器”对话框。您将会看到许多文件夹,用于对模板进行分类。
- 展开 UML 文件夹及其子文件夹。

添加到 IDE 中的模板文件不需要包含 Freemarker 脚本,因此在模板管理器中添加文件时没有预期的文件格式。用于生成 Java 代码的模板设计用于最大化代码重用。
添加模板文件时,请记住:
- CompilationUnit.java 文件是用于生成 Java 类、接口和枚举源文件的惟一模板文件。
- 附加文件(*Declaration.java 文件和 DeclLib.ftl)链接自 CompilationUnit.java 文件内部。
- 其他文件夹中还有许多其他模板。一些模板可能包含有价值的脚本示例,您可以将其用于生成 UML 代码的定制模板中。但是,UML 代码生成过程仅使用“UML/代码生成”文件夹及其子文件夹中列出的模板。
- 您可以在“UML/代码生成”文件夹下创建自己的定制子文件夹来存储您的模板,这些模板也可以用于 UML 代码生成。
在本文中,将使用非常简单的 Freemarker 模板脚本,这些脚本利用 NetBeans UML 代码生成过程为 Freemarker 模板引擎提供的缺省功能。
使用 NetBeans UML 选项面板映射域模板
创建定制 Freemarker 模板文件只是第一步。一些模板已经可以用于 Java 代码生成。
但是,在使用模板文件时,还需要将这些模板文件映射到您的模型中的模型元素。可以在“NetBeans UML 选项”面板中配置此映射,方法如下:
- 从 IDE 的主菜单中,选择“工具”>“选项”。
- 单击 "UML" 选项类别。
- 单击“模板”标签。
- 在树中选择 "Basic Class" 节点。
IDE 显示 Java/Basic Class 域模板的属性,该模板显示模型中类型为 Class 并且没有构造型的任何元素都被映射到 UML/Code Generation/Java/CompilationUnit.java 下的模板文件,而且输出文件的名称与文件扩展名为 .java 的元素的名称相同。

使用定制代码模板文件生成域对象代码
UML 功能拥有几种元素类型(比如 Class、Interface、Actor)。可以为这些元素添加上构造型来标识用于特定用途或拥有特定行为的元素。域对象是特定于域的语言(DSL)的专用对象。
例如,在 ATM 机器域(本教程未使用这个域)中,域对象可能包括:
- Customer
- Account
- Deposit
- Withdrawal
- Bank
这些域对象可以在 UML 类图中表示为分别带有以下构造型的 Class 元素:
- customer
- account
- deposit
- withdrawal
- bank
要生成域对象的代码,必须创建定制代码模板文件。定制代码模板文件包含将会在源文件中生成的必要的属性和方法。
创建了模板文件之后,需要在代码生成过程中将元素/构造型对映射到合适的模板文件。域模板提供了模型元素类型和构造型到一个或多个模板文件的映射。
借助 UML 模板选项面板,可以根据需要创建分类文件夹,然后将域模板添加到它们的类别中。您自己可以确定组织类别和域模板的方法,但是需要遵循在 NetBeans 模板管理器中创建的布局,您要从 NetBeans 模板管理器访问模板文件。
使用 UML 模板选项面板启用 UML 项目的域模板
创建域模板之后,需要根据每个 UML 项目启用或禁用它们。对于每个 UML 项目,缺省的 Java 域模板会自动启用。但是,如果在 UML 模板选项面板中创建定制域模板,缺省情况下,这些域模板不会为任何 UML 项目启用。
可以使用 UML 项目定制器(项目属性)来定制 UML 项目的启用的模板。
要为 UML 项目启用域模板:
- 右键单击 UML 项目节点(缺省名称为 UMLBankAppSample-Model)。
- 选择“属性”打开 UML 项目定制器。
- 在出现的定制器对话框中选择“代码生成”类别。
- 展开底部面板中的 Java 节点。
了解和使用项目属性面板
在此示例中,Target Project 字段是空的。这是因为您通过 Java 项目 UMLBankAppSample 对 UML 项目进行了逆向工程。

第一次生成代码时,IDE 不会配置目标项目,而且底部的状态消息会提示必须选择一个有效的目标项目。
使用“项目属性”面板:
- 单击“确定”保存属性,无需指定目标项目。(您稍后会在“代码生成”对话框的工作流中看到相同的用户界面,但那时,必须填写先工作流中的所有必需字段(包括 Target Project 在内),才能单击“确定”生成代码。)
- 展开底部“模板”面板中的 Java 节点,查看三个缺省的域模板:
- Basic Class
- Basic Interface
- Basic Enumeration
- 可以根据每个模板关闭特定元素的代码生成。例如,如果不希望为在模型中没有构造型的 Enumeration 元素生成代码,可以在属性面板中取消选择该域模板。
- 如果已添加了定制域模板,可以在此面板中为代码生成启用这些模板。假设在项目定制器中启用了“生成代码前提示”选项,所有这些选项还可以在调用代码生成过程中进行动态配置,(缺省情况下,IDE 会打开此对话框选项。)
从模型生成代码
所有域模板就绪之后,它们就会为您的 UML 项目启用,您可以从模型中生成代码。为此,
- 右键单击 UML 项目节点并选择“生成代码”操作。IDE 显示“生成代码”对话框,以确认正确配置了属性。缺省情况下,模板面板是隐藏的。
- 单击“显示模板”按钮显示域模板,如图所示。
- 单击“确定”按钮启动代码生成。在 NetBeans 输出窗口的“生成代码日志”标签中将显示消息。生成代码过程状态在这里显示。查看这些消息以确认正确生成了代码。

在下一节中,将使用通过流线化当前 Java 模板创建的 EJB 模板。此处未讨论创建这些模板的步骤,但是完成的、流线化的模板能够提供比 Java 模板更简单的示例。
创建 Enterprise Java Bean 3.0 定制模板
配置缺省 Java 代码模板生成 UML 项目中的 Java 代码后,可以使用定制模板为应用程序工件(比如典型的无状态会话 EJB)生成源文件。
创建健壮的代码生成模板是一个复杂的任务。为了方便学习使用定制模板的方法,已经为您创建了无状态会话 EJB 的三个必要的代码生成模板,并在压缩的发行版中提供。这些模板并不是生成无状态会话 EJB 的完整解决方案。它们仅生成 bean 类、Home 和 Remote 接口,如果标记恰当,还会带有来自 Class 元素的方法。
更完整的实现能够为每个独立操作添加构造型 local 和/或 remote,以指示该操作应该在哪个接口中声明。
获取代码生成模板并将其添加到 IDE
要将代码生成模板添加到 IDE,需要下载模板并使用模板管理器将其添加到 IDE:
- 请确保解压了本文提供的源文件,以获得一下模板:
- StatelessBean.ftl
- StatelessRemote.ftl
- StatelessLocal.ftl
- 将模板添加到 IDE。从主菜单中,选择“工具”>“模板”。NetBeans 模板管理器打开。
- 导航至文件夹 UML/Code Generation 并将其选中。
- 单击“新建文件夹”按钮并将其命名为 EJB 3.0。
- 单击“添加”按钮。
- 导航至解压缩模板文件所在的文件夹位置。
- 选择一个文件添加到 IDE。
- 对其他两个模板文件重复第 5-7 步。
- 选择所有三个模板。单击“在编辑器中打开”按钮。IDE 在 NetBeans 编辑器窗口中打开新模板文件。
- 浏览模板脚本,了解正在执行什么操作。这三个模板文件是通过组合用于生成 Java 类的三个独立模板文件的方式创建的,并被链接到一起,以使脚本可以重用。通过将脚本组合到一个模板,很容易执行脚本流程。
再次使用三个基本的缺省模板。它们是:
- DeclLib.ftl
- CompilationUnit.java
- NormalClassDeclaration.java
之所以有三个独立模板文件,是因为您将在 UML 项目中使用一个单一的模型元素来生成三个独立的源文件,而且每个生成的源文件必须至少有一个模板文件。
使用标准 Java 类型时,每种类型都会使用 CompilationUnit.java 模板文件,该模板文件引用其他模板文件(DeclLib.ftl 和其他三个 *Declaration.java 文件之一)来生成一个源文件。
生成 EJB 模板
压缩文件包含三个模板,它们可用于生成 EJB。借助这些模板,一个模型元素将直接使用三个不同的模板文件生成三个源文件。
下图将会帮助您可视化标准 Java 类代码生成与 EJB bean 类生成之间的关系和区别。
在下图中:
- 模型中有三个元素:一个 Class、一个 Interface 和一个 Enumeration。
- 每个 Class 元素被映射为使用基本类域模板(没有构造型的任何 Class 元素),而后者使用 CompilationUnit.java 模板文件。
- CompilationUnit.java 模板文件中的脚本确定此元素具有 Class 类型并且链接到 NormalClassDeclaration.java 模板中,以执行特定于 Java-Class 的代码生成。
- 类似地,对于 Interface 和 Enumeration 元素类型,CompilationUnit.java 中的脚本确定元素为一个特定的类型并连接到合适的模板,以方便特定于 Java、Interface 或 Enumeration 的 代码生成。

映射无状态类元素
带有无状态构造型的 Class 元素被映射到 Stateless 域模板,该模板拥有三个模板文件。
每个模板文件生成一个独立的源文件:一个 Java 类和两个 Java 接口。参见下图。

添加新模板
将新模板添加到 IDE 之后,需要通过选项面板将它们添加为域模板。为此:
- 从 IDE 的主菜单中,选择“工具”->“选项”。
- 单击“类别”
- 单击“添加”添加新的类别。
- 将缺省类别重命名为 EJB 3.0。
- 单击“添加”按钮添加一个新域。
- 将缺省域命名为 Stateless。
- 选择 Stateless。
- 从元素类型下拉菜单中选择 Class。
- 在 Stereotype 字段中输入 stateless。
- 选择“添加模板”。
- 使用以下建议条目填充对话框:
- 文件名格式:{名称}Bean
- 扩展名:.java
- 文件夹:保留为空,除非您想要在某处生成该文件
- 模板文件:EJB 3.0/StatelessBean.ftl
- 重复这些条目,但是提供其他两个模板的名称。
映射 EJB 模板
将模板添加到 IDE 并通过选项面板添加它们之后,需要使用 UML 选项面板将模板映射到您的模式中的模型元素。
- 从 IDE 的主菜单中,选择“工具”>“选项”。
- 单击“UML 选项”类别。
- 单击“模板”标签。
- 在选项面板中展开 EJB 3.0 节点。
IDE 显示 EJB 域模板的属性。如下面的演示所展示的,在 EJB 3.0 域模板下,将有一个元素类型为 Class 的无状态域模板,带有构造型 Stateless。
有三个输出参数:Bean、Local 和 Remote,每个参数的扩展名都是 .java

单个模型元素的多个域模板
一个模型元素可以映射到多个域模板。例如,Java 类别中的基本类域模板可以映射到类型为 Class 且没有构造型的任何元素。
现在可以创建另一个称为 C++ 的类别,其中包含名称也为 Basic Class(或者您想使用的任何名称)的模板,该模板也映射到类型为 Class 且没有构造型的元素。 模板文件可以生成 C++ 类,而不是 Java。
如果在调用“生成代码”操作时同时调用了两个模板,那么您将从一个元素获得两个文件,一个是 Java 类,另一个是 C++ 类。尽管后一个示例很少见,但仍然有可能发生。
创建 Calculator 无状态会话 RJB
在 NetBeans 中正确创建了模板并配置了合适的域模板之后,可以创建一个 UML 模型项目,该项目将利用新的模板为 Enterprise Java Bean 生成 Enterprise Java Bean 代码。
创建 UML 模型项目之后,创建一个 Calculator 元素并向其添加方法。
首先创建 UML 项目:
- 从主菜单中,选择“文件”>“新建项目”。
- 选择 UML,然后选择 Java 平台模型
- 单击“下一步”和“完成”。
- 在出现的“创建图”对话框中选择“类图”并单击“完成”。现在创建了一个带有一个类图的 UML 项目。
接下来,将要创建 Calculator 元素。要创建 Calculator 元素:
- 将一个 Class 元素添加到图中并将其命名为 Calculator(模板将会保证后缀被正确创建:也就是说,模板创建 Bean、Local 和 Remote 作为合适的源文件名称)。
- 对于选择的 Calculator 元素,编辑 Stereotype 属性并添加 stateless。
生成代码过程现在会识别 Calculator 元素,将其映射到 Stateless 域模板。但是,在执行代码生成之前,需要将一些方法添加到 Calculator 元素。
向 Calculator 元素添加方法
在 UML 图编辑器中为 Calculator 元素创建下面列出的三个操作。要创建一个元素,单击 Operation compartment 区域中的 Calculator 元素并选择“添加操作”。添加以下操作:
- public int add(int a, int b)
- public int subtract(int a, int b)
- public int multiply(int a, int b)
您可能想让所有三个操作在两个接口中都公开。只有公共方法能在这两个接口中声明,所以,如果不想让所有这些方法都公开,则需要过滤掉非公共方法。
而且,您可能不想让所有的公共方法在两个接口中都声明,或者在其中一个中声明。您需要一种脚本机制来确定在三个源文件的每一个中应该生成哪些方法。再一次,您可以使用构造型来指示应该添加哪些方法。
创建 Java 项目
现在 Calculator 元素已经完成了,您需要创建一个 Java 项目,以向其中生成代码。为此:
- 从 IDE 的主菜单中,选择“文件”>“新建项目”。
- 选择 "Java"、“Java 应用程序”并单击“下一步”。
- 在“选择项目”页,选择“Java 和 Java 应用程序”。
- 取消选择“创建主类”选项并单击“完成”。
- 右键单击 Calculator 元素并选择“生成代码”。
- 选择新创建的 Java 项目作为目标项目。
- 单击“显示模板”按钮并展开树中的 "EJB 3.0" 节点。
- 选择 Stateless 域模板。单击“确定”开始生成代码。
输出窗口显示消息,通知您 IDE 使用三个独立模板文件为 Calculator 元素生成代码。
生成代码过程运行完成之后,展开 Java 项目的源文件夹检查新的 Calculator 源文件。您将会看到三个生成的文件:
- CalculatorBean.java
- CalculatorLocal.java
- CalculatorRemote.java
打开每个文件确认您在类和两个接口中生成了所有三个方法。您可能会看到编译错误或其他错误,因为标准 Java 项目会自动包含 Java Enterprise 库或其他类。可以忽略这些错误,因为本教程的目标既不是编译也不是运行您创建的项目。
观察生成的代码发生更改的图编辑器
您可以看到在使用图编辑器对元素进行更改时,生成的代码是如何与 Calculator 元素保持同步的。在图编辑器中:
- 添加一个新操作:
public float divide(int a, int b)
- 删除相乘操作。
- 向相加操作添加第三个参数:
int c
- 右键单击 Calculator 元素并选择“生成代码”。
检查这三个源文件,就像之前检查新的源文件一样。 注意,IDE 更新了所有的源文件,以与您在图编辑器中对 Calculator 元素所做的更改保持同步。
小结
Freemarker 脚本环境为 NetBeans UML 代码生成提供了一个强大的附加功能,使您能够定制生成的代码。本文提供了概念性的背景知识和教程信息,使您能够创建、添加和定制代码生成模板、普通代码生成,以及引用了特定的 EJB 工件的代码生成。通过使用代码生成模板,可以在 NetBeans UML 代码生成的框架中利用模板的强大功能并轻松地修改一些特性,以维护许多源文件的源代码。定制的代码生成模板为您提供了一个简便有效的代码生成方式,可以用于您的应用程序项目中。
后续步骤
返回页首