1. 程式人生 > >JSP的四個作用域

JSP的四個作用域

首先要宣告一點,所謂“作用域”就是“資訊共享的範圍”,也就是說一個資訊能夠在多大的範圍內有效。4個JSP內建物件的作用域分別為:application、session、request、page 。JSP內建物件作用域表如下:

名稱

作用域

application

在所有應用程式中有效

session

在當前會話中有效

request

在當前請求中有效

page

在當前頁面有效

Web互動的最基本單位為HTTP請求。每個使用者從進入網站到離開網站這段過程稱為一個HTTP會話,一個伺服器的執行過程中會有多個使用者訪問,就是多個HTTP會話。作用域解釋如下。

application 作用域

     如果把變數放到application裡,就說明它的作用域是application,它的有效範圍是整個應用。 整個應用是指從應用啟動,到應用結束。我們沒有說“從伺服器啟動,到伺服器關閉”,是因為一個伺服器可能部署多個應用,當然你關閉了伺服器,就會把上面所有的應用都關閉了。 application作用域裡的變數,它們的存活時間是最長的,如果不進行手工刪除,它們就一直可以使用。

application作用域上的資訊傳遞是通過ServletContext實現的,它提供的主要方法如下所示:

Object getAttribute(String name)  //從application中獲取資訊;

void setAttribute(String name, Object value)  //向application作用域中設定資訊。

session作用域

       session作用域比較容易理解,同一瀏覽器對伺服器進行多次訪問,在這多次訪問之間傳遞資訊,就是session作用域的體現。如果把變數放到session裡,就說明它的作用域是session,它的有效範圍是當前會話。所謂當前會話,就是指從使用者開啟瀏覽器開始,到使用者關閉瀏覽器這中間的過程。這個過程可能包含多個請求響應。也就是說,只要使用者不關瀏覽器,伺服器就有辦法知道這些請求是一個人發起的,整個過程被稱為一個會話(session),而放到會話中的變數,就可以在當前會話的所有請求裡使用。 
 session是通過HttpSession介面實現的,它提供的主要方法如下所示:

Object HttpSession.getAttribute(String name) //從session中獲取資訊。

void HttpSession.setAttribute(String name, Object value)//向session中儲存資訊。

HttpSession HttpServletRequest.getSessio() //獲取當前請求所在的session的物件。

 session的開始時刻比較容易判斷,它從瀏覽器發出第一個HTTP請求即可認為會話開始。但結束時刻就不好判斷了,因為瀏覽器關閉時並不會通知伺服器,所以只能通過如下這種方法判斷:如果一定的時間內客戶端沒有反應,則認為會話結束。Tomcat的預設值為120分鐘,但這個值也可以通過HttpSession的setMaxInactiveInterval()方法來設定:

void setMaxInactiveInterval(int interval)

如果想主動讓會話結束,例如使用者單擊“登出”按鈕的時候,可以使用 HttpSession 的 invalidate()方法,用於強制結束當前session:void invalidate()

request作用域

     一個HTTP請求的處理可能需要多個Servlet合作,而這幾個Servlet之間可以通過某種方式傳遞資訊,但這個資訊在請求結束後就無效了。request裡的變數可以跨越forward前後的兩頁。但是隻要重新整理頁面,它們就重新計算了。如果把變數放到request裡,就說明它的作用域是request,它的有效範圍是當前請求週期。 所謂請求週期,就是指從http請求發起,到伺服器處理結束,返回響應的整個過程。在這個過程中可能使用forward的方式跳轉了多個jsp頁面,在這些頁面裡你都可以使用這個變數。

Servlet之間的資訊共享是通過HttpServletRequest介面的兩個方法來實現的:

void setAttribute(String name, Object value) //將物件value以name為名稱儲存到request作用域中。

Object getAttribute(String name)//從request作用域中取得指定名字的資訊。

     JSP中的doGet()、doPost()方法的第一個引數就是HttpServletRequest物件,使用這個物件的 setAttribute()方法即可傳遞資訊。那麼在設定好資訊之後,要通過何種方式將資訊傳給其他的Servlet呢?這就要用到RequestDispatcher介面的forward()方法,通過它將請求轉發給其他Servlet。

 RequestDispatcher ServletContext.getRequestDispatcher(String path) //取得Dispatcher以便轉發,path為轉發的目的Servlet。

 void RequestDispatcher.forward(ServletRequest request, ServletResponse response)//將request和response轉發

     因此,只需要在當前Servlet中先通過setAttribute()方法設定相應的屬性,然後使用forward()方法進行跳轉,最後在跳轉到的Servlet中通過使用getAttribute()方法即可實現資訊傳遞。

  需要注意兩點:

1、轉發不是重定向,轉發是在Web應用內部進行的。

2、轉發對瀏覽器是透明的,也就是說,無論在伺服器上如何轉發,瀏覽器位址列中顯示的仍然是最初那個Servlet的地址。

page作用域

page物件的作用範圍僅限於使用者請求的當前頁面,對於page物件的引用將在響應返回給客戶端之後被釋放,或者在請求被轉發到其他地方後被釋放。page裡的變數只要頁面跳轉了,它們就不見了。如果把變數放到pageContext裡,就說明它的作用域是page,它的有效範圍只在當前jsp頁面裡。從把變數放到pageContext開始,到jsp頁面結束,你都可以使用這個變數。

以上介紹的作用範圍越來越小,request和page的生命週期都是短暫的,它們之間的區別:一個request可以包含多個page頁(include,forward及filter)。

為了讓大家更容易理解application、session、request、page 4個物件的作用範圍,我們給出兩個程式來進行詳細說明。

【程式1】page01.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"  
    pageEncoding="UTF-8"%>  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<jsp:useBean id="pagevar" scope="page" class="java.lang.StringBuffer"/>  
<jsp:useBean id="requestvar" scope="request" class="java.lang.StringBuffer"/>  
<jsp:useBean id="sessionvar" scope="session"  class="java.lang.StringBuffer"/>  
 <jsp:useBean id="applicationvar" scope="application"  class="java.lang.StringBuffer"/>  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<title>JSP內建物件作用域</title>  
</head>  
<body>  
 <%  
    pagevar.append("page01");  
    requestvar.append("page01");  
    sessionvar.append("page01");  
    applicationvar.append("page01");  
%>  
<jsp:forward page="page02.jsp"/>  
</body>  
</html>  

【程式2】page02.jsp

<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"  
    pageEncoding="UTF-8"%>  
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<jsp:useBean id="pagevar" scope="page" class="java.lang.StringBuffer"/>  
<jsp:useBean id="requestvar" scope="request" class="java.lang.StringBuffer"/>  
<jsp:useBean id="sessionvar" scope="session" class="java.lang.StringBuffer"/>  
<jsp:useBean id="applicationvar" scope="application" class="java.lang.StringBuffer"/>  
<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
<title>JSP內建物件作用域</title>  
</head>  
<body>  
<%  
    pagevar.append("page02");  
    requestvar.append("page02");  
    sessionvar.append("page02");  
    applicationvar.append("page02");  
%>  
page = <%=pagevar.toString()%><br/>  
request = <%=requestvar.toString()%><br/>  
session = <%=sessionvar.toString()%><br/>  
application = <%=applicationvar.toString()%><br/>  
</body>  
</html>  

測試步驟以及結果分析:

1、直接執行程式1的結果為:(圖1)

程式1的結果

我們看到,page的作用域的值為page02,說明確實只在當前的頁面起作用,即跳轉到的page2頁面;request的作用域在當前請求中有效,所以其值為程式1和跳轉到程式2之和;session的作用域為當前會話,所以其值也是程式1和跳轉到程式2之和;而application對所有應用有效,也就是隻要在應用,都要疊加,即程式1中的值與程式2中的值的疊加;

2、不要關閉程式1執行的瀏覽器,直接執行程式2,其結果為:(圖2)

保持程式1執行的瀏覽器,直接執行程式2的結果圖

對比圖1的結果,我們發現page作用域沒有變化,它的值只是程式2裡的值;request作用域僅在當前請求作用,故也以程式2的值為準,變成page02;session的作用域為當前會話,因為執行程式1的瀏覽器保持著,說明還處於同一會話中,所以要在之前的基礎上疊加上一個page02;而application對所有應用有效,也就是隻要在應用,都要疊加,即在之前的基礎上疊加上一個程式2的page02;

3、將上兩步執行程式1和程式2的瀏覽器關閉,但不關閉伺服器,重新執行程式2,其結果如下:

步驟三執行結果

對比之前的結果,我們發現page作用域依舊沒有變化,它的值只是程式2即所在頁面裡的值;request作用域僅在當前請求作用,故也以程式2的值為準,變成page02;session的作用域為當前會話,因為前兩步執行程式的瀏覽器關閉了,說明之前的會話都結束了,所以其值恢復成當前的程式2裡的值page02;而application對所有應用有效,也就是隻要在應用即伺服器還沒重啟清空,都要疊加,即在之前的基礎上再疊加上一個程式2的page02;