四 个 域 的 作 用 域 范 围 大 小 : page < request < session < application
1.page作用域
page作用域在这4种类型中范围是最小的,客户端每次请求访问时都会创建一个JavaBean对象。JavaBean对象的有效范围是客户请求访问的当前页面文件,当客户执行当前的页面文件完毕后JavaBean对象结束生命。
(1)生命周期:当对 JSP的请求时开始,当响应结束时销毁。
(2)作用范围:整个 JSP页面,是四大作用域中最小的一个,即超过这个页面就不能够使用 了。 (所以使用 pageContext 对象向其它页面传递参数是不可能的 .) 作用:
1)获取其它八大隐式对象,可以认为是一个入口对象。
2)获取其所有域中的数据 pageContext 操作所有域中属性的方法 :
public java.lang.Object getAttribute(java.lang.String name,int scope)
public void setAttribute(java.lang.String name, java.lang.Object value,int scope)
public void removeAttribute(java.lang.String name,int scope)
pageContext 中代表域的常量 :
PageContext.APPLICATION_SCOPE
PageContext.SESSION_SCOPE
PageContext.REQUEST_SCOPE
PageContext.PAGE_SCOPE
findAttribute 方法 ,在四大域中搜寻属性,搜寻的顺序是 page 域、 request 域、 session 域、 application 域, 从小域到大域开始搜索,如果搜索到就直接获取该值,如果所有域中都找不到,返回一个 null(与 el 表达式不同,此处返回 null,对网页是不友好的 )
3)跳转到其他资源,其身上提供了 forward 和 include 方法,简化重定向和转发的操作。
2.request作用域
当scope为request时,JavaBean对象被创建后,它将存在于整个request的生命周期内,request对象是一个内建对象,使用它的getParameter方法可以获取表单中的数据信息。
(1)生命周期: 在 service 方法调用前由服务器创建, 传入 service 方法。整个请求结束, request 生命结束。
(2)作用范围:整个请求链(请求转发也存在) 。
( 3)作用: 在整个请求链中共享数据。最常用到:在 Servlet 中处理好的数据交给 Jsp 显示, 此时参数就可以放置在 Request 域中带过去。
3.session作用域
当scope为session时,JavaBean对象被创建后,它将存在于整个session的生命周期内.在同一个浏览器内,JavaBean对象就存在于一个session中。当重新打开新的浏览器时,就会开始一个新的session。每个session中拥有各自的JavaBean对象。
HttpSession 在服务器中, 为浏览器创建独一无二的内存空间, 在其中保存会话相关的信息。
(1)生命周期:在第一次调用 request.getSession() 方法时,服务器会检查是否已经有对应的 session,如果没有就在内存 中创建一个 session并返回。 当一段时间内 session 没有被使用(默认为 30 分钟),则服务器会销毁该 session。 如果服务器非正常关闭(强行关闭) ,没有到期的 session也会跟着销毁。 如果调用 session 提供的 invalidate (),可以立即销毁 session。 注意:服务器正常关闭,再启动, Session 对象会进行钝化和活化操作。同时如果服务器钝 化的时间在 session 默认销毁时间之内, 则活化后 session 还是存在的。 否则 Session 不存在。 如果 JavaBean 数据在 session 钝化时,没有实现 Serializable 则当 Session活化时,会消失。

(2)作用范围:一次会话。
4.application作用域
当scope为application时,JavaBean对象被创建后,它将存在于整个主机或虚拟主机的生命周期内,application范围是JavaBean的生命周期最长的。
(1)生命周期:当 Web 应用被加载进容器时创建代表整个 web 应用的 ServletContext 对象, 当服务器关闭或 Web 应用被移除时, ServletContext 对象跟着销毁。
(2)作用范围:整个 Web 应用。
(3)作用:
a) 在不同 Servlet 之间转发 this.getServletContext().getRequestDispatcher("/servlet/Demo10Servlet").forward(request,respo nse); 方法执行结束, service 就会返回到服务器, 再有服务器去调用目标 servlet ,其中 request 会重新创建,并将之前的 request 的数据拷贝进去。
b) 读取资源文件。
1)由于相对路径默认相对的是 java 虚拟机启动的目录,所以我们直接写相对路径将会是相 对于 tomcat/bin 目录,所以是拿不到资源的。 如果写成绝对路径,当项目发布到其他环境时,绝对路径就错了。
2)为了解决这个问题 ServletContext 提供了: this.getServletContext().getRealPath( “ /1.properties ”),给进一个资源的虚拟路径,将 会返回该资源在当前环境下的真实路径。 this.getServletContext().getResourceAsStream( “ /1.properties ”),给一个资源的虚拟路径 返回到该资源真实路径的流。
3)当在非 servlet 下获取资源文件时,就没有 ServletContext 对象用了,此时只能用类加载 器 classLoader.getResourceAsStream(“../../1.properties ”),此方法利用类加载器直接将资 源加载到内存中,有更新延迟的问题, 以及如果文件太大,占用内存过大。 classLoader.getResource(“../1.properties ”).getPath(),直接返回资源的真实路径,没有 更新延迟的问题。
案例4-4 测试JavaBean的作用域。
4_3.jsp:
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ page language="java" import="ch4.Person" %>
<html>
<head><title>测试JavaBean的作用域</title>
</head>
<body>
<jsp:useBean id="person" class="ch4.Person" scope="application"></jsp:useBean>
<jsp:setProperty name="person" property="name" value="lan"/>
<jsp:setProperty name="person" property="sex" value="男"/>
<jsp:setProperty name="person" property="age" value="18"/>
<br><a href="4_3.jsp">测试JavaBean的四个作用域</a>
</body>
</html>
点击超链接后,跳转到4_3.jsp,因为useBean的作用域是全局,所以从4_3.jsp页面也可以获得name、age。
4_4.jsp:
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ page language="java" import="ch4.Person" %>
<html>
<head><title>测试JavaBean的作用域</title>
</head>
<body>
使用内置对象获取姓名和年龄
<hr>
application作用域:<br>
姓名:<%= ((Person)application.getAttribute("person")).getName() %><br>
年龄:<%= ((Person)application.getAttribute("person")).getAge() %> <br>
session作用域:<br>
姓名:<%= ((Person)session.getAttribute("person")).getName() %><br>
年龄:<%= ((Person)session.getAttribute("person")).getAge() %> <br>
<%--
request作用域:<br>
姓名:<%= ((Person)request.getAttribute("person")).getName() %><br>
年龄:<%= ((Person)request.getAttribute("person")).getAge() %> <br>
page作用域:<br>
姓名:<%= ((Person)pageContext.getAttribute("person")).getName() %><br>
年龄:<%= ((Person)pageContext.getAttribute("person")).getAge() %> <br>
--%>
</body>
</html>
用request的作用域时,4_3.jsp页面就不能获取值了,因为超链接是一个请求重定向,而request作用域只在一次请求里有效。可以将超链接改为
<%
request.getRequestDispatcher("4_3.jsp").forward(request,response);
%>
但如果作用域是page,那就算服务器内部转发也不行了。因为只要换个页面,page就不能生效了。

