| 虚拟表单是 Sun Java Studio Creator 2 集成开发环境 (Integrated Development Environment, IDE) 中的新增功能。本技术文章是为那些使用 IDE 并希望利用这一功能强大的新机制的开发者而编写的。 |
目录
安装示例
- 首先,解压缩 MovieAdmin.zip 文件的内容,该文件包含两个项目文件夹:Movies 和 MoviesClassLibrary。
- 启动 IDE,关闭所有项目,然后打开 MoviesClassLibrary 项目。
- 打开 Movies 项目。
- 在“项目”窗口中,右键单击 Movies 项目节点,然后从上下文菜单中选择“属性”。
- 在“项目属性”对话框中,单击左侧树中的“库”。然后单击“添加项目”按钮。
- 在“添加项目”对话框中,找到 MoviesClassLibrary 项目并单击该项目,然后单击“添加项目 JAR 文件”按钮。
- 在“项目属性”对话框中,单击“确定”按钮。
- 在“项目”窗口中,右键单击 MoviesClassLibrary 项目节点,然后从上下文菜单中选择“生成项目”。
- 退出 IDE,然后重新打开 IDE。
“显示虚拟表单”按钮
安装示例后,单击 Page1.jsp 标签。在标签下面的工具栏中,您会看到一组按钮,其中包括“显示虚拟表单”按钮(请参见图 1)。单击该按钮可显示页面上使用的虚拟表单。
图 1:“显示虚拟表单”按钮 |
Movie Administration 概述
Movie Administration 示例是影片租赁公司使用的虚构管理应用程序。该公司将其影片集的相关数据保存在数据存储中,员工可以使用此管理应用程序对这些数据进行更改。该公司还具有一个单独的外部 Web 站点,客户可以在上面浏览影片集。该外部 Web 站点使用相同的数据存储。
| 注意:实际的应用程序利用关系数据库或其他外部数据存储。但是,为了重点说明虚拟表单,Movie Administration 示例仅将数据作为会话中的对象进行存储。 |
图 2 展示了 Movie Administration 应用程序中的 Page1.jsp 在浏览器中的显示情况。员工可通过在 "Current Genre" 下拉列表中进行选择来查看特定类型的影片。员工可以编辑表中的 Title(标题)、Year(年份)、Minutes(时间长度,以分钟为单位)、Rating(收视率)、Image(图像 URL)以及 Description(描述)字段;当其单击 "Update" 按钮或者使用表的分页控件(如果可用)时,将保存所做的更改。员工可以单击某一行中的 "Remove" 按钮,从影片集中删除某个影片。单击某一行中的 "Preview" 按钮时,将导航到 Preview.jsp,员工可以在其中预览影片的详细信息页面,这与浏览外部 Web 站点的客户所看到的内容相同。在表的下方,显示了一组不同的控件,用于为影片集添加影片。
图 2:Web 浏览器中的 Page1.jsp(单击以放大) |
| 提示:在运行该示例并为影片集添加影片时,可以输入图像文件在计算机上基于文件的 URL,来代替项目中图像文件的相对路径。使用这种便捷的方式,您可以预先将图像文件添加到项目中。 |
除了可以预览影片的详细信息外,员工还可以通过“预览”页来修改所预览的影片类型。
选择性处理要求
Page1.jsp 为我们提出了一个值得关注的问题。如果您选择了一种新的 Current Genre(当前类型),我们希望 "Current Genre" 下拉列表中的输入内容得到处理,而不是对页面上的其他输入内容进行处理。如果对其他输入内容进行了处理,那么当这些输入内容出现任何转换或验证错误时,将无法完成提交任务,即,无法更改当前类型,这是我们不希望看到的结果。同样,单击 "Update" 按钮时,我们希望表中的输入内容得到处理,而不对 "Add Movie" 部分的输入内容进行处理。如果 "Add Movie" 部分中的字段出现了任何转换或验证错误,将无法完成提交任务,即,无法更新表中的字段,这是我们不希望看到的情况。"Preview"、"Remove" 和 "Add" 按钮也都具有类似的选择性处理要求。
因此,用户与某些提交组件进行交互时,有选择地处理某些输入内容是对 Web 应用程序提出的一个常见且非常迫切的要求。处理输入内容是指:对输入内容进行转换和验证,触发与输入内容相关联的任何值更改事件,并将输入内容映射到其绑定目标上(如果已绑定组件)。输入组件是指任何接受用户输入的组件,如文本字段、文本区域、下拉列表或单选按钮(从技术角度而言,输入组件是实现 EditableValueHolder 接口的那些组件)。提交组件是指任何导致 Web 页提交并因而启动输入处理的组件;这不仅包括按钮和链接(用于实现 ActionSource 接口),而且还包括打开了“更改时自动提交”功能的输入组件。因此,一个组件可以既是输入组件又是提交组件。在 Movie Administration 应用程序中,Page1.jsp 上的 "Current Genre" 下拉列表就是一个这样的组件。
Page1.jsp 的完整选择性处理要求如下所示:
- Current Genre 下拉列表。选择新的 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 的可视编辑器中显示了 Movie Administration 应用程序的 Page1.jsp。虚拟表单使用颜色编码;实线表示参与方,虚线表示提交方。您可以使用以下四个虚拟表单:
- genre。Current Genre 下拉列表参与并提交了
genre 虚拟表单(蓝色)。为了表示它参与并提交该虚拟表单,它的上边和左边框为实线,而下边和右边框为虚线。
- update。表中的 Title(标题)、Year(年份)、Minutes(时间长度,以分钟为单位)、Rating(收视率)、Image(图像 URL)以及 Description(描述)字段参与了
update 虚拟表单(绿色);"Update" 按钮用于提交该表单。
- preview/remove。"Preview" 和 "Remove" 按钮用于提交
preview/remove 虚拟表单(红色),该表单没有参与方。
- add。"Add Movie" 部分的 Genre(类型)、Title(标题)、Year(年份)、Minutes(时间长度,以分钟为单位)、Rating(收视率)、Image(图像 URL)以及 Description(描述)字段都参与了
add 虚拟表单(黄色);并且 "Add" 按钮用于提交该表单。
注意:Page1.jsp 包含了一个嵌入在组面板中的消息列表组件。在可视编辑器中,消息列表带有红色边框,组面板显示细虚线边框。请不要受这些组件的干扰,因为这些组件的边框与虚拟表单无关。 |
图 3:可视编辑器中的 Page1.jsp(单击以放大) |
需要再次强调一下,尽管虚拟表单可以包含一个或多个提交方,但任何指定的提交组件最多只能提交一个虚拟表单。例如,preview/remove 虚拟表单包含两个提交方,即 "Preview" 和 "Remove" 按钮。但是,每个按钮只能提交一个虚拟表单,不能提交多个虚拟表单。此外,尽管 Movie Administration 应用程序中没有出现这种情况,但是输入组件完全可以参与多个虚拟表单(并且这种情况很常见)。再者,在 Page1.jsp 中,尽管与每个虚拟表单相关联的组件往往在布局上出现在彼此旁边,但这并不是虚拟表单机制的要求。
Page1.jsp 使用的四个虚拟表单满足了该页面的选择性处理要求,如下所示:
- genre。员工更改 "Current Genre" 下拉列表中选择的内容时,会提交
genre 虚拟表单。因为该下拉列表是此虚拟表单的唯一参与方,只有下拉列表中的输入才会得到处理,而页面上的其他输入则被忽略。因此,与这些其他输入关联的转换器和验证器不会拒绝提交。
- update。员工在单击 "Update" 按钮时,将提交
update 虚拟表单。由于只有表中的输入内容参与了该虚拟表单,所以只会处理这些输入内容,而所有其他输入将被忽略。因此,在 "Add Movie" 部分中,各字段的转换器和验证器不会拒绝提交。
- preview/remove。员工在单击 "Preview" 或 "Remove" 按钮时,将提交
preview/remove 虚拟表单。因为该虚拟表单不包含参与方,所以不会处理任何输入。如上所述,不需要处理任何输入,因为表组件和数据提供器 API 提供了对被单击的按钮所在行的访问。因此,页面上的任何转换器或验证器都不会拒绝提交。
- add。员工在单击 "Add" 按钮时,将提交
add 虚拟表单。因为只有 "Add Movie" 部分的输入参与了该虚拟表单,所以会处理这些输入,而忽略所有其他的输入。因此,表中的字段的转换器和验证器不会拒绝提交。
保留和放弃已提交的值
如果用户提交的虚拟表单会使同一页面重新显示,则该虚拟表单实现的缺省行为是保留并显示非参与方的提交值。这可以防止丢失任何未处理的用户条目。例如,假定用户在 "Add Movie" 部分的字段中输入某些数据。但是,在单击 "Add" 按钮之前,用户决定更改 "Current Genre" 下拉列表中选择的内容或修改表中的某些数据,并且单击了 "Update" 按钮。这样操作的结果是:将提交一个虚拟表单,"Add Movie" 部分中的输入字段不参与该表单。为了在重新显示页面时不丢失用户在这些输入字段中输入的内容,这些输入字段将保留并显示其提交值,而不显示其值。提交值是指用户提交 Web 页时,位于输入字段中的未转换且未验证的条目。值是组件的实际当前值。
然而,我们会希望覆盖某些用户操作的缺省行为。在这些情况下,我们希望显式地放弃某些非参与方的提交值并改为显示其值,而不保留并显示其提交值。例如,表中的输入字段不参与 genre 虚拟表单。因此,当用户更改了在 "Current Genre" 下拉列表中选择的内容并随后重新显示页面时,缺省行为是保留并显示表中输入字段的提交值。这并不是我们所希望看到的结果,因为表中将显示旧类型的影片,而不是新类型的影片。因此,必须通过在 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");
此处 update 虚拟表单的参与方(即,表中的所有输入字段)显式地放弃其提交值。因此,它们将改为显示其值,这意味着该表将显示新类型的影片,而不是旧类型的影片。
表单组件包含以下用于放弃非参与输入字段的提交值的方法:
public void discardSubmittedValues(String virtualFormName) public void discardSubmittedValue(EditableValueHolder inputField)
上面的第一种方法接受虚拟表单名称。指定的虚拟表单中的参与方将放弃其提交值。指定的虚拟表单不能是已提交的表单。如果在当前请求期间提交指定的虚拟表单,此方法将抛出 IllegalArgumentException。
上面的第二种方法接受单个输入字段作为 EditableValueHolder 对象。指定的输入字段将放弃其提交值。请注意,指定的输入字段必须是非参与方字段。如果虚拟表单已提交并且指定的输入字段参与到其中,此方法将抛出 IllegalArgumentException。
internalVirtualForm 属性
表组件包含 internalVirtualForm 属性,其缺省值为 false。在 Page1.jsp 的表中,该属性已设置为 true。这会导致表在内部使用虚拟表单。因此,使用分页控件时,只会处理表中的输入内容。这可以防止表外部字段的转换器和验证器拒绝提交。
“虚拟表单”对话框
在 Java Studio Creator 2 IDE 中,可以创建、删除和重命名虚拟表单,并且可以使用以下方法更改其颜色代码:右键单击可视编辑器本身(而不是任何组件),然后选择“虚拟表单”上下文菜单项。将打开“虚拟表单”对话框,如图 4 所示。
图 4:“虚拟表单”对话框 |
使用该对话框非常直观。要更改与虚拟表单相关联的颜色,请双击“颜色”单元格,然后从列表中选择一种颜色。要重命名虚拟表单,请双击“名称”单元格,然后编辑该名称。您还可以在该对话框中创建和删除虚拟表单。
“配置虚拟表单”对话框
尽管可以在“虚拟表单”对话框中创建、删除和重命名虚拟表单并且更改其颜色代码,但是无法在其中配置参与和提交每个虚拟表单的组件。您可以在“配置虚拟表单”对话框中完成所有这些操作。要访问该对话框,请在可视编辑器或“概要”窗口中选择一个或多个组件,单击鼠标右键,然后选择“配置虚拟表单”上下文菜单项。在出现的对话框中,可以指定由选定的组件参与的虚拟表单。还可以指定由选定的组件提交的虚拟表单。与“虚拟表单”对话框类似,您可以在“配置虚拟表单”对话框中创建、删除和重命名虚拟表单并更改其颜色代码。图 5 显示了在选择 Page1.jsp 的 "Add Movie" 部分中所有输入组件后显示的“配置虚拟表单”对话框。
图 5:“配置虚拟表单”对话框 |
虚拟表单和更改时自动提交
尽管按钮和链接组件是最常用的提交组件,但也可以将输入组件(如下拉列表)作为提交组件。在 Movie Administration 示例的 Page1.jsp 中,"Current Genre" 下拉列表同时参与并提交 genre 虚拟表单。可以使用“配置虚拟表单”对话框这种方式来配置此虚拟表单。但是,为了使下拉列表确实提交 Web 页,还需要右键单击该组件并打开“更改时自动提交”功能。请注意,按钮和链接组件没有“更改时自动提交”选项,因为它们可以自动提交 Web 页。
虚拟表单和页面片段
Java Studio Creator 2 IDE 的当前发行版本不支持在页面片段中使用虚拟表单。要配置对页面片段中组件的选择性处理,必须将这些组件的 immediate 属性设置为 true。此解决方案完全可以满足多种情况的要求;但目前来说它仍具有局限性,因为它只能对一组组件配置选择性处理。
虚拟表单和标准数据表组件
如果要使用标准数据表组件(不是新的表组件)中的按钮或链接来提交虚拟表单,则必须在按钮或链接的 onClick(或 onclick)属性中添加一些额外的脚本,这种情况虽然不常见,但也应当引起注意。例如,假设标准数据表组件包含一个按钮组件,其 id 属性为 button1。您需要将以下代码添加到该按钮的 onClick 属性中:
common_leaveSubmitterTrace(this.form,'button1');
如果没有这些额外的脚本,该按钮将无法提交虚拟表单。需要再次说明的是:这种情况只适用于标准数据表组件(而不是新的表组件)中的按钮和链接(不是输入组件)。
小结
本技术文章详细介绍了 Sun Java Studio Creator 2 IDE 中的新虚拟表单功能。虚拟表单在页面上定义了一组输入组件(“参与方”)和提交组件(“提交方”),这样当用户与某一提交方进行交互时,就可以专门处理参与方,而忽略页面上的所有其他输入。您已分析了 Movie Administration 示例应用程序的选择性处理要求,并且了解了虚拟表单是如何提供功能强大而全面的解决方案来满足这些要求的。您还了解了如何在 IDE 中通过“虚拟表单”和“配置虚拟表单”对话框来修改页面的虚拟表单配置,以及如果打开了“更改时自动提交”功能的输入组件,提交虚拟表单的方法。最后,与 immediate 属性不同的是,虚拟表单不会改变 JavaServer Faces 的生命周期,因此非常易于使用。
|