什麼是JSP內置對象 JSP引擎在調用JSP對應的jspServlet時, 會傳遞或創建9個與web開發相關的對象供jspServlet使用 。JSP技術的設計者為便於開發人員在編寫JSP頁面時獲得這些web對象的引用,特意定義了9個相應的變數, 開發人員在JSP頁面中通過這些變數就可以快速獲得這9 ...
什麼是JSP內置對象
JSP引擎在調用JSP對應的jspServlet時,會傳遞或創建9個與web開發相關的對象供jspServlet使用。JSP技術的設計者為便於開發人員在編寫JSP頁面時獲得這些web對象的引用,特意定義了9個相應的變數,開發人員在JSP頁面中通過這些變數就可以快速獲得這9大對象的引用
細心的朋友會發現,我們沒有在JSP頁面上定義過out對象,卻可以直接使用!其實out對象就是JSP內置對象之一。
九個內置對象:
- pageContext
- page
- config
- request
- response
- session
- application
- exception
- out
out對象
out對象的API
- int getBufferSize()【得到緩存大小】
- int getRemaining()【得到未使用緩存的大小】
- boolean isAutoFlush()
- void println()
- void flush()
- void close()
- void clearBuffer()
void clear()
out對象用於向瀏覽器輸出數據,與之對應的是Servlet的PrintWriter對象。然而這個out對象的類型並不是PrintWriter,是JspWriter
我們可以簡單理解為:JspWriter就是帶緩存的PrintWrieter。
out對象的原理如下:
- 只有向out對象中寫入了內容,且滿足如下任何一個條件時,out對象才去調用ServletResponse.getWriter方法,並通過該方法返回的PrintWriter對象將out對象的緩衝區中的內容真正寫入到Servlet引擎提供的緩衝區中:
- 設置page指令的buffer屬性關閉了out對象的緩存功能
- out對象的緩衝區已滿
- 整個JSP頁面結束
- 一般我們在JSP頁面輸出都是用表達式(<%=%>),所以out對象用得並不是很多!
request
- 內置對象request其實就是HttpServletRequest,在Servlet講解的時候已經詳細說明瞭,沒什麼好說的
response
- 內置對象response其實就是HttpServletResponse,在Servlet講解的時候已經詳細說明瞭,沒什麼好說的
config
- 內置對象config其實就是ServletConfig,在Servlet講解的時候已經詳細說明瞭,沒什麼好說的
session
- 內置對象session其實就是HttpSession。,在Servlet講解的時候已經詳細說明瞭,沒什麼好說的
註意:在page指令配置如下信息,session將不可使用
<%@page session="false" %>
application
- 內置對象application其實就是ServletContext對象,在Servlet講解的時候已經詳細說明瞭,沒什麼好說的
page
- 內置對象page是HttpJasPage對象,其實page對象代表的就是當前JSP頁面,是當前JSP編譯後的Servlet類的對象。也就是說:page對象相當於普通java類的this
exception
內置對象exception是java.lang.Exception類的對象,exception封裝了JSP頁面拋出的異常信息。exception經常被用來處理錯誤頁面
前面我們已經講過了怎麼設置錯誤頁面了,下麵我們就來簡單使用一下exception對象吧
1.jsp頁面
```JSP<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="error.jsp" %>
<%--模擬空指針異常的錯誤--%><% String sss = null; sss.length();%>
```
- error.jsp頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
<html>
<head>
<title>錯誤頁面</title>
</head>
<body>
<%
out.println("程式拋出了異常:" + exception);
%>
</body>
</html>
- 效果:
pageContext
pageContext是內置對象中最重要的一個對象,它代表著JSP頁面編譯後的內容(也就是JSP頁面的運行環境)!
pageContext獲取8個內置對象
- 既然它代表了JSP頁面編譯後的內容,理所當然的:它封裝了對其他8大內置對象的引用!,也就是說,通過pageContext可以獲取到其他的8個內置對象!
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>獲取八大內置對象</title>
</head>
<body>
<%
System.out.println(pageContext.getSession());
System.out.println(pageContext.getRequest());
System.out.println(pageContext.getResponse());
System.out.println(pageContext.getException());
System.out.println(pageContext.getPage());
System.out.println(pageContext.getServletConfig());
System.out.println(pageContext.getServletContext());
System.out.println(pageContext.getOut());
%>
</body>
</html>
- 看下效果:
pageContext作為域對象
- 類似於request,session,ServletContext作為域對象而言都有以下三個方法:
- setAttribute(String name,Objcet o)
- getAttribute(String name)
- removeAttribute(String name)
當然了,pageContext也不例外,pageContext也有這三個方法!
pageContext本質上代表的是當前JSP頁面編譯後的內容,作為域對象而言,它就代表著當前JSP頁面(也就是page)!也就是說:pageContext域對象只在page範圍內有效,超出了page範圍就無效了!
首先來看看在page範圍內能不能使用
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>使用page域對象</title>
</head>
<body>
<%
pageContext.setAttribute("name", "zhongfucheng");
%>
<%
String value = (String) pageContext.getAttribute("name");
System.out.println(value);
%>
</body>
</html>
- 效果如下:
我們現在來試驗一下是不是超出了page範圍就無效了!
在2.jsp中request域對象設置屬性
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>request域對象設置屬性</title>
</head>
<body>
<%
//這是request域對象保存的內容
request.setAttribute("name","zhongfucheng");
%>
<%--跳轉到1.jsp中--%>
<jsp:forward page="1.jsp"/>
</body>
</html>
- 企圖在1.jsp中pageContext取出request存進去的屬性
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>在page域對象獲取屬性</title>
</head>
<body>
<%
//企圖獲取request域對象存進的屬性
String value = (String) pageContext.getAttribute("name");
System.out.println(value);
%>
</body>
</html>
- 效果如下:
pageContext本質上代表著編譯後JSP的內容,pageContext還可以封裝了訪問其他域的方法!
- 上面的pageContext預設是page範圍的,但pageContext對象重載了set、get、removeAttribute這三個方法
- getAttribute(String name,int scope)
- setAttribute(String name,Object value,int scope)
- removeAttribute(String name,int scope)
- 多了一個設置域範圍的一個參數,如果不指定預設就是page。當然了,pageContext把request、session、application、page這幾個域對象封裝著了靜態變數供我們使用。
- PageContext.APPLICATION_SCOPE
- PageContext.SESSION_SCOPE
- PageContext.REQUEST_SCOPE
- PageContext.PAGE_SCOPE
剛纔我們沒有使用重載方法的時候,使用pageContext是無法獲取到request域對象設置的屬性的。現在我們使用重載後的方法看一下能不能獲取得到!
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>在page域對象獲取request域對象的屬性</title>
</head>
<body>
<%
//使用重載的方法獲取request域對象的屬性
String value = (String) pageContext.getAttribute("name",pageContext.REQUEST_SCOPE);
System.out.println(value);
%>
</body>
</html>
- 效果:
- pageContexst還有這麼一個方法:
- findAttribute(String name)
該方法會查找各個域的屬性,從小到大開始尋找!也就是page—>request->session->application。這個是EL表達式的原理!,EL表達式後面會講到!
我們用此方法看能不能查找出request域對象的屬性吧!
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>使用findAttribute</title>
</head>
<body>
<%
//使用findAttribute查找2.jsp中request域對象的屬性
String value = (String) pageContext.findAttribute("name");
System.out.println(value);
%>
</body>
</html>
- 效果如下:
引入和跳轉
PageContext類中定義了一個forward方法和兩個include方法來分別簡化和替代RequestDispatcher.forward方法和include方法。
- pageContext.forward(String url)
- pageContext.include(String url)
4種屬性範圍
到目前為止,我們已經學了4種屬性範圍了。
- page【只在一個頁面中保存屬性,跳轉頁面無效】
- requet【只在一次請求中保存屬性,伺服器跳轉有效,瀏覽器跳轉無效】
- session【在一個會話範圍中保存屬性,無論何種跳轉均有效,關閉瀏覽器後無效】
- application【在整個伺服器中保存,所有用戶都可以使用】
- 4個內置對象都支持以下的方法:
- setAttribute(String name, Object o )
- getAttribute(String name)
- removeAttribute(String name)
應用場景
- request:如果客戶向伺服器發請求,產生的數據,用戶看完就沒用了,像這樣的數據就存在request域,像新聞數據,屬於用戶看完就沒用的
- session:如果客戶向伺服器發請求,產生的數據,用戶用完了等一會兒還有用,像這樣的數據就存在session域中,像購物數據,用戶需要看到自己購物信息,並且等一會兒,還要用這個購物數據結帳
- servletContext:如果客戶向伺服器發請求,產生的數據,用戶用完了,還要給其它用戶用,像這樣的數據就存在servletContext域中,像聊天數據
如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章的同學,可以關註微信公眾號:Java3y