JSP第二篇【內建物件的介紹、4種屬性範圍、應用場景】

Java3y發表於2018-02-05

什麼是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頁面

    <%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="error.jsp" %>
    
    <html>
    <head>
        <title></title>
    </head>
    <body>
    
    <%--模擬空指標異常的錯誤--%>
    <%
    
        String sss = null;
        sss.length();
    %>
    
    </body>
    </html>
  • 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種屬性範圍了。

  1. page【只在一個頁面中儲存屬性,跳轉頁面無效】
  2. requet【只在一次請求中儲存屬性,伺服器跳轉有效,瀏覽器跳轉無效】
  3. session【在一個會話範圍中儲存屬性,無論何種跳轉均有效,關閉瀏覽器後無效】
  4. application【在整個伺服器中儲存,所有使用者都可以使用】

  • 4個內建物件都支援以下的方法:
  1. setAttribute(String name, Object o )
  2. getAttribute(String name)
  3. removeAttribute(String name)

應用場景

  1. request:如果客戶向伺服器發請求,產生的資料,使用者看完就沒用了,像這樣的資料就存在request域,像新聞資料,屬於使用者看完就沒用的
  2. session:如果客戶向伺服器發請求,產生的資料,使用者用完了等一會兒還有用,像這樣的資料就存在session域中,像購物資料,使用者需要看到自己購物資訊,並且等一會兒,還要用這個購物資料結帳
  3. servletContext:如果客戶向伺服器發請求,產生的資料,使用者用完了,還要給其它使用者用,像這樣的資料就存在servletContext域中,像聊天資料

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章的同學,可以關注微信公眾號:Java3y

相關文章