有些 JSP 程序员会将 request、session、application 和 pageContext 归为一类,原因在于:
它们皆能借助 setAttribute( )和 getAttribute( )来设定和取得其属性(Attribute),通过这两种 方法来做到数据分享。
我们先来看下面这段小程序:
Page1.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - Page1.jsp</title>
</head>
<body>
</br>
<%
application.setAttribute("Name","mike");
application.setAttribute("Password","browser");
%>
<jsp:forward page="Page2.jsp"/>
</body>
</html>
在这个程序中,笔者设定两个属性:Name、Password,其值为:mike、browser。然后再转交(forward) 到 Page2.jsp。我只要在 Page2.jsp 当中加入 application.getAttribute( ),就能取得在 Page1.jsp 设定的数据。
Page2.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - Page2.jsp</title>
</head>
<body>
<%
String Name = (String) application.getAttribute("Name");
String Password = (String) application.getAttribute("Password");
out.println("Name = "+Name);
out.println("Password = "+ Password);
%>
</body>
</html>
Page1.jsp 的执行结果如图 5-1 所示。
图 5-1 Page1.jsp 的执行结果
从图 5-1 可以看出,此时 Name 的值就会等于 mike,Password 的值就等于 browser。看完这个小 范例之后,读者有没有发现网页之间要传递数据时,除了可以使用窗体、隐藏字段来完成之外,JSP 技术还提供给开发人员一项传递数据的机制,那就是利用 setAttribute( )和 getAttribute( )方法,
如同 Page1.jsp 和 Page2.jsp 的做法。不过它还是有些限制的,这就留到下一节来说明。
在上面 Page1.jsp 和 Page2.jsp 的程序当中,是将数据存入到 application 对象之中。除了 application 之外,还有 request、pageContext 和 session,也都可以设定和取得属性值,那它们 之间有什么分别吗?
它们之间最大的差别在于范围(Scope)不一样,这个概念有点像 C、C++中的全局变量和局部变量 的概念。接下来就介绍 JSP 的范围。
5-1-1 JSP Scope—Page
JSP 有四种范围,分别为 Page、Request、Session、Application。所谓的 Page,指的是单单一 页 JSP Page 的范围。若要将数据存入 Page 范围时,可以用 pageContext 对象的 setAttribute( ) 方法;若要取得 Page 范围的数据时,可以使用 pageContext 对象的 getAttribute( )方法。我们将 之前的范例做小幅度的修改,将 application 改为 pageContext。
PageScope1.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - PageScope1.jsp</title>
</head>
<body>
<h2>Page 范围 - pageContext</h2>
<%
pageContext.setAttribute("Name","mike");
pageContext.setAttribute("Password","browser");
%>
<jsp:forward page="PageScope2.jsp"/>
</body>
</html>
PageScope2.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - PageScope2.jsp</title>
</head>
<body>
<h2>Page 范围 - pageContext</h2>
</br>
<%
String Name = (String)pageContext.getAttribute("Name");
String Password = (String)pageContext.getAttribute("Password");
out.println("Name = "+Name);
out.println("Password = "+ Password);
%>
</body>
</html>
执行结果如图 5-2 所示。
图 5-2 PageScope1.jsp 的执行结果
这个范例程序和之前有点类似,只是之前的程序是 application,现在改为 pageContext,但是结 果却大不相同,PageScope2.jsp 根本无法取得 PageScope1.jsp 设定的 Name 和 Password 值,因为在 PageScope1.jsp 当中,是把 Name 和 Password 的属性范围设为 Page,所以 Name 和 Password 的值只能 在 PageScope1.jsp 当中取得。若修改 PageScope1.jsp 的程序,重新命名为 PageScope3.jsp,如下:
PageScope3.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - PageScope3.jsp</title>
</head>
<body>
<h2>Page 范围 - pageContext</h2>
</br>
<%
pageContext.setAttribute("Name","mike");
pageContext.setAttribute("Password","browser");
String Name = (String)pageContext.getAttribute("Name");
String Password = (String)pageContext.getAttribute("Password");
out.println("Name = "+Name);
out.println("Password = "+ Password);
%>
</body>
</html>
PageScope3.jsp 的执行结果如图 5-3 所示。
图 5-3 PageScope3.jsp 的执行结果
经过修改后的程序,Name 和 Password 的值就能顺利显示出来。这个范例主要用来说明一个概 念:若数据设为 Page 范围时,数据只能在同一个 JSP 网页上取得,其他 JSP 网页却无法取得该数据。
5-1-2 JSP Scope—Request
接下来介绍第二种范围:Request。Request 的范围是指在一 JSP 网页发出请求到另一个 JSP 网 页之间,随后这个属性就失效。设定 Request 的范围时可利用 request 对象中的 setAttribute( ) 和 getAttribute( )。我们再来看下列这个范例:
RequestScope1.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - RequestScope1.jsp</title>
</head>
<body>
<h2>Request 范围 - request</h2>
<%
request.setAttribute("Name","mike");
request.setAttribute("Password","browser");
%>
<jsp:forward page="RequestScope2.jsp"/>
</body>
</html>
RequestScope2.jsp
<%@ page contentType="text/html;charset=GB2312" %>
<html>
<head>
<title>CH5 - RequestScope2.jsp</title>
</head>
<body>
<h2>Request 范围 - request</h2>
<%
String Name = (String) request.getAttribute("Name");
String Password = (String) request.getAttribute("Password");
out.println("Name = "+Name);
out.println("Password = "+ Password);
%>
</body>
</html>
RequestScope1.jsp 的执行结果如图 5-4 所示。
现在将 Name 和 Password 的属性范围设为 Request,当 RequestScope1.jsp 转向到 RequestScope2.jsp 时, RequestScope2.jsp 也能取得 RequestScope1.jsp 设定的 Name 和 Password 值。不过其他的 JSP 网页
无法得到 Name 和 Password 值,除非它们也和 RequestScope1.jsp 有请求的关系。
图 5-4 RequestScope1.jsp 的执行结果
除了利用转向(forward)的方法可以存取 request 对象的数据之外,还能使用包含(include)的 方法。
假若我将 RequestScope1.jsp 的
<jsp:forward page="RequestScope2.jsp"/>
改为
<jsp:include page="RequestScope2.jsp" flush="true"/>
执行 RequestScope1.jsp 时,结果还是和图 5-4 一样。表示使用<jsp:include>标签所包含进来 的网页,同样也可以取得 Request 范围的数据。
5-1-3 JSP Scope—Session、Application
表 5-2 介绍了最后两种范围:Session、Application。
表 5-2
范 围 说 明
Session
Session 的作用范围为一段用户持续和服务器所连接的时间,但与服务 器断线后,这个属性就无效。只要将数据存入 session 对象,数据的范 围就为 Session
Application
Application 的作用范围在服务器一开始执行服务,到服务器关闭为 止。Application 的范围最大、停留的时间也最久,所以使用时要特别注 意,不然可能会造成服务器负载越来越重的情况。只要将数据存入 application 对象,数据的 Scope 就为 Application
表 5-3 列出了一般储存和取得属性的方法,以下 pageContext、request、session 和 application 皆可使用。
注意
pageContext 并无 getAttributeNames( )方法。
表 5-3
方 法 说 明
void setAttribute(String name, Object value) 设定 name 属性的值为 value Enumeration getAttributeNamesInScope(int
scope ) 取得所有 scope 范围的属性
Object getAttribute(String name) 取得 name 属性的值
void removeAttribute(String name) 移除 name 属性的值
当 我 们 使 用 getAttribute(String name) 取 得 name 属 性 的 值 时 , 它 会 回 传 一 个 java.lang.Object,因此,我们还必须根据 name 属性值的类型做转换类型(Casting)的工作。例如:
若要取得 String 类型的 Name 属性时:
String Name = (String)pageContext.getAttribute("Name");
若是 Integer 类型的 Year 属性时:
Integer Year = (Integer)session.getAttribute("Year");
到目前已大约介绍完 JSP 中四种范围(Scope):Page、Request、Session 和 Application。假若 我的数据要设为 Page 范围时,则只需要:
pageContext.setAttribute("Year", new Integer(2001));
若要为 Request、Session 或 Application 时,就分别存入 request、session 或 application 对象之中,如下:
request.setAttribute("Month", new Integer(12) );
session.setAttribute("Day", new Integer(27) );
application.setAttribute("Times", new Integer(10));
接下来就正式进入本章的主题:隐含对象(Implicit Object)。