什么是JSP內(nèi)置對(duì)象
JSP引擎在調(diào)用JSP對(duì)應(yīng)的jspServlet時(shí),會(huì)傳遞或創(chuàng)建9個(gè)與web開(kāi)發(fā)相關(guān)的對(duì)象供jspServlet使用。JSP技術(shù)的設(shè)計(jì)者為便于開(kāi)發(fā)人員在編寫(xiě)JSP頁(yè)面時(shí)獲得這些web對(duì)象的引用,特意定義了9個(gè)相應(yīng)的變量,開(kāi)發(fā)人員在JSP頁(yè)面中通過(guò)這些變量就可以快速獲得這9大對(duì)象的引用
細(xì)心的朋友會(huì)發(fā)現(xiàn),我們沒(méi)有在JSP頁(yè)面上定義過(guò)out對(duì)象,卻可以直接使用!其實(shí)out對(duì)象就是JSP內(nèi)置對(duì)象之一。
九個(gè)內(nèi)置對(duì)象:
- pageContext
- page
- config
- request
- response
- session
- application
- exception
- out
out對(duì)象
out對(duì)象的API
int getBufferSize()【得到緩存大小】
int getRemaining()【得到未使用緩存的大小】
boolean isAutoFlush()
void println()
void flush()
void close()
void clearBuffer()
void clear()
out對(duì)象用于向?yàn)g覽器輸出數(shù)據(jù),與之對(duì)應(yīng)的是Servlet的PrintWriter對(duì)象。然而這個(gè)out對(duì)象的類型并不是PrintWriter,是JspWriter

我們可以簡(jiǎn)單理解為:JspWriter就是帶緩存的PrintWrieter。
out對(duì)象的原理如下:

- 只有向out對(duì)象中寫(xiě)入了內(nèi)容,且滿足如下任何一個(gè)條件時(shí),out對(duì)象才去調(diào)用ServletResponse.getWriter方法,并通過(guò)該方法返回的PrintWriter對(duì)象將out對(duì)象的緩沖區(qū)中的內(nèi)容真正寫(xiě)入到Servlet引擎提供的緩沖區(qū)中:
- 設(shè)置page指令的buffer屬性關(guān)閉了out對(duì)象的緩存功能
- out對(duì)象的緩沖區(qū)已滿
- 整個(gè)JSP頁(yè)面結(jié)束
- 一般我們?cè)贘SP頁(yè)面輸出都是用表達(dá)式(<%=%>),所以out對(duì)象用得并不是很多!
request
- 內(nèi)置對(duì)象request其實(shí)就是HttpServletRequest,在Servlet講解的時(shí)候已經(jīng)詳細(xì)說(shuō)明了,沒(méi)什么好說(shuō)的

response
- 內(nèi)置對(duì)象response其實(shí)就是HttpServletResponse,在Servlet講解的時(shí)候已經(jīng)詳細(xì)說(shuō)明了,沒(méi)什么好說(shuō)的

config
- 內(nèi)置對(duì)象config其實(shí)就是ServletConfig,在Servlet講解的時(shí)候已經(jīng)詳細(xì)說(shuō)明了,沒(méi)什么好說(shuō)的

session
- 內(nèi)置對(duì)象session其實(shí)就是HttpSession。,在Servlet講解的時(shí)候已經(jīng)詳細(xì)說(shuō)明了,沒(méi)什么好說(shuō)的

注意:在page指令配置如下信息,session將不可使用
<%@page session="false" %>
application
- 內(nèi)置對(duì)象application其實(shí)就是ServletContext對(duì)象,在Servlet講解的時(shí)候已經(jīng)詳細(xì)說(shuō)明了,沒(méi)什么好說(shuō)的

page
- 內(nèi)置對(duì)象page是HttpJasPage對(duì)象,其實(shí)page對(duì)象代表的就是當(dāng)前JSP頁(yè)面,是當(dāng)前JSP編譯后的Servlet類的對(duì)象。也就是說(shuō):page對(duì)象相當(dāng)于普通java類的this
exception
內(nèi)置對(duì)象exception是java.lang.Exception類的對(duì)象,exception封裝了JSP頁(yè)面拋出的異常信息。exception經(jīng)常被用來(lái)處理錯(cuò)誤頁(yè)面
前面我們已經(jīng)講過(guò)了怎么設(shè)置錯(cuò)誤頁(yè)面了,下面我們就來(lái)簡(jiǎn)單使用一下exception對(duì)象吧
-
1.jsp頁(yè)面
<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="error.jsp" %> <%--模擬空指針異常的錯(cuò)誤--%><% String sss = null; sss.length();%>
* error.jsp頁(yè)面
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
<html>
<head>
<title>錯(cuò)誤頁(yè)面</title>
</head>
<body>
<%
out.println("程序拋出了異常:" + exception);
%>
</body>
</html>
* 效果:

# pageContext
**pageContext是內(nèi)置對(duì)象中最重要的一個(gè)對(duì)象,它代表著JSP頁(yè)面編譯后的內(nèi)容(也就是JSP頁(yè)面的運(yùn)行環(huán)境)!**
## pageContext獲取8個(gè)內(nèi)置對(duì)象
* 既然它代表了JSP頁(yè)面編譯后的內(nèi)容,理所當(dāng)然的:**它封裝了對(duì)其他8大內(nèi)置對(duì)象的引用!**,也就是說(shuō),**通過(guò)pageContext可以獲取到其他的8個(gè)內(nèi)置對(duì)象!**
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>獲取八大內(nèi)置對(duì)象</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>
* 看下效果:
[圖片上傳中...(image-c4d657-1517835716808-5)]
## pageContext作為域?qū)ο?
* 類似于request,session,ServletContext作為域?qū)ο蠖?*都有以下三個(gè)方法**:
* **setAttribute(String name,Objcet o)**
* **getAttribute(String name)**
* **removeAttribute(String name)**
* 當(dāng)然了,pageContext也不例外,**pageContext也有這三個(gè)方法**!
* pageContext本質(zhì)上代表的是當(dāng)前JSP頁(yè)面編譯后的內(nèi)容,**作為域?qū)ο蠖?,它就代表著?dāng)前JSP頁(yè)面(也就是page)**!也就是說(shuō):**pageContext域?qū)ο笾辉趐age范圍內(nèi)有效,超出了page范圍就無(wú)效了**!
* 首先來(lái)看看在**page范圍內(nèi)能不能使用**
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>使用page域?qū)ο?lt;/title>
</head>
<body>
<%
pageContext.setAttribute("name", "zhongfucheng");
%>
<%
String value = (String) pageContext.getAttribute("name");
System.out.println(value);
%>
</body>
</html>
* 效果如下:
[圖片上傳中...(image-3aff51-1517835716808-4)]
* 我們現(xiàn)在來(lái)試驗(yàn)一下**是不是超出了page范圍就無(wú)效了!**
* **在2.jsp中request域?qū)ο笤O(shè)置屬性**
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>request域?qū)ο笤O(shè)置屬性</title>
</head>
<body>
<%
//這是request域?qū)ο蟊4娴膬?nèi)容
request.setAttribute("name","zhongfucheng");
%>
<%--跳轉(zhuǎn)到1.jsp中--%>
<jsp:forward page="1.jsp"/>
</body>
</html>
* **企圖在1.jsp中pageContext取出request存進(jìn)去的屬性**
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>在page域?qū)ο螳@取屬性</title>
</head>
<body>
<%
//企圖獲取request域?qū)ο蟠孢M(jìn)的屬性
String value = (String) pageContext.getAttribute("name");
System.out.println(value);
%>
</body>
</html>
* 效果如下:

* * *
* pageContext本質(zhì)上代表著編譯后JSP的內(nèi)容,**pageContext還可以封裝了訪問(wèn)其他域的方法**!
* 上面的**pageContext默認(rèn)是page范圍的**,**但pageContext對(duì)象重載了set、get、removeAttribute這三個(gè)方法**
* **getAttribute(String name,int scope)**
* **setAttribute(String name,Object value,int scope)**
* **removeAttribute(String name,int scope)**
* **多了一個(gè)設(shè)置域范圍的一個(gè)參數(shù),如果不指定默認(rèn)就是page**。當(dāng)然了,**pageContext把request、session、application、page這幾個(gè)域?qū)ο蠓庋b著了靜態(tài)變量供我們使用**。
* **PageContext.APPLICATION_SCOPE**
* **PageContext.SESSION_SCOPE**
* **PageContext.REQUEST_SCOPE**
* **PageContext.PAGE_SCOPE**
* 剛才我們沒(méi)有使用重載方法的時(shí)候,使用pageContext是無(wú)法獲取到request域?qū)ο笤O(shè)置的屬性的。**現(xiàn)在我們使用重載后的方法看一下能不能獲取得到**!
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>在page域?qū)ο螳@取request域?qū)ο蟮膶傩?lt;/title>
</head>
<body>
<%
//使用重載的方法獲取request域?qū)ο蟮膶傩? String value = (String) pageContext.getAttribute("name",pageContext.REQUEST_SCOPE);
System.out.println(value);
%>
</body>
</html>
* 效果:

* * *
* pageContexst還有這么一個(gè)方法:
* **findAttribute(String name)**
* **該方法會(huì)查找各個(gè)域的屬性,從小到大開(kāi)始尋找!也就是page—>request->session->application。**這個(gè)是EL表達(dá)式的原理!,EL表達(dá)式后面會(huì)講到!
* 我們用此方法看能不能查找出request域?qū)ο蟮膶傩园桑?
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>使用findAttribute</title>
</head>
<body>
<%
//使用findAttribute查找2.jsp中request域?qū)ο蟮膶傩? String value = (String) pageContext.findAttribute("name");
System.out.println(value);
%>
</body>
</html>
* 效果如下:

* * *
## 引入和跳轉(zhuǎn)
PageContext類中定義了一個(gè)**forward方法和兩個(gè)include方法來(lái)分別簡(jiǎn)化和替代RequestDispatcher.forward方法和include方法**。
* **pageContext.forward(String url)**
* **pageContext.include(String url)**
[圖片上傳中...(image-ef6a2c-1517835716807-0)]
* * *
# 4種屬性范圍
到目前為止,我們已經(jīng)學(xué)了4種屬性范圍了。
1. **page【只在一個(gè)頁(yè)面中保存屬性,跳轉(zhuǎn)頁(yè)面無(wú)效】**
2. **requet【只在一次請(qǐng)求中保存屬性,服務(wù)器跳轉(zhuǎn)有效,瀏覽器跳轉(zhuǎn)無(wú)效】**
3. **session【在一個(gè)會(huì)話范圍中保存屬性,無(wú)論何種跳轉(zhuǎn)均有效,關(guān)閉瀏覽器后無(wú)效】**
4. **application【在整個(gè)服務(wù)器中保存,所有用戶都可以使用】**
* * *
* 4個(gè)內(nèi)置對(duì)象都支持以下的方法:
1. **setAttribute(String name, Object o )**
2. **getAttribute(String name)**
3. **removeAttribute(String name)**
## 應(yīng)用場(chǎng)景
1. request:如果客戶向服務(wù)器發(fā)請(qǐng)求,產(chǎn)生的數(shù)據(jù),**用戶看完就沒(méi)用了,**像這樣的數(shù)據(jù)就存在request域,像新聞數(shù)據(jù),屬于用戶看完就沒(méi)用的
2. session:如果客戶向服務(wù)器發(fā)請(qǐng)求,產(chǎn)生的數(shù)據(jù),**用戶用完了等一會(huì)兒還有用**,像這樣的數(shù)據(jù)就存在session域中,像購(gòu)物數(shù)據(jù),用戶需要看到自己購(gòu)物信息,并且等一會(huì)兒,還要用這個(gè)購(gòu)物數(shù)據(jù)結(jié)帳
3. servletContext:如果客戶向服務(wù)器發(fā)請(qǐng)求,產(chǎn)生的數(shù)據(jù),**用戶用完了,還要給其它用戶用**,像這樣的數(shù)據(jù)就存在servletContext域中,像聊天數(shù)據(jù)
> 如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章的同學(xué),可以關(guān)注微信公眾號(hào):Java3y