JAVA编程技术支持:
1.3 JavaBeans 的 Scope 属性
第一部分 JSP 技术与 J2EE 技术
Resin1.2 服务器 保存路径为
1 doc\WEB-INF\classes\folderName
2 doc\examples\..\WEB\INF\classes\folderName
限于篇幅 关于 JavaBeans 程序在各个 JSP 服务器平台下的保存路径 我们就介绍到 这里 如果读者还希望了解 JavaBeans 程序在其他 JSP 服务器平台下的保存路径 请参考 相应的服务器开发文档 或者是与本书作者联系
1.3 JavaBeans 的 Scope 属性
对于JSP 程序而言 使用 JavaBeans 组件不仅可以封装许多信息 而且还可以将一些 数据处理的逻辑隐藏到JavaBeans 的内部 除此之外 我们还可以设定 JavaBeans 的 Scope 属性 使得 JavaBeans 组件对于不同的任务 具有不同的生命周期和不同的使用范围 在 前面 我们已经提到过Scope 属性具有四个可能的值 分别是 application session request page 分别代表 JavaBeans 的四种不同的生命周期和四种不同的使用范围 下面我们就分别 介绍这四种不同的情况
1.3.1 Application Scope
如果JavaBeans 的 Scope 属性被指定为 application 也就是说这个 JavaBean 组件具有 Application Scope 这是什么意思呢?如果一个 JavaBean 组件具有 Application Scope 那么 它的生命周期和JSP 的 Application 对象同步 作用范围也和 Application 对象一样 使用这 种类型的 JavaBeans 组件 可以在多个用户之间共享全局信息 具体来说 它的生命周期 是这样子的 如果某个JSP 程序使用<jsp:useBean>操作指令创建了一个 JavaBean 对象 而 且这个JavaBean 组件具有 Application Scope 那么这个 JavaBean 就一直在服务器的内存空 间中待命 随时处理客户端的请求 直到服务器关闭为止 它所保存的信息才消失 它所 占用的系统资源才会被释放 在此期间 如果有若干个用户请求的 JSP 程序中 需要用到 这个JavaBean 组件 那么服务器在执行<jsp:useBean>操作指令时 并不会创建新的 JavaBean 组件 而是创建源对象的一个同步拷贝 在任何一个拷贝对象上发生的改变都会影响到源 对象 源对象也会做出同步的改变 不过这个状态的改变不会影响其他已经存在的拷贝对 象 这种类型的JavaBeans 组件的功能和 JSP 的 Application 对象十分类似 不过前者的功 能要强大得多 而且可以自由扩展 用起来也方便得多 请看程序清单1.10(Counter.java) 程序清单1.11(useCounter.jsp)
程序清单 1.10 //File Name:Counter.java //Author:fancy
//Date:2001.3.26
//Note:use this JavaBean to Counter!
package test;
JAVA编程技术支持:
http://shop61582462.taobao.com/
第 1 章 JavaBeans 组件技术
public class Counter {
int Count=1;
public void Counter() {
}
public void addCount() {
Count++;
}
public int getCount() {
return Count;
} }
在程序清单1.10 中 我们定义了一个 Counter Bean 这个 JavaBean 组件可以用于记录 访问者的人数 由于这个程序十分简单 我们就不多做介绍了
程序清单 1.11
<%--
File Name:useCounter.jsp Author:fancy
Date:2001.3.26
Note:use javabean to say hello world!
--%>
<jsp:useBean id="counter" scope="application" class="test.Counter" />
<br>
你好 你是第
<%
out.println(counter.getCount());
counter.addCount();
%>位访客
程序清单1.11(useCounter.jsp)中 首先使用<jsp:useBean>操作指令引入了 JavaBean 组 件 Counter 并且声明它的 Scope 为 Application 这一步十分重要 然后调用 Counter 组件的getCount()方法 获取访问过这个 JSP 程序的人数 如果 Counter 组件刚刚被创建 那么这个方法将会返回缺省值 1 接着调用 Counter 组件的 addCounte()方法 把访问人 数加上1
JAVA编程技术支持:
http://shop61582462.taobao.com/
第一部分 JSP 技术与 J2EE 技术
程序清单1.11 的运行效果如图 1.2 所示
图1.2 useCounter.jsp 的运行效果 1.3.2 Session Scope
如果一个JavaBean 组件的 Scope 属性值为 session 那么这个 JavaBean 组件的生命周 期 作用范围就和 JSP 的 Session 对象的生命周期 作用范围一样 也就是说 这一类型 的 JavaBeans 组件的生命周期就是某个会话过程所经历的时间 也许有的读者对会话过程 还不太了解 实际上 会话过程是对于单个用户而言的 会话过程的开始以用户开始访问 某个网站为标志 会话过程的结束以用户结束对该网站的访问为标志 不同的用户对应着 不同的会话过程 不同的会话过程之间互不干涉 互不影响 假设用户A 第一次访问了某 个网站的某个JSP 程序 而这个 JSP 程序用到了一个 Scope 属性为 session 的 JavaBean 组 件 那么服务器会自动创建这个JavaBean 组件的实例对象 并且当 A 用户继续访问同一网 站其他的JSP 程序 而其他的 JSP 程序又用到同一个 JavaBean 对象时 那么服务器不会创 建新的 JavaBean 对象 而是使用已经存在的 JavaBean 对象实例 也就是说在第一个 JSP 程序中创建的JavaBean 组件对象在这个用户访问的同一网站的所有的 JSP 程序中都是可用 的 而且这个JavaBean 组件对象的状态保持唯一性 如果有另一个用户 B 访问了用户 A 访问过的JSP 程序 那么服务器是否会不创建新的 JavaBean 组件对象 而使用由于用户 A 访问而创建的JavaBean 组件对象呢?答案是否定的 服务器将会为用户 B 创建只属于他的 JavaBean 组件对象 这个新创建的 JavaBean 组件对象在用户 B 访问的同一网站的所有 JSP 程序中都是直接可用的 而不需要创建一个新的组件 并且属于用户A 的 JavaBean 组件对 象和属于用户B 的组件对象都是唯一的 它们之间互不干涉 这里我们讨论的只是两个用 户的情况 其实如果有多个用户在线 情况也一样
综上所述 Scope 属性为 session 的 JavaBeans 组件的功能 作用范围都和 JSP 的 Session 对象十分类似 不过前者的功能比后者要强大得多 并且使用起来也灵活得多 具有可扩 展性 后者没有扩展性
下面我们就利用这种类型的 JavaBeans 组件 来编写一个特殊的计数器程序 这个计 数器并不是统计一个网页的访问人数 而是统计一个用户所访问的页面数目 请看程序清 单1.12(beanPage1.jsp) 程序清单 1.13(beanPage2.jsp)
程序清单 1.12
<%--
File Name:beanPage1.jsp
JAVA编程技术支持:
http://shop61582462.taobao.com/
第 1 章 JavaBeans 组件技术
Author:fancy Date:2001.3.26
Note:use Counter to calculate how many pages this user have visited --%>
<jsp:useBean id="counter" scope="session" class="test.Counter" />
<br>
第一页
<br>
你好 你已经访问了
<%
out.println(counter.getCount());
counter.addCount();
%>个页面
在程序清单1.12 中 我们使用的 JavaBean 组件仍然是我们在程序清单 1.10 中编写的 Counter 不过这里 Counter 对象的 Scope 属性值是 session 而不是 Application 当用户首 先调用beanPage1.jsp 程序时 Counter 对象被创建了 程序清单 1.12 的运行效果如图 1.3 所示
图1.3 beanPage1.jsp 程序的运行效果 程序清单 1.13
<%--
File Name:beanPage2.jsp Author:fancy
Date:2001.3.26
Note:use Counter to calculate how many pages this user have visited --%>
<jsp:useBean id="counter" scope="session" class="test.Counter" />
<br>
第二页
<br>
你好 你已经访问了
<%
JAVA编程技术支持:
http://shop61582462.taobao.com/
第一部分 JSP 技术与 J2EE 技术
out.println(counter.getCount());
counter.addCount();
%>个页面
程序清单 1.13(beanPage2.jsp)程序与程序清单 1.12 基本上是一样的 如果我们首先调 用了程序清单1.12 再访问程序清单 1.13 那么服务器在执行<jsp:useBean>操作指令时 只是返回在程序清单1.12 中创建的 Counter 对象 而不会创建新的 Counter 对象(即使两个 程序文件中的<jsp:useBean>操作指令的 id 属性值不同 也不会创建新的 JavaBean 对象) 程序清单1.13(beanPage2.jsp)的运行效果如图 1.4 所示
图1.4 beanPage2.jsp 程序的运行效果
请读者想一想 如果首先调用 beanPage2.jsp 程序 再调用 beanPage1.jsp 程序 那么 运行效果还会是这样吗?如果不是 那么又应该如何呢?读者不妨试一试
1.3.3 Request Scope
如果JavaBeans 的 Scope 属性值被设为 request 那么这种类型的 JavaBeans 组件对象 又有何特性呢?可能读者已经猜到了 这种类型的 JavaBeans 组件对象的生命周期和作用范 围和JSP 的 Request 对象一样 当一个 JSP 程序使用<jsp:forward>操作指令定向到另外一个 JSP 程序或者是使用<jsp:include>操作指令导入另外的 JSP 程序 那么第一个 JSP 程序会把 Request 对象传送到下一个 JSP 程序 而属于 Request Scope 的 JavaBeans 组件对象也将伴随 着 Request 对象送出 被第二个 JSP 程序接收 因此 所有通过这两个操作指令连接在一 起的JSP 程序都可以共享一个 Request 对象 共享这种类型的 JavaBeans 组件对象 这种类 型的 JavaBeans 组件对象使得 JSP 程序之间传递信息更为容易 不过美中不足的是这种 JavaBeans 不能够用于客户端与服务端之间传递信息 因为客户端是没有办法执行 JSP 程序 创建新的JavaBeans 对象的
下面的程序清单 1.14(RequestBean.java) 程序清单 1.15(beanPage3.jsp)和程序清单 1.16(beanPage4.jsp)演示了这种 JavaBeans 组件对象的使用方法
程序清单 1.14
//File Name:RequestBean.java //Author:fancy
//Date:2001.3.26
//Note:use this JavaBean to transfer info between two jsp program
JAVA编程技术支持:
http://shop61582462.taobao.com/
第 1 章 JavaBeans 组件技术
package test;
public class RequestBean {
String url="index.jsp";
public void Counter() {
}
public void setURL(String strURL) {
url=strURL;
}
public String getURL() {
return url;
} }
在程序清单1.14(RequestBean.java)中创建的 RequestBean Bean 可以用于保存当前页面 的 名 称 缺 省 值 为 index.jsp 在 下 面 的 程 序 清 单 1.15(beanPage3.jsp) 和 程 序 清 单 1.16(beanPage4.jsp)中 将要使用这个 JavaBean 组件实现一个小功能
程序清单 1.15
<%--
File Name:beanPage3.jsp Author:fancy
Date:2001.3.26
Note:use RequestBean to pass info before two different jsp page --%>
<jsp:useBean id="reqBean" scope="request" class="test.RequestBean" />
调用页:beanPage3.jsp
<%
reqBean.setURL("beanPage3.jsp");
%>
<br>
<br>
<jsp:include page="beanPage4.jsp" flush="true" />
在程序清单 1.15 中(beanPage3.jsp) 首先使用<jsp:useBean>操作指令创建一个新的 RequestBean 组件对象 reqBean 然后在 JSP 程序段中使用 setURL()方法把当前程序的名称
JAVA编程技术支持:
http://shop61582462.taobao.com/
第一部分 JSP 技术与 J2EE 技术
beanPage3.jsp 保存在 reqBean 对象的 url 属性中 接下来使用<jsp:include>操作指令导入 beanPage4.jsp 程序
程序清单 1.16
<%--
File Name:beanPage4.jsp Author:fancy
Date:2001.3.26
Note:use RequestBean to pass info before two different jsp page --%>
<jsp:useBean id="reqBean" scope="request" class="test.RequestBean" />
被调用页:beanPage4.jsp
<br>
本页面由
<%
out.println(reqBean.getURL());
%>
调用
在 程 序 清 单 1.16(beanPage4.jsp) 中 同 样 使 用<jsp:useBean> 操 作 指 令 以 便 获 取 RequestBean 组件对象的实例 由于 在 执行 beanPage3.jsp 程序的时候 已 经 创 建了 RequestBean 组件的实例对象 所以在这里就不用创建新的 RequestBean 对象 简单地引用 已经存在的组件对象即可 然后 在JSP 程序段中调用 RequstBean 组件的 getURL()方法 获取使用<jsp:include>操作指令的 JSP 程序的名称 在本例中 这个值应该是 beanPage3.jsp 程序清单1.15(beanPage3.jsp)的运行效果如图 1.5 所示
图1.5 beanPage3.jsp 程序的运行效果
如果不事先运行beanPage3.jsp 而是直接运行 beanPage4.jsp 程序 那么运行效果应该 如何呢?根据我们前面介绍的知识 在执行 beanPage4.jsp 程序中的<jsp:useBean>操作指令 时 由于beanPage4.jsp 没有接受到现存的 RequestBean 组件对象 那么 JSP 服务器将会创 建一个新的 RequestBean 对象 接下来 调用 getURL()方法的时候 由于 RequestBean 的 url 属性未经重新赋值 所以 getURL()方法的执行结果是返回缺省值 index.jsp 程序清单
如果不事先运行beanPage3.jsp 而是直接运行 beanPage4.jsp 程序 那么运行效果应该 如何呢?根据我们前面介绍的知识 在执行 beanPage4.jsp 程序中的<jsp:useBean>操作指令 时 由于beanPage4.jsp 没有接受到现存的 RequestBean 组件对象 那么 JSP 服务器将会创 建一个新的 RequestBean 对象 接下来 调用 getURL()方法的时候 由于 RequestBean 的 url 属性未经重新赋值 所以 getURL()方法的执行结果是返回缺省值 index.jsp 程序清单