四大作用域
為了在頁面、請求、和用戶之間傳遞和共享數據,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(請求作用域)
session(會話作用域)
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都是完全隔離的,無論如何修改都不會影響其他人的數據。
舉例說明
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>
- 變量 test1 只在success.jsp內有效;
- 變量 test2 在success.jsp、master.jsp、top.jsp、main.jsp、foot.jsp中有效;
- 變量 test3 在7個頁面中都有效(包括login.jsp和news.jsp);
- 變量 test4 在整個網站,當前也就是7個頁面中都有效(包括login.jsp和news.jsp)。
