>> 更多 Visual Web Pack 文档
了解范围和受管 Bean
撰稿人:Visual Web Pack 教程编写小组
| 2007 年 5 月 [修订号:V5.5.1-1] |
|
|
在本教程中,您将利用 NetBeans Visual Web Pack 创建一个应用程序,以此来说明如何使用应用程序、会话和请求范围对应用程序的对象进行管理。范围指的是对象的可用性(或上下文)及其在 Web 应用程序中的预定生命周期。
您在本教程中创建的 Web 应用程序将使用一个应用程序范围对象来统计投票,使用一个会话范围对象来确保每个用户在每个会话期间只能投票一次。该应用程序还使用请求范围对象来显示用户提交投票的时间。此提交时间存储在请求范围中,因为在将响应发送到客户端浏览器之后,应用程序就不再需要该值。 |
目录
|
|
 |
本教程将使用以下技术和资源
JavaServer Faces 组件/ Java EE 平台 |
1.2/Java EE 5* 1.1/J2EE 1.4
|
| Travel 数据库 |
不是必需的 |
| BluePrints AJAX 组件库 |
不是必需的 |
* 该教程发布时,只有 Sun Java System Application Server 支持 Java EE 5。
本教程是针对使用 Sun Java Application Server PE 9.0 Update Release 1(或更高版本)和 Tomcat 5.5.17 进行定制的。如果您使用的是其他服务器,请参考发行说明和常见问题解答以了解已知问题和解决方法。有关支持的服务器和 Java EE 平台的详细信息,请参见发行说明。
关于范围
只要用户停留在某个页面上,系统就会记住其组件值,即使重新显示该页面(例如,用户单击某个按钮后返回 null)也是如此。但是,当用户离开该页面后,其组件值就会消失。
要使其他页面可以访问这些值,或者当用户返回同一页面时可以访问这些值,则需要对它们进行存储。在 IDE 中创建项目时,IDE 会创建三种用于存储这些值的受管 Bean:
RequestBean1
SessionBean1
ApplicationBean1
下图显示了包含缺省受管 Bean 的“概要”窗口。
图 1:缺省受管 Bean |
受管 bean 是 JavaBeans 对象,JavaServer Faces Web 应用程序对该对象进行实例化并将其存储在请求范围、会话范围或应用程序范围中。Web 应用程序将 RequestBean1 存储在请求范围中,将 SessionBean1 存储在会话范围中,并将 ApplicationBean1 存储在应用程序范围中。
要向其中某个受管 Bean 添加属性,请在“概要”窗口中右键单击该 Bean,然后从弹出式菜单中选择“添加”>“属性”。完成对话框并单击“确定”后,IDE 会将该属性及其相应的 getter 和 setter 方法添加到源代码中。您可以通过以下两种方法访问 Bean 属性的值:将组件的属性绑定到该 Bean 属性,或者调用该 Bean 属性的 getter 和 setter 方法。我们将在本教程中采用这两种访问方法。
在创建 Bean 属性以便存储值之前,您必须为该属性的值确定相应的范围。由于多个用户可以同时访问一个 Web 应用程序,因此,您需要尽可能使用最小的范围以充分利用服务器资源。下图显示了每种类型的范围所持续的时间阶段。
- 应用程序的范围将一直持续到服务器停止应用程序为止。使用相同应用程序映射的每个会话以及每个请求都可以访问存储在应用程序 Bean 中的值。
- 会话范围从用户第一次访问 Web 应用程序中的页面开始,直至由于不活动导致用户会话超时而结束,或者直至 Web 应用程序使会话失效(例如,通过调用
session.invalidate())而结束。
- 请求范围从用户提交页面开始,直至完全呈现响应(不论是哪个页面)而结束。
图 2:Web 应用程序范围 |
例如,您所创建的 Web 应用程序包含一个度量单位(像素、厘米和英寸)的下拉列表。您可能需要在 ApplicationBean1 中存储选项列表,以便让所有并行的用户会话都可以共享该列表。另一方面,您可能还需要在 SessionBean1 中存储用户的登录名,以便让该名称适用于用户在此会话中访问的所有页面。如果您不需要了解有关当前请求的生命周期之外的信息,则可以通过将此属性放在 RequestBean1 中来节省空间。
警告:如果将 <redirect> 元素包含在导航规则的 <navigation-case> 元素中,则不能使用请求 Bean(在页面导航编辑器中单击 "XML" 按钮时,可以看到这些规则)。提交页面时,<redirect> 元素会重定向该页面并结束请求,接下来,后续的页面才能使用请求 Bean 中所存储的任何值。
在 IDE 中创建页面时,页面 Bean 的 Java 源代码包含用于访问 RequestBean1、SessionBean1 和 ApplicationBean1 对象的方法。要访问这些受管 Bean 的属性,请使用类似于以下代码片段中的语句代码。
| 代码样例 1:访问应用程序 Bean 属性 |
ApplicationBean1 appBean = getApplicationBean1();
Option[] choices = appBean.BallotOptions(); |
Web 应用程序将在页面第一次(在 Bean 的范围内)访问受管 Bean 中的属性时,实例化该受管 Bean。例如,只有当用户访问了引用 SessionBean1 属性的页面时,用户会话中才会出现 SessionBean1 对象的实例。ApplicationBean1 对象实例是在任何会话中的页面第一次访问应用程序 Bean 时创建的,而且只要 Web 应用程序处于运行状态,它就会存在。
提示:要添加其他的受管 Bean,请在“项目”窗口中展开“源包”节点,右键单击包节点,选择“新建”>“文件/文件夹”,选择“受管 Bean”类别,选择“文件类型”下的范围,然后完成其余的向导步骤。
向受管 Bean 添加属性
此 Web 应用程序中的页需要访问以下值,您将在本部分创建这些值:
ballotOptions。包含选票选项列表的数组属性。由于此列表对于所有会话来说都是相同的,因此该属性位于应用程序范围中。
tally。累计所有会话投票的散列映射属性。因为它必须存在于会话之间,所以位于应用程序范围中。
hasVoted。跟踪用户是否已投票的布尔型属性。由于应用程序需要在单个会话的多个请求之间保留该值,因此应用程序将其存储在会话范围中。
timestamp。Date 属性,应用程序在其中记录用户提交投票的时间以备下一个页面使用。由于在呈现下一个页面后应用程序不再需要该值,因此应用程序将其存储在请求范围中。
请完成以下步骤,以便向受管 Bean 添加属性。
- 从主菜单中选择“文件”>“新建项目”。
- 在新建项目向导中,从“类别”列表中选择 "Web",然后从“项目”列表中选择“Visual Web 应用程序”。
- 单击“下一步”。
- 将项目命名为
Scopes,然后单击“完成”。
-
在“概要”窗口中,右键单击 "ApplicationBean1",然后从弹出式菜单中选择“添加”>“属性”。
注意:如果第一次右键单击该节点时禁用了“添加”菜单,请按 Esc 键,然后再次单击鼠标右键。
将出现“新建属性模式”对话框,如下图所示。
图 3:“新建属性模式”对话框 |
-
按照以下所示设置属性的“名称”和“类型”,然后单击“确定”。
| 文本字段 |
值 |
| 名称 |
ballotOptions |
| 类型 |
Option[] |
|
-
使用相同的步骤,向应用程序 Bean 添加另一个属性。按照以下所示设置属性的“名称”和“类型”,然后单击“确定”。
| 文本字段 |
值 |
| 名称 |
tally |
| 类型 |
HashMap |
|
- 在“概要”窗口中,右键单击 "ApplicationBean1",然后从弹出式窗口中选择“编辑 Java 源代码”。
-
在源代码中单击鼠标右键,然后从弹出式菜单中选择“修复导入”。
由于多个包中含有 Option 类,因此将出现“修复导入”对话框。
“全限定名称”下拉列表中的 Option 类取决于项目所使用的 Java EE 版本。
- 对于 Java EE 5 项目,请选择
com.sun.webui.jsf.model.Option。
- 对于 J2EE 1.4 项目,请选择
com.sun.rave.web.ui.model.Option。
- 单击“确定”。
-
滚动至 init 方法,然后在该方法的底部添加下面以粗体显示的代码。
代码样例 2:向应用程序 Bean 的 init 方法添加的代码 |
// 待做事项 - 在此处添加您自己的初始化代码
// populate ballot items
ballotOptions = new Option[] {
new Option("java", "Java Programming Language"),
new Option("cpp", "C++"),
new Option("fortran", "Fortran")
};
// initialize counters for ballot choices
tally = new HashMap();
for (int i=0; i < ballotOptions.length; i++) {
this.tally.put(ballotOptions[i].getValue(), "0");
} |
-
在该文件的结尾(紧邻最后一个右花括号之前)添加以下方法。
| 代码样例 3:应用程序 Bean 投票计数方法 |
/**
* Vote counter for property tally.
*/
public void incrementTallyFor(String category) {
int count = getTallyFor(category);
count++;
this.tally.put(category, Integer.toString(count));
}
/**
* Getter for value in property tally.
* @param category HashMap key
* @return Value to which the specified key is mapped
*/
public int getTallyFor(String category) {
String stringCount = (String) this.tally.get(category);
if (stringCount == null) {
return 0;
} else {
int count = Integer.valueOf(stringCount).intValue();
return count;
}
}
|
- 按 Ctrl-S 组合键保存所做的更改,然后按 Ctrl-F4 组合键关闭该文件。
-
在“概要”窗口中,右键单击 "SessionBean1",然后从弹出式菜单中选择“添加”>“属性”。
注意:如果“概要”窗口未打开,请单击编辑区域中的 "Page1" 标签,然后单击编辑工具栏中的“设计”。当 IDE 处于设计模式时,将会出现“概要”窗口。
-
按照以下所示设置属性的“名称”和“类型”,然后单击“确定”。
- 在“概要”窗口中,右键单击 "SessionBean1",然后从弹出式菜单中选择“编辑 Java 源代码”。
-
滚动至 init 方法,然后在该方法的底部添加下面以粗体显示的代码。
代码样例 4:向会话 Bean 的 init 方法添加的代码 |
// 待做事项 - 在此处添加您自己的初始化代码
setHasVoted(false); |
- 按 Ctrl-S 组合键保存所做的更改,然后按 Ctrl-F4 组合键关闭该文件。
- 在“概要”窗口中,右键单击 "RequestBean1",然后从弹出式菜单中选择“添加”>“属性”。
-
按照以下所示设置属性的“名称”和“类型”,然后单击“确定”。
| 文本字段 |
值 |
| 名称 |
timestamp |
| 类型 |
java.util.Date |
|
-
检查“概要”窗口,以确保请求 Bean、会话 Bean 和应用程序 Bean 中的属性与下图匹配。您可能需要打开并保存 RequestBean1 的 Java 源代码以显示 timestamp 属性。
图 4:请求、会话和应用程序 Bean 属性 |
创建起始页
按照此部分的步骤创建下图中的页面,当运行应用程序时,可以在浏览器中显示此页面。如果用户单击 "Submit Vote" 按钮,此页面将提交用户的投票。用户完成投票后,该按钮将变为禁用状态,从而防止用户在该会话中再次投票。
图 5:第一页 |
- 将一个标签组件从组件面板的“基本”类别拖放到页面的顶部中央,并将其 text 属性设置为
Reader's Poll: What Is Your Favorite Programming Language。
- 将一个单选按钮组组件拖放到标签组件的下方。
- 在“属性”窗口中,将该单选按钮组组件的
id 属性设置为 voteRBGroup。
-
右键单击单选按钮组组件,然后从弹出式菜单中选择“绑定到数据”。
将出现“绑定到数据”对话框。
- 在该对话框的“绑定到对象”标签中,选择 "ApplicationBean1" > "ballotOptions",然后单击“确定”。
- 将一个按钮组件拖放到单选按钮组组件的下方,并将其 text 属性设置为
View Results。
- 在“属性”窗口中,将该按钮组件的
id 属性设置为 viewButton。
-
单击 action 属性的省略号 (...) 按钮,从下拉菜单中选择 "viewButton_action",然后单击“确定”。
IDE 将添加 viewButton_action 事件处理程序,该程序返回 null。
- 将一个按钮组件拖放到 "View Results" 按钮的右侧,并将其 text 属性设置为
Submit Vote。
- 在“属性”窗口中,将该按钮组件的
id 属性设置为 voteButton。
-
单击 disabled 属性的省略号 (...) 按钮。
将出现一个对话框。
-
在该对话框中,选择“使用绑定”,单击“绑定到对象”,选择 "SessionBean1" > "hasVoted"(如下图所示),然后单击“确定”。
图 6:绑定 disabled 属性 |
-
双击 "Submit Vote" 按钮。
IDE 将添加 voteButton_action 事件处理程序,打开页面的 Java 源代码并显示该方法。
-
将该方法的主体替换为下面以粗体显示的代码。
代码样例 5:voteButton_action 方法 |
public String voteButton_action() {
if (voteRBGroup.getSelected() == null) {
return null;
}
// Tallies are kept across all user sessions
String votedFor = voteRBGroup.getSelected().toString();
getApplicationBean1().incrementTallyFor(votedFor);
// User can only vote one time per session
getSessionBean1().setHasVoted(true);
// Don't need the timestamp after the next request ends
Date now = new Date();
getRequestBean1().setTimestamp(now);
return null;
} |
- 在源代码中单击鼠标右键,然后从弹出式菜单中选择“修复导入”。
- 从“全限定名称”下拉列表中选择 "
java.util.Date",然后单击“确定”。
创建结果页
按照下面的步骤,创建下图所示的页面(正在浏览器中运行)。此页面用于显示当前的计票情况。用户可以单击 "Refresh Results" 按钮以获得最新的计票,该计票包括自最后一次显示页面以来其他用户提交的投票。
图 7:结果页 |
- 在“项目”窗口中,右键单击 Scopes 项目下的“Web 页”节点,选择“新建”>“页面”,将页面命名为
Results,然后单击“完成”以创建页面。
- 将一个标签组件拖放到 "Results" 页的顶部中央,并将其 text 属性设置为
Results。
- 将一个按钮组件拖放到标签组件的左侧,并将其 text 属性设置为
Home。
- 将该按钮组件的
id 属性设置为 homeButton。
- 单击
action 属性的省略号 (...) 按钮,从下拉列表中选择 "homeButton_action",然后单击“确定”。
- 将一个按钮组件拖放到标签组件的右侧,并将其 text 属性设置为
Refresh Results。
- 将该按钮组件的
id 属性设置为 refreshButton。
- 单击
action 属性的省略号 (...) 按钮,从下拉菜单中选择 "refreshButton_action",然后单击“确定”。
- 将一个网格面板组件从组件面板的“布局”类别拖放到标签组件的下方。
- 在“项目”窗口中,将
cellspacing 属性设置为 10,并将 columns 属性设置为 1。
-
将一个静态文本组件拖动到网格面板组件中。当该网格面板组件的边框变为蓝色实线时,放置静态文本组件,如下图所示。
图 8:在网格面板组件中放置组件 |
- 在“属性”窗口中,将静态文本组件的
id 设置为 resultsST。并将其 text 属性保留为空。
-
清除该静态文本组件的 escape 属性的复选框。
随后,您需要添加代码以在该组件的 text 属性中放置 HTML。通过将 escape 属性设置为 false,会将未经修改的 HTML 代码传递给浏览器。
- 将另一个静态文本组件拖动到网格面板组件中,当该网格面板组件的边框变为蓝色实线时,放置静态文本组件。
- 将该静态文本组件的
id 属性设置为 messageST,并将其 text 属性保留为空。
- 单击编辑工具栏中的 "Java" 以查看该页面的 Java 源代码。
-
在“概要”窗口中,双击 prerender 方法以在 Java 编辑器中将其打开,然后添加下面以粗体显示的代码。
代码样例 6:prerender 方法 |
public void prerender() {
// Display latest poll results
ApplicationBean1 appBean = getApplicationBean1();
Option[] choices = appBean.getBallotOptions();
String str = "<table border=\"0\" cellpadding=\"5\">";
for (int i = 0; i < choices.length; i++) {
int count =
appBean.getTallyFor(choices[i].getValue().toString());
str = str + "<tr><td>" +
choices[i].getLabel() +
"</td><td>" +
count +
"</td></tr>";
}
str = str + "</table>";
resultsST.setText(str);
RequestBean1 reqBean = getRequestBean1();
Date timestamp = (Date) reqBean.getTimestamp();
if (timestamp != null) {
messageST.setText("Your vote was recorded at " +
(String)DateFormat.getTimeInstance(DateFormat.LONG).format(
timestamp));
}
} |
此代码用于创建一个包含每次投票计票的 HTML 表,并将该表放到第一个静态文本组件的 text 属性中。如果用户刚刚投完票,第二个静态文本组件就会显示投票的登记日期和时间。
- 在源代码中单击鼠标右键,然后从弹出式菜单中选择“修复导入”。
- 在 Date 的“类名”下,从“全限定名称”下拉列表中选择
java.util.Date。
在 Option 的“类名”下,“全限定名称”下拉列表中的名称取决于项目所使用的 Java EE 版本。
- 对于 Java EE 5 项目,请选择
com.sun.webui.jsf.model.Option。
- 对于 J2EE 1.4 项目,请选择
com.sun.rave.web.ui.model.Option。
指定页面导航
请按照下列步骤,指定下图中所示的按钮的页面导航。
图 9:页面导航编辑器 |
- 在编辑区域中,单击 "Results" 标签,然后单击“设计”以便在可视设计器中查看该页面。
- 右键单击页面中的空白处,然后从弹出式菜单中选择“页面导航”。
- 单击 "Page1.jsp" 图标以将其放大。
- 单击位于 "viewButton" 旁边的连接器端口并拖动一条直线至 "Results.jsp",以便在该按钮和 Results 页之间创建一条连线。
- 双击该连线的标签以更改为编辑模式,双击以选择文本,键入
view results,然后按 Enter 键。
- 再次单击 "Page1.jsp" 图标以将其放大,然后单击 "voteButton" 旁边的连接器端口并拖动一条直线至 "Results.jsp"。
- 双击连线的标签以更改为编辑模式,双击以选择文本,键入
vote,然后按 Enter 键。
- 单击 "Results.jsp" 图标以将其放大。
- 单击 "homeButton" 旁边的连接器端口并拖动一条直线至 "Page1.jsp"。
- 双击连线的标签以更改为编辑模式,双击以选择文本,键入
home,然后按 Enter 键。
运行应用程序
要通过同一个浏览器来启用多个会话,请配置应用程序以在每个会话一分钟不活动时结束该会话。然后,部署并运行该应用程序。
-
在“文件”窗口中,展开 "Scopes" > "web" > "WEB-INF",如下图所示。
图 10:“文件”窗口 |
- 右键单击 "web.xml",然后从弹出式菜单中选择“打开”。
-
在“会话超时”文本框中键入 1,如下图所示。
图 11:在 web.xml 可视编辑器中设置会话超时 |
- 保存并关闭该文件。
- 单击主工具栏中的“运行主项目”按钮。
-
当出现起始页后,选中一个单选按钮,然后单击 "Submit Vote"。
浏览器将显示结果页。请注意,在结果页上将会显示出您提交投票的时间。
-
单击 "Home" 返回到起始页。
由于您已经投票,因此将禁用 "Submit Vote"。
-
单击 "View Results"。
请注意,结果页不再显示您投票的时间。这是因为以前的请求 Bean 超出范围,并且已实例化新的请求 Bean。
- 请等待一分钟,以使会话超时。然后,在浏览器的地址文本框中键入以下 URL 并按 Enter 键启动新的会话:
http://localhost:8080/Scopes。如果未使用缺省的服务器配置,则可能需要将 8080 更改为其他端口。
- 再次投票并检查结果。结果应当包括第一次的投票。
- 如果具有不同的浏览器应用程序,请启动该浏览器,在浏览器的地址文本框中键入
http://localhost:8080/Scopes,然后按 Enter 键。提交另一个投票。
-
在第一个浏览器中,单击结果页中的 "Refresh Results"。
结果应当包括通过第二个浏览器提交的投票。
执行更多操作
利用在本教程中所学到的内容,您可以构建一个提示输入登录名的应用程序。然后,添加一个页面,该页面用于显示已访问此 Web 应用程序的用户的数量(不包括每位用户重复访问的次数)。
小结
您可以使用应用程序 Bean、会话 Bean 和请求 Bean 来存储信息以供其他页面使用。
- 使用应用程序 Bean 可存储适用于所有用户会话的信息,如下拉列表组件的静态选项列表。
- 使用会话 Bean 可存储在整个用户会话期间供其他页面使用的信息,如用户的登录名。
- 如果只需要供下一个页面使用的信息,应使用请求 Bean。
警告:如果将 <redirect> 元素包含在导航规则的 <navigation-case> 元素中,则不能使用请求 Bean。
在页面访问请求 Bean、会话 Bean 或应用程序 Bean 中的某个属性时,将会实例化这些 Bean。当 Bean 的范围结束时,这些 Bean 将会被销毁。
要向会话 Bean 添加属性,请右键单击“概要”窗口中的会话 Bean 节点,然后选择“添加”>“属性”。此外,也可以使用类似的步骤向请求 Bean 或应用程序 Bean 添加属性。
>> 更多 Visual Web Pack 文档
此页的最新修改时间:2007 年 5 月 24 日