Jsp:內置對象和四種域對象的理解


由來:在jsp開發中,會頻繁使用到一些對象 。例如HttpSession,ServletContext,ServletContext,HttpServletRequet。所以Sun公司設計Jsp時,在jsp頁面加載完畢之后就會自動幫開發者創建好這些對象,開發者只需要直接使用這些對象調用方法即可!這些創建好的對象就叫內置對象,一共有九個。

內置對象名 類型
request HttpServletRequest
 response  HttpServletResponse
config ServletConfig
application ServletContext
session Httpsession
exception Thrwable(錯誤處理頁面)
page Object(this:當前jsp翻譯的類如我們上次寫到的hello.jsp翻譯變成了hello_jsp.java中的生命周期方法)
out JspWriter
pageContext pageContext

我們可以隨便打開一個以jsp翻譯的java源文件

public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html;charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

    } 

  從上面可以看到內置對象都是在service方法中創建的,而指令和聲明是成員變量和方法,故不能在指令和聲明中使用內置對象


1、out對象

  是jspWriter類,相當於帶緩存的PrintWriter。有點與PrintWriter方法相似

 

  如果我們在jsp頁面執行以下代碼會發現

<%
    		out.write("abc");
    		response.getWriter().write("2222223");
%>

因為out中添加了緩沖區的設置,所以在瀏覽器中先打印出后面的語句,前面的要等其緩沖區(默認大小是8kb)沒有滿,要等jsp頁面執行完之后才打印,我們也可以去手動刷新頁面

         

我們可以在jsp的指令部分去設置緩沖區大小

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" buffer="8kb"%>

我們繼續做實驗,在jsp頁面運行如下的代碼

<%
    		out.write("abc");
    		//查看緩沖區的大小
    		System.out.println("當前緩沖區的大小:"+out.getBufferSize());
    		System.out.println("當前緩沖區的剩余大小:"+out.getRemaining());
 %>

看到的結果是這樣的:

 

我們在瀏覽端發送了只有“abc”這樣3個字節,卻是用了兩百多個字節的大小,多余的部分去哪了呢?這個時候我們可以全看看out_jsp.java文件,

 out.write("\r\n");
      out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
      out.write("<html>\r\n");
      out.write("  <head>\r\n");
      out.write("    <base href=\"");
      out.print(basePath);
      out.write("\">\r\n");
      out.write("    <title>My JSP 'out.jsp' starting page</title>\r\n");
      out.write("  </head>\r\n");
      out.write("  <body>\r\n");
      out.write("     \t");

    		out.write("abc");
    		//查看緩沖區的大小
    		System.out.println("當前緩沖區的大小:"+out.getBufferSize());
    		System.out.println("當前緩沖區的剩余大小:"+out.getRemaining());
    	 
      out.write("\r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");

其實我們會發現,我們向瀏覽發送字節遠不止abc,其實還有一些標簽等的內容,他們是要發送到瀏覽器端,也是占大小的。

我們再來做一個實驗,如下代碼,

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" buffer="1kb"%>
<%	
	System.out.println(out.getRemaining());
	for(int i=1;i<=1024;i++)
	out.write("a");
	//查看緩沖區的大小
	response.getWriter().write("郭慶興");
 %>

看到這個時候的效果:

不知道為什么我這里出現了一開始的緩沖區大小是1022(我設置了應該是1kb buffer="1kb"),但是這不是我的重點,重點是他這個圖說明了緩沖區的運行機制,如果緩沖區滿了,就立即將其打印出來,沒有滿,就等待頁面執行完才打印,就像第一次1022緩沖區滿了之后去打印,然后又重新往里放兩個a,此時緩沖區沒有滿,就必須等待jsp頁面加載完后執行,所以出現在“郭慶興”的后面出現。

(我發現不知道哪里用了兩個字節使得一開始的緩沖區大小只有1022B,我有試了buffer="2kb"和buffer="3kb",發現其剩余大小都正常)

2、exception 對象

該對象表示其他頁面所拋出的異常對象(Throwable對象)

我們打開jsp翻譯后的java源文件發現,在該文件的service方法中居然里面八大內置對象都存在,就唯獨沒有該對象,這是因為我們沒有指定其為錯誤處理頁面,只有指定當前頁面為錯誤錯里頁面后才可以去使用它。

3、pageContext對象

jsp的上下文對象,為了我們更方便的去使用其他八個內置對象。

(例如當我們要在service方法之外去調用session對象或者request對象等,)

public void _jspService(request,response){

          創建內置對象

           HttpSession session =....;

            ervletConfig config = ....;

     把8個經常使用的內置對象封裝到PageContext對象中

             PageContext pageContext  = 封裝;

             調用method1方法(如果將這八個內置對象一個一個的作為參數傳遞給下面的方法,顯然過於麻煩,這個時候我們可以使用已經封裝好了的pageContext作為參數傳遞過去明顯就簡單多了)

              method1(pageContext);

}

public void method1(PageContext pageContext){

  希望使用內置對象

  從PageContext對象中獲取其他8個內置對象

    JspWriter out =pageContext.getOut();

   HttpServletRequest rquest = pageContext.getRequest();

  ........

}

 注意:pageContext也是一個域對象,已經有四個域對象了:request,servletContext,還有session,現在又有pageContext,(cookie不是域對象,而是將數據發送到瀏覽器端保存),那么現在servlet已經有三個域對象了,而jsp有四個域對象(jsp就是一個servlet)。

#保存數據

    1)默認情況下,保存到page域

              pageContext.setAttribute("name");

    2)可以向四個域對象保存數據

              pageContext.setAttribute("name",域范圍常量)

#獲取數據

  1)、默認情況下,從page域獲取

                pageContext.getAttribute("name")

  2)、可以從四個域中獲取數據

      pageContext.getAttribute("name",域范圍常量)

          PageContext.PAGE_SCOPE (page域)

                          PageContext.REQUEST_SCOPE(request域)

                            PageContext..SESSION_SCOPE(session域)

                            PageContext.APPLICATION_SCOPE(aplication域:即servletContext)

  3)、自動在四個域中搜索數據

               pageContext.findAttribute("name");

    如果有相同的名字,則按照順序:page域 -> request域 -> session域- > context域(application域)  

我們可以來對pageContext來做實驗

<%
    	//pageContext作為域對象去保存數據
    	pageContext.setAttribute("message", "i am coming");
    	pageContext.setAttribute("message", "我是pageContext中設置的request域中的值,i am coming", pageContext.REQUEST_SCOPE);
    	//request.setAttribute("name", "gqxing");		//等價於上面的代碼
    	
    	request.setAttribute("value", "request's value");
    	 %>
    	 <hr>
    	 <%--
    	 	原則:在那個域中保存數據,必須在哪個域中取數據。
    	  --%>
    	 <%
    	 	//獲取數據
    	 	String message=(String)pageContext.getAttribute("message");
    	 	out.print(message+"<hr>");
    	 	String name=(String)request.getAttribute("message");
    	 	out.print(name);
    	  %>
    
    	   <hr>
    	   <span>用pageContext中的request域去取request域中設置的值(request.setAttribute("value", "request's value");)</span>
    	   <% String value=(String)pageContext.getAttribute("message", pageContext.REQUEST_SCOPE);
    	   	  out.print(value);
    	    %>
    	    <hr><span>用findattribute去查找:</span>
    	    <%--
    	    	findAttribute:自動搜索功能
    	    	順序:page域(pageContext)——>request域——>session域——>application域。
    	    	 --%>
    	    <%
    	    	String name3=(String)pageContext.findAttribute(message);
    	    	out.print(name);
    	     %>

  結果如圖所示:

 

 


 關於四種域對象的理解

可以來試着去辨別各自的區別(jsp的四個域對象的作用范圍)

page域(pageContext):只能作用於當前頁面,既不能用來做做轉發的數據分享,也不能做重定向的數據分享

request域:只能作用於同一個請求的數據共享,所以只能在請求的轉發中使用

session域:只能作用於一次對話中共享數據(一次對話:用戶打開瀏覽器,瀏覽多個web站點后,關閉該瀏覽器),轉發和重定向都可以使用

context域(application):只能在同一個web應用中使用。(全局的)

我們可以做如下的實驗:

先用請求的轉發做一個實驗,如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>

    <title>My JSP 'demo4.jsp' starting page</title>
  </head>
  <body>
  <%--數據的保存面 --%>
    <%pageContext.setAttribute("messsage", "page'vale",pageContext.PAGE_SCOPE);
      pageContext.setAttribute("message", "request'value",pageContext.REQUEST_SCOPE);
      pageContext.setAttribute("message", "session'value",pageContext.SESSION_SCOPE);
      pageContext.setAttribute("message", "context'value", pageContext.APPLICATION_SCOPE);
     %>   
     <%
     	request.getRequestDispatcher("/demo5.jsp").forward(request, response);
      %>
  </body>
</html>

  然后在另一個頁面去接受數據

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  </head>
  <body>
   page:<%=pageContext.getAttribute("message") %>
   <hr>
   request:<%=pageContext.getAttribute("message",pageContext.REQUEST_SCOPE) %>
   <hr>
   session:<%=pageContext.getAttribute("message",pageContext.SESSION_SCOPE) %>
   <hr>
   application(context):<%=pageContext.getAttribute("message",pageContext.APPLICATION_SCOPE) %>
  </body>
</html>

 最后發現結果如圖所示:

當我們將轉發方式改為重定向的時候,如下:

response.sendRedirect(request.getContextPath()+"/demo5.jsp");

這時結果如圖:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM