在這篇博文中,我們將討論和學習JSP中的隱式對象及四個作用域。
一、九大隱式對象
這些對象是JSP容器為每個頁面中的開發人員提供的Java對象,開發人員可以直接調用它們而不用顯式地聲明它們再調用。 JSP隱式對象也稱為預定義變量。
下表列出了JSP支持的九個隱式對象 -

1. request對象
request對象是javax.servlet.http.HttpServletRequest對象的一個實例。每當客戶端請求頁面時,JSP引擎將創建一個新對象來表示該請求。
request對象提供了獲取包括表單數據,Cookie,HTTP方法等HTTP頭信息的方法。
2. response對象
response對象是javax.servlet.http.HttpServletResponse對象的一個實例。就像服務器創建request對象一樣,它還創建一個對象來表示對客戶端的響應。
response對象還定義了處理創建新HTTP頭的接口。通過此對象,JSP程序員可以添加新的Cookie或日期戳,HTTP狀態代碼等。
3. out對象
out隱式對象是javax.servlet.jsp.JspWriter對象的一個實例,用於在響應中發送內容。
初始化JspWriter對象根據頁面是否緩存而不同地實例化。緩沖可以通過使用page指令的buffered ='false'屬性來關閉。
JspWriter對象包含與java.io.PrintWriter類大部分相同的方法。但是,JspWriter還有一些額外的方法用來處理緩沖。與PrintWriter對象不同,JspWriter會拋出IOExceptions異常。
4. session對象
session對象是javax.servlet.http.HttpSession的一個實例,其行為與Java Servlet下的會話對象行為完全相同。session對象用於跟蹤客戶端請求之間的客戶端會話。
5. application對象
application對象是生成的Servlet的ServletContext對象的直接包裝,實際上是javax.servlet.ServletContext對象的一個實例。
application對象是JSP頁面在其整個生命周期中的表示。 當JSP頁面被初始化時,將創建此對象,並且在JSP頁面被jspDestroy()方法刪除時application對象也將被刪除。
通過向application對象添加屬性值,可以確保組成Web應用程序的所有JSP文件都可以訪問它。
6. config對象
config對象是javax.servlet.ServletConfig的實例化,是生成的servlet的ServletConfig對象周圍的直接包裝。
7. pageContext對象
pageContext對象是javax.servlet.jsp.PageContext對象的一個實例。pageContext對象用於表示整個JSP頁面。
8. page對象
page對象是對該頁面實例的實際引用。可以認為它是表示整個JSP頁面的對象。
page對象是this對象的直接同義詞。
9. exception對象
exception對象是一個包含上一頁拋出的異常的包裝器。它通常用於生成對錯誤條件的適當響應。
二、JSP中四個作用域
所謂“作用域”就是“信息共享的范圍”,也就是說一個信息能夠在多大的范圍內有效。JSP中九個內置對象及其相應所屬作用域如下表:
| 編號 | 對象 | 所屬作用域 | 作用域描述 |
| 1 | request | request | 在當前請求中有效 |
| 2 | response | page | 在當前頁面有效 |
| 3 | out | page | 在當前頁面有效 |
| 4 | session | session | 在當前會話中有效 |
| 5 | application | application | 在所有應用程序中有效 |
| 6 | config | page | 在當前頁面有效 |
| 7 | pageContext | page | 在當前頁面有效 |
| 8 | page | page | 在當前頁面有效 |
| 9 | Exception | page | 在當前頁面有效 |
作用域介紹
由上圖可知,這九個內置對象都有相應的作用域,作用域在這里的作用就是限定對象的生命周期。如果跳出了當前對象的作用域,該對象的信息就不能再被訪問。
讓我們通過一個例子在理解上述過程
1、首先寫一個index.jsp頁面調用其中的request、session、application和pageContext這個四個內置對象,並分別給其設置num屬性值為1。代碼如下:
1 <body> 2 <% 3 pageContext.setAttribute("num", 1); 4 session.setAttribute("num", 1); 5 request.setAttribute("num", 1); 6 application.setAttribute("num", 1); 7 //response.sendRedirect("http://localhost:8088/demo1012/first.jsp"); 8 %> 9 <table> 10 <tr> 11 <td>pageContext:</td> 12 <td><%=pageContext.getAttribute("num")%></td> 13 </tr> 14 <tr> 15 <td>session:</td> 16 <td><%=session.getAttribute("num")%></td> 17 </tr> 18 <tr> 19 <td>request:</td> 20 <td><%=request.getAttribute("num")%></td> 21 </tr> 22 <tr> 23 <td>application:</td> 24 <td><%=application.getAttribute("num")%></td> 25 </tr> 26 </table> 27 </body>
在瀏覽器請求index.jsp頁面顯示結果如下:

由結果可知,在index.jsp頁面中我們可以訪問四個對象的num屬性值。
2、我們用<jsp:forward page="first.jsp"></jsp:forward>替換上面第7行代碼,重新請求index.jsp頁面。運行結果如下:

可以看到無法獲得之前的那個pageContext對象的num屬性值,這主要是因為轉發請求到了first頁面,跳出了之前的pageContext對象的作用域,現在調用的pageContext對象是first.jsp頁面重建的一個。所以其num屬性值為null。
3、我們取消上述代碼中第7行的注釋,其中first.jsp頁面代碼就是上述代碼的table部分,我們再重新請求index.jsp頁面。運行結果如下:

可以看到無法獲得之前的那個pageContext和request的num屬性的值了,pageContext的原因如上,而因為我們對頁面重定向到了first.jsp,開始重瀏覽器到index.jsp的request連接結束了,所以現在獲得的request是在index.jsp到first.jsp頁面建立的新request請求域下生成的request對象,所以其num屬性未初始化為null。
4、我們再重新使用其他瀏覽器訪問first.jsp頁面,顯示的結果如下:

我們知道當前會話,是指從用戶打開瀏覽器開始,到用戶關閉瀏覽器這中間的過程。因為這次我們使用另外的瀏覽器對服務器發起請求,所以服務器為這次用戶請求建立了新的會話,所以其num的屬性值為null。另外因為只有index.jsp頁面對四個內置對象的num屬性進行了初始化,所以first.jsp頁面只有application對象還在其application作用域內。其值為index.jsp頁面設置的1,其他兩個屬性都為null.
5、最后對於application作用域中的對象application,它的有效范圍是整個應用。整個應用是指從應用啟動,到應用結束。這里並不是說“從服務器啟動,到服務器關閉”,是因為一個服務器可能部署多個應用,當然你關閉了服務器,就會把上面所有的應用都關閉了。application作用域里的變量,它們的存活時間是最長的,如果不進行手工刪除,它們就一直可以使用。與上述三個不同的是,application里的變量可以被所有用戶共用。如果用戶甲的操作修改了application中的變量,用戶乙訪問時得到的是修改后的值。這在其他scope中都是不會發生的,page、 request和session都是完全隔離的,無論如何修改都不會影響其他人的數據。
總結
1、最后你一定就可以理解下面說法了

參考資料:
1、對於JSP九大內置對象和四個作用域的理解:http://www.blogjava.net/ourday/archive/2008/09/20/230107.html
2、JSP九大內置對象:http://www.yiibai.com/jsp/jsp_implicit_objects.html
