幾乎所有的Web開發語言都支持Session功能,Servlet也不例外。 Servlet/JSP中的Session功能是通過作用域(scope)這個概念來實現的。
作用域分爲四種,分別爲:
page |
在當前頁面有效(僅用於JSP中) |
request |
在當前請求中有效 |
session |
在當前會話中有效 |
application |
在所有應用程序中有效 |
是不是看不太明白?page因爲僅用於JSP中,這裏只講述其他三種作用域。首先要聲明的一點,所謂“作用域”就是“信息共享的範圍”, 也就是說一個信息能夠在多大的範圍內有效。
話說武松一日來到景陽崗,見一旗幟迎風飄揚,旗子上書五個大字“三碗不過崗”。武松叫道:“店家,拿三碗酒來,再切兩斤熟牛肉!”店小二應聲道:“三碗好酒, 二斤熟牛肉囉~~”裏面廚師趕忙噹噹噹當切好牛肉,店小二倒上三碗酒,店小二端上前來。
武松咕咚咕咚連幹三碗,叫一聲“好酒!店家,再來三碗!”小二忙又倒上三碗好酒,武松一飲而盡。就這樣前前後後武松一共喝了十八大腕。付了帳剛要走,店小二道: “客官,這前面山上有大蟲,客官剛剛喝完十八碗酒恐怕過不得崗,不如在小店暫住一夜,待明天和獵戶一同過崗豈不是好?”
之後武松說什麼就留待各位看官自己去回憶啦。在這段武松打虎中,大家有沒有看到些熟悉的東西?
•武松:瀏覽器。
•酒館: 服務器。
•店小二、廚師: Servlet或者JSP。
•來三碗好酒!:瀏覽器向服務器發出HTTP請求。
•店小二上酒:服務器的響應。
•武松從進店到離開: 一個HTTP會話(即 Session)。
我們可以看到,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。
RequestDispatcherServletContext.getRequestDispatcher(String path)
取得Dispatcher以便轉發。path爲轉發的目的Servlet。
voidRequestDispatcher.forward(ServletRequest request, ServletResponse response)
將request和response轉發。
因此,只要在當前Servlet中先 setAttribute,然後forward,最後在forward到的Servlet中 getAttribute即可實現信息傳遞。
PHP的程序員可能不太好理解這一段,因爲PHP中沒有轉發的概念, 一個請求只能由一個PHP文件來處理,所以PHP中根本沒有request作用域的概念。 而Servlet則不同,請求可以在應用程序中任意轉發,所以用request作用域在不同Servlet之間傳遞信息。 需要注意兩點:
1.轉發不是重定向,轉發是在Web應用內部進行的。PHP支持重定向但沒有轉發。
2.轉發對瀏覽器是透明的,也就是說,無論在服務器上如何轉發,瀏覽器地址欄中顯示的仍然是最初那個Servlet的地址。
session
session作用域比較容易理解,同一瀏覽器訪問多次,在這多次訪問之間傳遞信息,就是session作用域。 (武松每次點菜,帳房先生都要記一筆賬,等武松走之前結帳用。這筆帳在武松吃飯過程中始終有效,即位於session作用域中)
session是通過HttpSession接口實現的。
ObjectHttpSession.getAttribute(String name)
從session中獲取信息
voidHttpSession.setAttribute(String name, Object value)
向session中保存信息
而通過HttpServletRequest.getSession()方法可以獲得HttpSession對象。
HttpSessionHttpServletRequest.getSession()
獲取當前請求所在的session的對象。
session的開始容易判斷(瀏覽器發出第一個HTTP請求即可認爲會話開始),但結束就不好判斷了(因爲瀏覽器關閉時不會通知服務器“我關了,會話可以結束了”), 所以只能通過這種方法判斷:如果一定的時間內客戶端沒有反應,則認爲會話結束。 Tomcat的默認值爲120分鐘,但這個值也可以通過 HttpSession 的setMaxInactiveInterval() 方法來設置。
void setMaxInactiveInterval(intinterval)
設置會話的超時值。
如果想主動讓會話結束,如用戶單擊“註銷”的時候,可以使用HttpSession 的 invalidate() 方法:
void 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 |
示例程序
示例程序
這一節的示例程序是一個用戶登錄的模擬程序。文件較多。
•login.html 登錄表單
•DoLogin.java 處理登錄動作的Servlet
•LoginSuccess.java 用於顯示登錄成功信息的Servlet
•SessionTest.java 登錄後的處理程序
•DoLogout.java 註銷的處理程序
爲了演示 request、application、session 各個作用域的使用方法, Servlet之間進行了數據傳遞,數據傳遞方式如下:
數據產生 |
數據接受 |
數據內容 |
作用域 |
DoLogin |
LoginSuccess |
登錄時間 |
request |
DoLogin |
SessionTest |
登錄用戶名 |
session |
DoLogin |
SessionTest |
系統登錄次數 |
application |
訪問 http://localhost:8080/LearnJSP/sessiontest, 登錄時輸入用戶名 charlee 和密碼 123456 即可。
來自 <http://www.jb51.net/article/35875.htm>