JSP中四大作用域詳解


四大作用域

  為了在頁面、請求、和用戶之間傳遞和共享數據,JSP提供了四個不同的作用域:page(頁面作用域)、request(請求作用域)、session(會話作用域)、application(應用程序作用域),這些作用域就規定了數據可以傳遞和共享的范圍以及數據的存活時間。

page(頁面作用域)

  JSP默認的作用域是page,這個作用域中的對象只能在該頁面中使用,不允許在其他頁面使用。我們可以通過調用pageContext這個隱含的對象的getAttribute()和setAttribute()方法去獲取和設置需要傳遞、共享具有這種范圍類型的數據。(pageContext對象還提供了訪問其他范圍對象的getAttribute方法)。page范圍內的對象,在客戶端每次請求JSP頁面時創建,在頁面向客戶端發送回響應或請求被轉發(forward)到其他的資源后被刪除。JSP最終會被編譯成Servlet文件。在Servlet容器中,每個Servlet都只存在一個實例。但是對於page作用域的屬性來說,在當前頁面設置的屬性只在本次訪問該頁面有效,當你再次訪問該頁面時,又會重新初始化頁面的屬性。

1 <%
2 out.print(pageContext.getAttribute("SiteName")); // 輸出null
3 pageContext.setAttribute("SiteName", "博客園");
4 %>

  當我在瀏覽器訪問該頁面時會輸出null;當我再重新打開一個該頁面時,還會輸出null,並不會輸出”博客園”。也就是說,page作用域范圍的不會存在線程安全的問題,每一次訪問同一個頁面,設置的page作用域的屬性都是不一樣的。

request(請求作用域)

  request在一次請求的全過程中有效,即從http請求到服務器處理結束,返回響應的整個過程,存放在HttpServletRequest對象中。一次請求的生命周期從客戶端發起到服務器接收並響應該請求,或者將該請求forward到另一個頁面或者Servlet進行處理而結束。在此期間,本次請求的參數,屬性都是有效的;一旦客戶端刷新瀏覽器,重新發起請求,則之前的請求參數和屬性都將失效。需要注意的是,當我們使用<jsp:forward .../>動作將當前請求轉向另一個頁面或者Servlet的時候,該請求的參數和屬性也一並轉過去,並不會因為<jsp:forward .../>動作而丟失request的參數和屬性。

session(會話作用域)

  當我們向服務器發送第一個請求開始,只要頁面不關閉,或者會話未過期(默認30分鍾),或者未調用HttpSession的invalidate()方法,接下來的操作都屬於同一次會話的范疇。在JSP中,每當向服務器發送一個請求,服務器響應這個請求的時候,會在客戶端的Cookie中寫一個session id值。每次發送請求的時候,會將該session id值一起發送到服務器端,服務器端根據該session id值來判斷每次請求是否屬於同一個session的范疇之內。其存放在HttpSession對象中。

application(應用程序作用域)

  application的作用域是最廣的,它代表着整個Web應用的全局變量,對每一個頁面,每一個Servlet都是有效的。當我們在application中設置屬性時,這個屬性在任意的一個頁面都是可以訪問的。在application作用域中設置的屬性如果不手動調用removeAttribute函數進行刪除的話,它們就一直可以使用,如果Web容器發生重啟,此時application范圍內的所有屬性都將丟失。

注意:根據jsp規范,用於某個對象的名稱必須在所有作用域中都是唯一的。也就是說,如果application作用域中有一個名為user的對象,而且在request作用域中用相同的名稱保存着另一個對象,那么容器可能會移除第一個對象,盡管很少有容器會執行這項規則,但是為了使您的項目更加完善,還是應該確保在任何地方都是用唯一的名稱,除非所保存的對象為同一個。

如何使用

  • page里的變量沒法從index.jsp傳遞到test.jsp。只要頁面跳轉了,它們就不見了。  
  • request里的變量可以跨越forward前后的兩頁。但是只要刷新頁面,它們就重新計算了。  
  • session的變量一直在累加,開始還看不出區別,只要關閉瀏覽器,再次重啟瀏覽器訪問這頁,session里的變量就重新計算了。  
  • application里的變量一直在累加,除非你重啟tomcat,否則它會一直變大。  
  • 如果把變量放到pageContext里,就說明它的作用域是page,它的有效范圍只在當前jsp頁面里。 從把變量放到pageContext開始,到jsp頁面結束,你都可以使用這個變量。  
  • 如果把變量放到request里,就說明它的作用域是request,它的有效范圍是當前請求周期。 所謂請求周期,就是指從http請求發起,到服務器處理結束,返回響應的整個過程。在這個過程中可能使用forward的方式跳轉了多個jsp頁面,在這些頁面里你都可以使用這個變量。 
  • 如果把變量放到session里,就說明它的作用域是session,它的有效范圍是當前會話。 所謂當前會話,就是指從用戶打開瀏覽器開始,到用戶關閉瀏覽器這中間的過程。這個過程可能包含多個請求響應。也就是說,只要用戶不關瀏覽器,服務器就有辦法知道這些請求是一個人發起的,整個過程被稱為一個會話(session),而放到會話中的變量,就可以在當前會話的所有請求里使用。 
  • 如果把變量放到application里,就說明它的作用域是application,它的有效范圍是整個應用。 整個應用是指從應用啟動,到應用結束。沒有說“從服務器啟動,到服務器關閉”,是因為一個服務器可能部署多個應用,當然你關閉了服務器,就會把上面所有的應用都關閉了。 application作用域里的變量,它們的存活時間是最長的,如果不進行手工刪除,它們就一直可以使用。與上述三個不同的是,application里的變量可以被所有用戶共用。如果用戶甲的操作修改了application中的變量,用戶乙訪問時得到的是修改后的值。這在其他scope中都是不會發生的,page, request, session都是完全隔離的,無論如何修改都不會影響其他人的數據。

舉例說明

  假如一個網站WebSite,其包含7個jsp頁面,分別為master.jsp、top.jsp、main.jsp、foot.jsp、login.jsp、success.jsp和news.jsp。master.jsp頁面通過<include>指令包含top.jsp、main.jsp、foot.jsp三個頁面,當用戶通過login.jsp登錄成功后,進入success.jsp頁面然后通過此頁面的<forward>標簽跳轉到master.jsp頁面中。
我們在success.jsp頁面中加入如下代碼(用到jstl標簽) 
1 <span style="font-family:'微軟雅黑', 'Microsoft YaHei';">
2 <c:set value="aaa" var="test1" scope="page" />  
3 <c:set value="aaa" var="test2" scope="request" />  
4 <c:set value="aaa" var="test3" scope="session" />  
5 <c:set value="aaa" var="test4" scope="application"/>  
6 <jsp:forward page="master.jsp"/ >這里跳轉  
7 </span>
  1. 變量 test1 只在success.jsp內有效;
  2. 變量 test2 在success.jsp、master.jsp、top.jsp、main.jsp、foot.jsp中有效;
  3. 變量 test3 在7個頁面中都有效(包括login.jsp和news.jsp);
  4. 變量 test4 在整個網站,當前也就是7個頁面中都有效(包括login.jsp和news.jsp)。
  Test3和test4有效范圍一樣,有什么區別呢?說明一點,假如此時又有另一個用戶訪問master.jsp頁面,那么test3相對於這個用戶來說就無效,而test4卻是有效的。或者當第一個登錄的用戶關閉瀏覽器后,再重新訪問master.jsp時,test3就無效,而test4卻有效。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM