如何使用虚拟表单
撰稿人:Matt Bohm
本文介绍了如何在 NetBeans IDE 6.0 或 6.1 中使用虚拟表单。
目录
要学习本教程,您需要具备以下软件和资源。
| NetBeans IDE |
Web 和 Java EE 版本 6.1 或 6.0 |
| Java Development Kit (JDK) |
版本 6 或
版本 5 |
JavaServer Faces 组件/
Java EE 平台 |
1.2(带有 Java EE 5*)或
1.1(带有 J2EE 1.4)
|
| GlassFish Application Server |
V2 |
| Travel 数据库 |
不需要 |
* 要利用 NetBeans IDE 的 Java EE 5 功能,请使用与 Java EE 5 规范完全兼容的应用服务器,例如 GlassFish Application Server V2 UR2。如果使用的是其他服务器,请查阅发行说明和常见问题解答,了解已知问题和解决方法。有关支持的服务器和 Java EE 平台的详细信息,请参见发行说明。
NetBeans IDE 6.1 用户的注意事项:
- NetBeans 6.1 提供了一些用于创建项目的新选项,对于这些选项,可以保留其缺省设置。例如,可以将使用专用的文件夹来存储库复选框保留为未选中状态。
- NetBeans IDE 6.1 具有按需绑定功能。如果组件需要 Java 编码,那么您必须现在手动在 Visual Web JSF 应用程序中向组件添加绑定属性。要执行此操作,请右键单击每个组件,然后选择“添加绑定属性”。有关详细信息,请参见 On-demand Binding Attribute Wiki(按需绑定属性 Wiki)。
安装示例
注意:如果使用的是 NetBeans 6.0 或 6.1,则可以通过“新建项目”向导获得样例应用程序。只需选择“文件”>“新建项目”>“样例”> "Web" >“可视 JSF”>“电影管理”,然后继续执行下面的步骤 3 即可。
- 首先,解压缩 MovieAdmin.zip 文件的内容,该文件包含两个项目文件夹:MovieAdmin 和 MoviesClassLibrary。
- 启动 IDE,关闭所有项目,然后打开 MoviesClassLibrary 项目。
打开 MovieAdmin 项目。
注意:Page1.jsp 会显示错误,因为您需要解决一个库引用问题。
- 在“项目”窗口中,右键单击 "MovieAdmin" 项目节点,然后选择“属性”。
- 在“项目属性”对话框中,选择“类别”树下的“库”,然后单击“添加项目”按钮。
- 在“添加项目”对话框中,浏览至 MoviesClassLibrary 项目所在的位置,选择
MoviesClassLibrary,然后单击“添加项目 JAR 文件”按钮。
- 单击“确定”。
- 在“项目”窗口中,右键单击 "MoviesClassLibrary" 项目节点,然后从弹出式菜单中选择“生成”。
- 退出 IDE,然后重新打开 IDE,以便可以在 MovieAdmin 项目中使用 MoviesClassLibrary。
安装示例后,双击“项目”窗口中的 Page1.jsp 节点,以便在可视设计器中打开 Page1.jsp。在标签下面的工具栏中,您会看到一组按钮,其中包括“显示虚拟表单”按钮
。单击该按钮可显示页面上使用的虚拟表单。
“电影管理”示例是一个电影租赁公司使用的虚构管理应用程序。该公司将其电影集的相关数据保存在数据存储库中,员工可以使用此管理应用程序对这些数据进行更改。该公司还具有一个单独的外部 Web 站点,客户可以在上面浏览电影集。该外部 Web 站点使用相同的数据存储库。
注意:实际的应用程序可以使用关系数据库或其他外部数据存储库。但是,为了重点说明虚拟表单,“电影管理”示例仅将数据作为会话中的对象进行存储。
图 2 展示了“电影管理”应用程序的 Page1.jsp 在浏览器中的显示情况。员工可以通过在 Current Genre 下拉列表中进行选择来查看特定类型的电影。员工可以编辑表中的标题、年份、片长(分钟)、分级、图像 URL 和描述字段,当其单击 "Update" 按钮或使用该表的分页控件(如果可用)时,将保存所做的更改。员工可以通过单击其中一行的 "Remove" 按钮,从电影集中删除某部电影。如果单击其中一行的 "Preview" 按钮,将导航至 Preview.jsp,员工可以在其中预览电影的详细信息页面,这与浏览外部 Web 站点的客户所看到的内容相同。在表的下方,显示了一组单独的控件,用于为电影集添加电影。
提示:在运行该示例并为电影集添加电影时,可以输入图像文件在计算机上基于文件的 URL,而不是项目中图像文件的相对路径。用这种便捷的方式,您可以预先将图像文件添加到项目中。
除了可以预览电影的详细信息外,员工还可以通过“预览”页来修改所预览的电影类型。
Page1.jsp 为我们提出了一个值得关注的问题。如果您选择了一种新的当前类型,我们希望 Current Genre 下拉列表中的输入内容得到处理,而不是对页面上的其他输入内容进行处理。如果对其他输入内容进行了处理,那么当这些输入内容出现任何转换或验证错误时,将导致拒绝提交,即,无法更改当前类型,这是我们不希望看到的结果。同样,单击 "Update" 按钮时,我们希望表中的输入内容得到处理,而不对 "Add Movie" 部分的输入内容进行处理。如果 "Add Movie" 部分中的字段出现了任何转换或验证错误,将导致拒绝提交,即,无法更新表中的字段,这是我们不希望看到的情况。Preview、Remove 和 Add 按钮也都具有类似的选择性处理要求。
因此,用户与某些提交组件进行交互时,有选择地处理某些输入内容是对 Web 应用程序提出的一个常见且非常迫切的要求。处理输入内容是指:对输入内容进行转换和验证,触发与输入内容相关联的任何值更改事件,并将输入内容映射到其绑定目标上(如果已绑定组件)。输入组件是指任何接受用户输入的组件,如文本字段、文本区域、下拉列表或单选按钮。(从技术上说,输入组件是实现 EditableValueHolder 接口的组件。)提交组件是指任何导致 Web 页提交并因而启动输入处理的组件;这不仅包括按钮和链接(用于实现 ActionSource 接口),而且还包括打开了“更改时自动提交”功能的输入组件。因此,一个组件可以既是输入组件又是提交组件。“电影管理”应用程序的 Page1.jsp 上的 "Current Genre" 下拉列表就是这样一个组件。
Page1.jsp 的完整选择性处理要求如下所示:
- "Current Genre" 下拉列表。选择一种新的当前类型后,Current Genre 下拉列表会自动提交 Web 页,并且专门处理下拉列表的输入内容,而忽略页面上的其他输入内容。
- "Update" 按钮。单击 "Update" 按钮时,只处理表中的字段,而不处理 "Add Movie" 部分的字段。发生这种情况时,也不需要处理当前类型选择,因为它不发生任何变化。
- "Preview"/"Remove" 按钮。单击 "Preview" 或 "Remove" 按钮时,不处理任何输入内容。在这种情况下,由于表组件和数据提供器 API 提供了对被单击的按钮所在行的访问,因此不需要处理任何输入内容。在表或 "Add Movie" 部分的字段中输入的任何内容都必须忽略。同样,也不需要处理选择的当前类型,因为它不发生任何变化。
- "Add" 按钮。单击 "Add" 按钮时,只处理 "Add Movie" 部分的输入内容。
Page1.jsp 还具有其他选择性处理要求。当表显示分页控件时,在与这些控件进行交互的过程中,只处理表中的输入内容。否则,表外部字段出现任何转换和验证错误时都将导致拒绝提交。
如果没有足够强大的选择性处理机制,将无法满足这些要求。JavaServer Faces 组件上的 immediate 属性提供了某些选择性处理支持,但还不足以生成此类 GUI。问题是,在此 GUI 中包含多组输入组件,需要根据用户使用的提交组件选择性地处理这些组件。通过在 GUI 中的某些组件上设置 immediate 属性,可以指定选择性地处理一组组件,而不是多组组件。
虚拟表单在页面上定义了一组输入组件和提交组件。输入组件是虚拟表单的参与方。提交组件是虚拟表单的提交方。Web 站点用户与提交虚拟表单的组件交互时,将处理虚拟表单的参与方,而忽略页面上的其他输入内容。
请注意以下事项:
- 虚拟表单可以包含零个或多个参与方以及一个或多个提交方。
- 只有输入组件才可以是虚拟表单的参与方。由于从定义上讲,提交组件是指任何可以提交 Web 页面的组件(包括打开“更改时自动提交”功能的输入组件),因此任何此类组件都可能是虚拟表单提交方。
- 虚拟表单没有拓扑限制;其参与方和提交方不需要出现在彼此旁边。
- 输入组件可以参与多个虚拟表单,但提交组件最多只能提交一个虚拟表单。
- 输入组件既可以提交虚拟表单,又可以同时参与一个或多个虚拟表单。
- 如果提交组件不提交任何虚拟表单,则用户与其进行交互时,将正常提交实际的表单。
与只能定义一个组的 immediate 属性不同,页面可以根据需要使用尽可能多的虚拟表单,从而使之成为一个功能强大的解决方案。此外,因为 immediate 属性会修改 JavaServer Faces 的生命周期,所以适合高级开发者使用,而虚拟表单却不会出现上述情况,因此非常易于使用。
让我们看一下图 3,在 IDE 的可视编辑器中显示了“电影管理”应用程序的 Page1.jsp。虚拟表单采用颜色编码,实线表示参与,虚线表示提交。您可以使用以下四个虚拟表单:
- 类型。Current Genre 下拉列表参与并提交了类型虚拟表单(蓝色)。为了表示它参与并提交该虚拟表单,它的上边和左边框为实线,而下边和右边框为虚线。
- 更新。表中的标题、年份、片长(分钟)、分级、图像 URL 和描述字段参与了更新虚拟表单(绿色),使用 Update 按钮进行提交。
- 预览/删除。"Preview" 和 "Remove" 按钮用于提交预览/删除虚拟表单(红色),该表单没有参与方。
- 添加。在 "Add Movie" 部分中,标题、年份、片长(分钟)、分级、图像 URL 和描述字段都参与了添加虚拟表单(黄色),使用 Add 按钮进行提交。
注意:Page1.jsp 的组面板中嵌入了一个消息列表组件。在可视编辑器中,消息列表带有红色边框,组面板显示细虚线边框。请不要受这些组件的干扰,因为这些组件的边框与虚拟表单无关。
需要再次强调一下,尽管虚拟表单可以包含一个或多个提交方,但任何指定的提交组件最多只能提交一个虚拟表单。例如,预览/删除虚拟表单包含两个提交方,即 Preview 和 Remove 按钮。但是,每个按钮只能提交一个虚拟表单,不能提交多个虚拟表单。此外,尽管“电影管理”应用程序中没有出现这种情况,但是输入组件完全可以参与多个虚拟表单(并且这种情况很常见)。而且,在 Page1.jsp 上,尽管与每个虚拟表单相关联的组件往往出现在彼此旁边,但这并不是虚拟表单机制的要求。
Page1.jsp 上使用的四个虚拟表单满足了该页面的选择性处理要求,如下所示:
- 类型。员工更改 Current Genre 下拉列表中的选择内容时,会提交类型虚拟表单。由于该下拉列表是此虚拟表单的唯一参与方,因此只会处理其输入内容,而忽略页面上的其他输入内容。因此,与其他输入内容关联的转换器和验证器不会拒绝提交。
- 更新。员工单击 "Update" 按钮时,会提交更新虚拟表单。由于只有表中的输入内容参与了该虚拟表单,因此会处理这些输入内容,而忽略所有其他输入内容。因此,在 "Add Movie" 部分中,各字段的转换器和验证器不会拒绝提交。
- 预览/删除。当员工单击 "Preview" 或 "Remove" 按钮时,会提交预览/删除虚拟表单。因为该虚拟表单不包含参与方,所以不会处理任何输入内容。如上所述,由于表组件和数据提供器 API 提供了对被单击的按钮所在行的访问,因此不需要处理任何输入内容。因此,页面上的任何转换器或验证器都不会拒绝提交。
- 添加。员工单击 "Add" 按钮时,会提交添加虚拟表单。由于只有 "Add Movie" 部分的输入内容参与了该虚拟表单,因此会处理这些输入内容,而忽略所有其他输入内容。因此,表中字段上的转换器和验证器不会拒绝提交。
如果用户提交的虚拟表单会使同一页面重新显示,则该虚拟表单实现的缺省行为是保留并显示非参与方的提交值。这样可以防止丢失未进行处理的任何用户输入。例如,假定用户在 "Add Movie" 部分的字段中输入了某些数据。但是,在单击 "Add" 按钮之前,用户决定更改 "Current Genre" 下拉列表中选择的内容或修改表中的某些数据,并且单击了 "Update" 按钮。结果,将提交一个虚拟表单,"Add Movie" 部分中的输入字段不参与该表单。为了不丢失用户在这些输入字段中的输入,当重新显示页面时,这些输入字段将保留并显示其提交值,而不是显示其值。提交值是未转换且未验证的条目,它们在用户提交 Web 页时位于输入字段中。值是组件的当前实际值。
但是,还有一些我们希望覆盖缺省行为的用户操作。在这些情况下,我们希望明确放弃某些非参与方的提交值并改为显示其值,而不保留并显示其提交值。例如,表中的输入字段不参与类型虚拟表单。因此,当用户更改了在 "Current Genre" 下拉列表中选择的内容并随后重新显示页面时,缺省行为是保留并显示表中输入字段的提交值。这并不是我们所希望看到的结果,因为表中将显示旧类型的电影,而不是新类型的电影。因此,必须通过在 currentGenreDropDown_processValueChange 方法中明确放弃这些提交值来覆盖缺省行为:
| 代码示例 1:currentGenreDropDown_processValueChange 方法 |
// the genre virtual form, in which only the currentGenreDropDown
// participates, has been submitted
// make sure the input fields in the movies table do not
// retain their submitted values
form1.discardSubmittedValues("update"); |
此处,更新虚拟表单的参与方(即,表中的所有输入字段)明确放弃其提交值。因此,它们将改为显示其值,这意味着该表将显示新类型的电影,而不是旧类型的电影。
表单组件包含以下用于放弃非参与输入字段的提交值的方法:
| 代码示例 2:用于放弃非参与输入字段提交值的方法 |
public void discardSubmittedValues(String virtualFormName)
public void discardSubmittedValue(EditableValueHolder inputField) |
上面的第一种方法接受虚拟表单名称。所指定虚拟表单中的参与方将放弃其提交值。指定的虚拟表单不能是已提交的表单。如果在当前请求期间提交指定的虚拟表单,则此方法会抛出 IllegalArgumentException。
上面的第二种方法接受单个输入字段作为 EditableValueHolder 对象。指定的输入字段将放弃其提交值。请注意,指定的输入字段必须是非参与字段。如果虚拟表单已提交并且指定的输入字段参与到其中,则此方法会抛出 IllegalArgumentException。
表组件有一个 internalVirtualForm 属性,其缺省值为 false。在 Page1.jsp 的表中,该属性已设置为 true。这将导致该表在内部使用虚拟表单。因此,使用分页控件时,仅处理该表中的输入内容。这可以防止表外部字段的转换器和验证器拒绝提交。
在 NetBeans IDE 中,可以通过在可视编辑器中右键单击,并选择虚拟表单上下文菜单选项,以此来创建、删除和重命名虚拟表单,以及更改其颜色代码。将打开“虚拟表单”对话框,如下图所示。
使用该对话框非常直观。要更改与虚拟表单相关联的颜色,请单击颜色单元格,然后从列表中选择一种颜色。要重命名虚拟表单,请双击名称单元格,然后编辑该名称。还可以在此对话框中创建和删除虚拟表单。
虽然可以在“虚拟表单”对话框中创建、删除和重命名虚拟表单并且更改其颜色代码,但是无法在其中配置参与和提交每个虚拟表单的组件。您可以在“配置虚拟表单”对话框中完成所有这些操作。要访问该对话框,请在可视编辑器或“概要”窗口中选择一个或多个组件,单击鼠标右键,然后选择“配置虚拟表单”上下文菜单项。在出现的对话框中,可以指定选定组件参与其中的虚拟表单。还可以指定选定组件提交的虚拟表单。与“虚拟表单”对话框类似,您可以在“配置虚拟表单”对话框中创建、删除和重命名虚拟表单并更改其颜色代码。下图显示了在选择 Page1.jsp 的 "Add Movie" 部分中所有输入组件后显示的“配置虚拟表单”对话框。
虽然按钮和链接组件是最常用的提交组件,但是也可以将输入组件(如下拉列表)作为提交组件。在“电影管理”示例的 Page1.jsp 上,Current Genre 下拉列表参与并提交了类型虚拟表单。可以使用“配置虚拟表单”对话框这种方式来配置此虚拟表单。但是,为了使下拉列表实际可以提交 Web 页,还需要右键单击该组件并启用“更改时自动提交”功能。请注意,按钮和链接组件没有“更改时自动提交”选项,因为这些组件可以自动提交 Web 页。
在 NetBeans IDE 中,不支持页面片段内的虚拟表单。要对页面片段中的组件配置选择性处理,请在这些组件上将 immediate 属性设置为 true。此解决方案可适用于多种用例,但是到目前为止,由于该方案只能对一组组件进行选择性处理,因此仍然存在局限性。
如果要使用标准数据表组件(不是新的表组件)中的按钮或链接来提交虚拟表单,则必须在按钮或链接的 onClick(或 onclick)属性中添加一些额外的脚本,这种情况虽然不常见,但也应当引起注意。假设标准数据表组件包含一个按钮组件,其 id 属性为 button1。您需要将以下脚本添加到该按钮的 onClick 属性中:
| 代码示例 3 |
common_leaveSubmitterTrace(this.form,'button1'); |
如果没有此额外的脚本,则该按钮将无法提交虚拟表单。需要再次说明的是:这种情况只适用于标准数据表组件(而不是新的表组件)中的按钮和链接(不是输入组件)。
本技术文章探讨了 NetBeans IDE 中的新虚拟表单功能。虚拟表单在页面上定义了一组输入组件(“参与方”)和提交组件(“提交方”),这样当用户与某一提交方进行交互时,将专门处理这些参与方,而忽略页面上的所有其他输入内容。您还了解了:
- “电影管理”示例应用程序的选择性处理要求,并且了解了虚拟表单是如何提供功能强大而全面的解决方案来满足这些要求的。
- 如何在 IDE 中通过“虚拟表单”和“配置虚拟表单”对话框来修改页面的虚拟表单配置。
- 在输入组件打开了“更改时自动提交”功能时,如何提交虚拟表单。
- 与 immediate 属性不同,虚拟表单不会改变 JavaServer Faces 的生命周期,因此非常易于使用。
另请参见
返回页首