1. 程式人生 > >Java中request,session,application的作用域

Java中request,session,application的作用域

幾乎所有的Web開發語言都支援Session功能,Servlet也不例外。 Servlet/JSP中的Session功能是通過作用域(scope)這個概念來實現的。

作用域分為四種,分別為:

page 在當前頁面有效(僅用於JSP中)
request 在當前請求中有效
session 在當前會話中有效
application在所有應用程式中有效

是不是看不太明白?page因為僅用於JSP中,這裡只講述其他三種作用域。首先要宣告的一點,所謂“作用域”就是“資訊共享的範圍”,也就是說一個資訊能夠在多大的範圍內有效。

話說武松一日來到景陽崗,見一旗幟迎風飄揚,旗子上書五個大字“三碗不過崗”。武松叫道:“店家,拿三碗酒來,再切兩斤熟牛肉!”店小二應聲道:“三碗好酒,二斤熟牛肉囉~~”裡面廚師趕忙噹噹噹當切好牛肉,店小二倒上三碗酒,店小二端上前來。

武 鬆咕咚咕咚連幹三碗,叫一聲“好酒!店家,再來三碗!”小二忙又倒上三碗好酒,武松一飲而盡。就這樣前前後後武松一共喝了十八大腕。付了帳剛要走,店小二 道: “客官,這前面山上有大蟲,客官剛剛喝完十八碗酒恐怕過不得崗,不如在小店暫住一夜,待明天和獵戶一同過崗豈不是好?”

之後武松說什麼就留待各位看官自己去回憶啦。在這段武松打虎中,大家有沒有看到些熟悉的東西?

武松: 瀏覽器。
酒館: 伺服器。
店小二、廚師: Servlet或者JSP。
來三碗好酒!: 瀏覽器向伺服器發出HTTP請求。
店小二上酒: 伺服器的響應。
武松從進店到離開: 一個HTTP對話。
我 們可以看到,Web互動的最基本單位為HTTP請求(武松點菜)。每個使用者從進入網站到離開網站這段過程稱為一個HTTP會話 (武松進店到出店),一個伺服器的執行過程中會有多個使用者訪問,就是多個HTTP會話(酒館當然不可能只接待武松一個客人)。那麼作用域就可以理解為:

request HTTP請求開始到結束這段時間
session HTTP會話開始到結束這段時間
application 伺服器啟動到停止這段時間

request

一個HTTP請求的處理可能需要多個Servlet合作(武松點菜時店小二就要吩咐廚房做菜),幾個Servlet之間可以通過某種方式傳遞資訊(店小二就用吆喝的方式通知廚房),但這個資訊在請求結束後就無效了(廚房在做完菜之後就不用再管這道菜的事兒了)。

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

void setAttribute(String name, Object value)
將物件 value 以 name 為名稱儲存到request作用域中。
Object getAttribute(String name)
從request作用域中取得指定名字的資訊。
doGet()、doPost()函式的第一個引數就是 HttpServletRequest 物件,使用這個物件的 setAttribute 即可傳遞資訊。

那麼設定好資訊之後,如何將資訊傳給其他Servlet?這就要用到 RequestDispatcher 介面的 forward 方法,將請求轉發給其他Servlet。

RequestDispatcher ServletContext.getRequestDispatcher(String path)
取得Dispatcher以便轉發。path為轉發的目的Servlet。
void RequestDispatcher.forward(ServletRequest request, ServletResponseresponse)
將request和response轉發。
因此,只要在當前Servlet中先 setAttribute,然後forward,最後在forward到的Servlet中 getAttribute即可實現資訊傳遞。

PHP 的程式設計師可能不太好理解這一段,因為PHP中沒有轉發的概念,一個請求只能由一個PHP檔案來處理,所以PHP中根本沒有request作用域的概念。而 Servlet則不同,請求可以在應用程式中任意轉發,所以用request作用域在不同Servlet之間傳遞資訊。需要注意兩點:

轉發不是重定向,轉發是在Web應用內部進行的。PHP支援重定向但沒有轉發。
轉發對瀏覽器是透明的,也就是說,無論在伺服器上如何轉發,瀏覽器位址列中顯示的仍然是最初那個Servlet的地址。
session

session作用域比較容易理解,同一瀏覽器訪問多次,在這多次訪問之間傳遞資訊,就是session作用域。 ('''武松每次點菜帳房先生都要記一筆賬,等武松走之前結帳用。這筆帳在武松吃飯過程中始終有效,即位於session作用域中''')

session是通過HttpSession介面實現的。

Object HttpSession.getAttribute(String name)
從session中獲取資訊
void HttpSession.setAttribute(String name, Object value)
向session中儲存資訊
而通過HttpServletRequest.getSession()方法可以獲得HttpSession物件。

HttpSession HttpServletRequest.getSessio()
獲取當前請求所在的session的物件。
session 的開始容易判斷(瀏覽器發出第一個HTTP請求即可認為會話開始),但結束就不好判斷了(因為瀏覽器關閉時不會通知伺服器“我關了,會話可以結束了”), 所以只能通過這種方法判斷:如果一定的時間內客戶端沒有反應,則認為會話結束。 Tomcat的預設值為120分鐘,但這個值也可以通過 HttpSession 的 setMaxInactiveInterval 方法來設定。

void setMaxInactiveInterval(int interval)
設定繪畫的超時值。
如果想主動讓會話結束,如使用者單擊“登出”的時候,可以使用 HttpSession 的 invalidate 方法:

vooid invalidate()
強制結束當前session。
application

application作用域就是伺服器啟動到關閉的整段時間,在這個作用域內設定的資訊可以被所有應用程式使用。 (餐館打烊後結帳,用到的即是開張到打烊之間的所有資訊。)

還記得上一節提到的ServetContext嗎? application作用域上的資訊傳遞就是通過ServetContext實現的。

Object getAttribute(String name)
從application中獲取資訊。
void setAttribute(String name, Object value)
向application作用域中設定資訊。
總結

可以看到,每個作用域除了實現介面不同、意義不同之外,它們的使用方法和作用都是相同的,都是通過 getAttribute 和 setAttribute 方法進行資訊傳遞。

作用域 意義 實現介面
request HTTP請求內 HttpServletRequest
session HTTP會話內 HttpSession
application 伺服器生命週期內 ServletContext