一. 引入
1. JSP運行原理
(1) 每個JSP 頁面在第一次被訪問時,WEB容器都會把請求交給JSP引擎(即一個Java程序)去處理。JSP引擎先
將JSP翻譯成一個_jspServlet(實質上也是一個servlet) ,然後按照Servlet的調用方式進行調用。
(2) 由於JSP第一次訪問時會翻譯成Servlet,所以第一次訪問通常會比較慢,但第二次訪問,JSP引擎如果發現JSP
沒有變化,就不再翻譯,而是直接調用,所以程序的執行效率不會受到影響。
(3) JSP引擎在調用JSP對應的_jspService時,會傳遞或創建9個與web開發相關的對象供_jspService使用。JSP技
術的設計者爲便於開發人員在編寫JSP頁面時獲得這些web對象的引用,特意定義了9個相應的變量,開發人員在
JSP頁面中通過這些變量就可以快速獲得這9大對象的引用。
2. 什麼是內置對象?
在JSP開發中,會頻繁使用到一些對象。例如HttpSession,ServletContext,HttpServletRequet,這些對象都
是Servlet中的對象。如果我們每次要使用這些對象的時候都去創建這些對象就顯得非常麻煩。所以Sun公司設計
JSP時,在JSP頁面加載完畢之後就會自動幫開發者創建好這些對象,而開發者只需要直接使用這些對象調用方法
即可!這些創建好的對象就叫內置對象!
3. 內置對象的原理
(1) 在執行JSP的翻譯的時候,它會自動的幫我們翻譯成創建對象的代碼
(2) 舉例:
①Servlet: HttpSession session = request.getSession(true); (需要開發者做)
②JSP:
tomcat服務器:HttpSession session = request.getSession(true);(不需要開發者做)
開發者做的直接用:session.getId();
4. 九大內置對象
二. out隱式對象
1. 簡介
(1) out隱式對象用於向客戶端發送文本數據。
(2) out對象是通過調用pageContext對象的getOut方法返回的,其作用和用法與ServletResponse.getWriter方
法返回的PrintWriter對象非常相似。
2. 細節
(1) out對象對應的類型是JspWriter類,相當於帶緩衝的PrintWriter。
① PrintWriter類中的:
wrier(內容): 直接向瀏覽器寫出內容。
② JspWriter類中的:
writer(內容): 向JSP緩衝區寫出內容。
(2) JSP頁面中的out隱式對象的類型爲JspWriter,JspWriter相當於一種帶緩存功能的PrintWriter,設置JSP頁面
的page指令的buffer屬性可以調整它的緩存大小,甚至關閉它的緩存。
3. JSP頁面的緩衝機制
(1) 在Servlet中輸出內容是不帶緩衝的,當用戶訪問Servlet1時,就會調用PrintWriter的writer方法,把內容輸
出到瀏覽器,直接輸送,沒有任何的中間環節。
(2) JSP中,如果一個用戶訪問了一個JSP頁面,JSP頁面中不建議用PrintWriter寫,而是用JSP提供給我們的
JspWriter中的writer方法,它先把內容寫到緩衝區,緩衝的功能就是爲了提高效率,JspWriter緩衝區把內容輸
出到PrintWriter對象中去,PrintWriter是不帶緩衝區的,再由PrintWriter對象的writer方法輸出到瀏覽器。
(3) 所以理論上,用JSP寫出數據比Servlet效率要高。因爲採用緩衝區後,當緩衝區滿時纔會寫出。緩衝區的大小
默認是8KB。
(4) 只有向out對象中寫入了內容,且滿足如下任何一個條件時,out對象纔去調用ServletResponse.getWriter方
法,並通過該方法返回的PrintWriter對象將out對象的緩衝區中的內容真正寫入到Servlet引擎提供的緩衝區中。
(也就是說只要滿足以下條件之一,緩衝區內容寫出):
①關閉緩衝區,設置page指令的buffer屬性關閉了out對象的緩存功能
②out對象的緩衝區已滿
③刷新緩衝區
④執行完畢JSP頁面,整個JSP頁面結束
4. out隱式對象的工作原理圖
5. 實例
(1) 實例一
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
buffer="1kb"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>out對象</title>
</head>
<body>
<%
out.write("abc");
response.getWriter().write("123");//運行結果是123 abc
%>
</body>
</html>
運行結果如下圖所示:
(2) 實例二
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
buffer="1kb"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>out對象</title>
</head>
<body>
<%
out.write("abc");
//手動刷新緩存
out.flush();
response.getWriter().write("123");//運行結果是abc123
%>
</body>
</html>
運行結果如下圖所示:
(3) 實例三
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
buffer="0kb"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>out對象</title>
</head>
<body>
<%
out.write("abc");//buffer="0kb"就意味着關閉緩存
response.getWriter().write("123");//運行結果是abc123
%>
</body>
</html>
運行結果如下圖所示:
(4) 實例四
<%@ page language="java" import="java.util.*" pageEncoding="utf-8" buffer="1kb"%><%
for(int i=1;i<=1023;i++){
out.write("a");
}
//查看緩存區大小
System.out.println("當前緩存區大小:"+out.getBufferSize());
//查看緩存區剩餘大小
System.out.println("緩存區剩餘大小:"+out.getRemaining());
//刷新緩存
//out.flush();
response.getWriter().write("123");
%>
</body>
</html>
運行結果如下圖所示:
三. pageContext對象
1. 簡介
(1) pageContext對象的類型是PageContext,叫JSP的上下文對象。
(2) pageContext對象是JSP技術中最重要的一個對象,它代表當前JSP頁面的運行環境,這個對象不僅封裝了對
其它8大隱式對象的引用,它自身還是一個域對象,可以用來保存數據。並且,這個對象還封裝了web開發中經
常涉及到的一些常用操作,例如包含和跳轉其它資源、檢索其它域對象中的屬性等。
2. 用途一:通過pageContext可以獲取其他八個內置對象
(1) 僞代碼理解
public class 01_hello_jsp {
public void _jspService(request,response){
創建內置對象
HttpSession session =....;
ServletConfig config = ....;
//SUN公司把8個經常使用的內置對象封裝到PageContext對象中
PageContext pageContext = 封裝;
//調用method1方法
method1(pageContext);
}
public void method1(PageContext pageContext){
//希望在這個方法內部使用內置對象,但是不能在method1中使用,因爲上面的內置對象都是局部變量,所以在下面的方法內部使用局部變量是不可能的。可以從PageContext對象中獲取其他8個內置對象
JspWriter out = pageContext.getOut();
HttpServletRequest rquest = pageContext.getRequest();
........
}
}
(2) 通過pageContext獲得其他對象
(3) 使用場景:在自定義標籤的時候,PageContext對象頻繁使用到!
(4) 實例:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
isErrorPage="true"
session="true"
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>pageContext對象</title>
</head>
<body>
<%
//作用1:pageContext可以獲取其他8個內置對象
response.getWriter().write("是否相等?"+(out==pageContext.getOut()) +"<br/>");
response.getWriter().write("是否相等?"+(session==pageContext.getSession()));
%>
</body>
</html>
運行結果如下圖所示:
3. 用途二:pageContext可以作爲域對象用於共享數據
(1) 常量及方法
(2) 域範圍常量:
① PageContext.PAGE_SCOPE
② PageContext.REQUEST_SCOPE
③ PageContext..SESSION_SCOPE
④ PageContext.APPLICATION_SCOPE(3) 保存數據
① 默認情況下,保存到page域:pageContext.setAttribute("name");
② 可以向四個域對象保存數據:pageContext.setAttribute("name",域範圍常量);
(4) 獲取數據
① 默認情況下,從page域獲取:pageContext.getAttribute("name");
② 可以從四個域中獲取數據:pageContext.getAttribute("name",域範圍常量);
③ 自動在四個域中搜索數據:pageContext.findAttribute("name");
搜索順序:page域 -> request域 -> session域- > context域(application域)。
(5) 實例:
① 實例一:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
isErrorPage="true"
session="true"
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>pageContext對象</title>
</head>
<body>
<%-- pageContext作爲域對象使用, 可以往不同域對象中存取數據 --%>
<%
//第一步:保存數據。默認情況下,保存在page域中
pageContext.setAttribute("message","page's message");
%>
<%
//第二步:獲取數據,page只能在當前頁面獲取。
String message = (String)pageContext.getAttribute("message");
out.write(message);
%>
</body>
</html>
運行結果如下圖所示:
② 實例二:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
isErrorPage="true"
session="true"
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>pageContext對象</title>
</head>
<body>
<%-- pageContext作爲域對象使用,可以往不同域對象中存取數據 --%>
<%
pageContext.setAttribute("message", "page's message");
pageContext.setAttribute("message","request's messsage",PageContext.REQUEST_SCOPE);//保存到request域中
//request.setAttribute("message","request's message"); 等價於上面的代碼
pageContext.setAttribute("message","session's messsage",PageContext.SESSION_SCOPE);//保存到sessio域中
pageContext.setAttribute("message","application's messsage",PageContext.APPLICATION_SCOPE);//保存到context域中
%>
<%-- 從request域中取出數據 --%>
<%=request.getAttribute("message") %><br/>
<%-- 原則: 在哪個域中保存數據,就必須從哪個域取出數據!!! --%>
<%=pageContext.getAttribute("message",PageContext.PAGE_SCOPE) %><br/>
<%=pageContext.getAttribute("message",PageContext.REQUEST_SCOPE) %><br/>
<%=pageContext.getAttribute("message",PageContext.SESSION_SCOPE) %><br/>
<%=pageContext.getAttribute("message",PageContext.APPLICATION_SCOPE) %><br/>
<hr/>
</body>
</html>
運行結果如下圖所示:
③ 實例三:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
isErrorPage="true"
session="true"
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>pageContext對象</title>
</head>
<body>
<%-- pageContext作爲域對象使用,可以往不同域對象中存取數據 --%>
<%
pageContext.setAttribute("message", "page's message");
pageContext.setAttribute("message","request's messsage",PageContext.REQUEST_SCOPE);//保存到request域中
//request.setAttribute("message","request's message"); 等價於上面的代碼
pageContext.setAttribute("message","session's messsage",PageContext.SESSION_SCOPE);//保存到sessio域中
pageContext.setAttribute("message","application's messsage",PageContext.APPLICATION_SCOPE);//保存到context域中
%>
<%-- 更方便的取數據的方法,因爲保存的都是message --%>
<%-- findAttribute(): 在四個域中自動搜索數據。順序: page域 -> request域 -> session域 -> context域 --%>
<%=pageContext.findAttribute("message") %>
<hr/>
</body>
</html>
運行結果如下圖所示:
4. 用途三:引入和跳轉到其他資源
(1) PageContext類中定義了一個forward方法和兩個include方法來分別簡化和替代RequestDispatcher.forward方法和include方法;
(2) 傳遞給這些方法的資源路徑,如果路徑以“/”開頭,表示相對於當前WEB應用程序的根目錄,否則,表示相
對於當前JSP所映射到的訪問路徑。
(3) 如果想把數據從一個資源發到另外一個資源,前提是使用重定向技術,此時只能使用Session域和context
域;(重定向是不能從request中帶數據的);此時分析這個數據是瀏覽器特有的還是全局的?
(4) 實例:
① 轉發
保存數據:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
isErrorPage="true"
session="true"
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>pageContext對象</title>
</head>
<body>
<%-- pageContext作爲域對象使用,可以往不同域對象中存取數據 --%>
<%
pageContext.setAttribute("message", "page's message");
pageContext.setAttribute("message","request's messsage",PageContext.REQUEST_SCOPE);//保存到request域中
//request.setAttribute("message","request's message"); 等價於上面的代碼
pageContext.setAttribute("message","session's messsage",PageContext.SESSION_SCOPE);//保存到sessio域中
pageContext.setAttribute("message","application's messsage",PageContext.APPLICATION_SCOPE);//保存到context域中
%>
<%
//轉發
request.getRequestDispatcher("/05.pageContext2.jsp").forward(request,response);
%>
</body>
</html>
獲取數據:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>從四個域中獲取數據</title>
</head>
<body>
page域:<%=pageContext.getAttribute("message",PageContext.PAGE_SCOPE) %><br/>
request域: <%=pageContext.getAttribute("message",PageContext.REQUEST_SCOPE) %><br/>
session域: <%=pageContext.getAttribute("message",PageContext.SESSION_SCOPE) %><br/>
context域:<%=pageContext.getAttribute("message",PageContext.APPLICATION_SCOPE) %><br/>
</body>
</html>
運行結果如下圖所示:
② 重定向
保存數據:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"
isErrorPage="true"
session="true"
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>pageContext對象</title>
</head>
<body>
<%-- pageContext作爲域對象使用,可以往不同域對象中存取數據 --%>
<%
pageContext.setAttribute("message", "page's message");
pageContext.setAttribute("message","request's messsage",PageContext.REQUEST_SCOPE);//保存到request域中
//request.setAttribute("message","request's message"); 等價於上面的代碼
pageContext.setAttribute("message","session's messsage",PageContext.SESSION_SCOPE);//保存到sessio域中
pageContext.setAttribute("message","application's messsage",PageContext.APPLICATION_SCOPE);//保存到context域中
%>
<%
//重定向
response.sendRedirect(request.getContextPath()+"/05.pageContext2.jsp");
%>
</body>
</html>
獲取數據:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>從四個域中獲取數據</title>
</head>
<body>
page域:<%=pageContext.getAttribute("message",PageContext.PAGE_SCOPE) %><br/>
request域: <%=pageContext.getAttribute("message",PageContext.REQUEST_SCOPE) %><br/>
session域: <%=pageContext.getAttribute("message",PageContext.SESSION_SCOPE) %><br/>
context域:<%=pageContext.getAttribute("message",PageContext.APPLICATION_SCOPE) %><br/>
</body>
</html>
運行結果:
四. 補充:域對象
1. Servlet中的三個域對象:
(1) ServletContext-------context域
(2) HttpServletRequet---request域
(3) HttpSession----------session域
2. JSP中的四個域對象:
(1)pageContext-------page域
(2)request-------------request域
(3)session-------------session域
(4)ServletContext-----application域(context域)3. 域對象的作用:
域對象可以保存數據和獲取數據,用於數據共享。
4. 域對象中的方法:
(1) setAttribute("name",Object)---保存數據
(2) getAttribute("name")---獲取數據
(3) removeAttribute("name")---清除數據5. 域對象作用範圍:
(1) page域:只能在當前JSP頁面中使用(當前頁面);
(2) request域:只能在同一個請求中使用(轉發);
(3) session域:只能在同一個會話(session對象)中使用(私有的),只要不關閉瀏覽器,那麼這個session就
一直存在;
(4) context域:只能在同一個web應用中使用。