JSP內置對象、指令和動作

JSP內置對象、指令和動作

一、內置對象

在 JSP 的 Java 代碼塊、表達式塊等中可以直接使用的引用,稱為 JSP 的內置對象。常用的內置對象有九個,分別是:

1.jpg

這九個對象在 JSP 的 Java 代碼塊、表達式塊中可以直接使用。之所以可以直接使用,是因為 Java 代碼塊與表達式塊被 JSP 引擎翻譯后均出現在了 Servlet 的_jspService()方法中。而這九個對象,就_jspService()方法中的局部變量。在 JSP 的 Java 代碼塊、表達式塊中的代碼就是_jspService()方法中的代碼,所以在其中可以直接使用。

2.jpg

1.1 pageContext

pageContext,頁面上下文,其具有一個只在當前頁面范圍的域屬性空間,即其具有setAttribute()方法與 getAttribute()方法。但,由于在當前頁面范圍,數據不存放到域屬性空間也可直接使用,將數據存放到域屬性空間反而感覺“多此一舉”,所以這些方法并不常用。不過,在同一頁面中,為了使用 EL 表達式(后面學習)來訪問某變量的值,此時一般使用
pageContext。pageContext 具有一些 get 方法,可以獲取到 Request、Response、Session、ServletContext、ServletConfig、page(即當前 Servlet)、exception、out 等另外八個內置對象。

3.jpg

但由于這些對象本身就是內置對象,在 JSP 頁面中可以直接使用,所以這些方法也并不常用。不過 EL 表達式中,將會經常使用 pageContext 的這些方法。

1.2 application

application,即 ServletContext。所以 ServletContext 所具有的方法,application 都具有。
常用的方法例如,

  • String getInitParameter ():
    獲取 web.xml文件的<context-param/>中指定名稱的上下文參數值。例 如getInitParameter(“myDBDriver”);會返回字符串“com.mysql.jdbc.Driver”。

  • Enumeration getInitParameterNames():獲取 web.xml 文件的<context-param/>中的所有的上下文參數名稱。其返回值為枚舉類
    型 Enumeration<String>。

  • void setAttribute(String name, Object object):
    在 ServletContext 的公共數據空間中,也稱為域屬性空間,放入數據。這些數據對于 Web應用來說,是全局性的,與整個應用的生命周期相同。當然,放入其中的數據是有名稱的,通過名稱來訪問該數據。

  • Object getAttribute(String name):
    從 ServletContext 的域屬性空間中獲取指定名稱的數據。

  • void removeAttribute(String name):
    從 ServletContext 的域屬性空間中刪除指定名稱的數據。

  • String getRealPath(String path):
    獲取當前 Web 應用中指定文件或目錄在本地文件系統中的路徑,是基于盤符的路徑。

  • String getContextPath():
    獲取當前應用在 Web 容器中的名稱。

1.3 out

out,類型為 javax.servlet.jsp.JspWriter。查看 JavaEE 文檔,發現 JspWriter 類繼承自 IO流的 Writer 類。即 out 就是一個輸出流對象。

4.jpg

1.4 page

查看 JSP 翻譯為的 Servlet,可以看到 page 對象即 Servlet 對象本身。這個對象在實際應用中并不常用。

5.jpg

1.5 exception

在普通的 JSP 頁面中是不能使用 exception 內置對象的。因為打開 JSP 翻譯為的 Servlet,發現其中并沒有 exception 對象。若要在頁面中直接使用 exception 對象,則需要配合著 page指令使用。

1.6 其它對象

其它對象,還有 request、response、session,及 config。它們的用法與Servlet的用法相同。只不過是直接使用在了 JSP 頁面中了。

二、JSP指令

SP 指令的作用是為當前頁面做一些基本的屬性設置,為當前的頁面的運行提供基本的環境。

根據功能的不同,JSP 中包含三類指令:page 指令,即頁面指令;include 指令,即包含指令;及 taglib 指令,即標簽庫指令。無論哪種指令,其使用的語法格式均為如下形式:

<%@ 指令名稱 屬性名=屬性值 屬性名=屬性值 ... %>

2.1 page指令

page 指令用于設置當前 JSP 頁面的相關信息。一個 JSP 文件中可以包含多個 page 指令。常用的 page 指令的屬性意義及用法如下:

(1)pageEncoding屬性

pageEncoding 屬性用于設置當前 JSP 頁面所使用的字符編碼格式。即,用戶在瀏覽器中通過右擊查看編碼所看到的編碼格式。

<%@ page pageEncoding="utf-8" %>

其被 JSP 翻譯引擎翻譯到 Servlet 中的語句,是_jspService()方法中的 setContentType()。

(2)contentType屬性

contentType 屬性用于設置當前 JSP 頁面呈現于用戶瀏覽器中的內容類型,通常為”text/html”類型,即 html 格式的文本。若在 JSP 頁面中設置如下:

<%@ page contentType="text/html" %>

注:當內容類型為”text/html”時,使用 pageEncoding 屬性與contentType 屬性效果是相同的。只有當內容類型不為”text/html”時,才專門使用 contentType 屬性指定。在指定字符編碼時,這兩個屬性一般不同時使用。

(3)import屬性

import 屬性,用于完成在 JSP 頁面中導入指定的類。其被 JSP 引擎翻譯為 Servlet 中的import 語句。例如,

<%@ page import="java.util.Date" %>

若要導入多個類,則在 import 屬性值中可使用逗號將這些類分隔。

<%@ page import="java.util.Date,java.sql.*"%>

(4)errorPage屬性

errorPage 屬性用于指定,當前頁面運行過程中發生異常時所要跳轉到的頁面。

<%@ page errorPage="/error.jsp"%>

<%
    int i = 3/0;
%>

注意,該屬性會被翻譯到 Servlet 的_jspService()方法中,即這里出現的路徑是一個后臺路徑,而非前臺路徑。所以這里指定的發生異常后所要跳轉的頁面,需要使用以斜杠開頭的后臺路徑。

(5)isErrorPage屬性

若一個頁面中指定了發生異常后所要跳轉的頁面,將會出現一個問題:異常信息被隱藏了。在控制臺看不到異常信息,在所跳轉的頁面中也看不到異常信息。這對于程序員來說,不是件好事,沒有足夠的信息提示。

此時,一般是希望當異常發生后,在所要跳轉的頁面中能夠給出相應的異常信息。而異常信息是封裝在異常對象 exception 中的。也就是說,我們需要在所要跳轉的頁面中能夠獲取到異常對象。此時,就需要將這個所要跳轉的頁面指定為“錯誤處理頁面”。

當一個頁面的 page 指令中設置 isErrorPage 的值為 true 時,表明當前頁面為一個“錯誤處理頁面”。默認 isErrorPage 的值為 false。

<%@ page isErrorPage="true" pageEncoding="utf-8"%>

error page

<%
    //在控制臺輸出異常的堆內存跟蹤信息
    exception.printStackTrace();
%>

一旦一個頁面 page 指令的 isErrorPage 屬性被指定為了 true,查看 JSP 頁面所翻譯為的Servlet 則會發現,在_jspService()方法中,多出了一個變量 exception。這就是內置對象exception,可以在 JSP 的 Java 代碼塊、表達式塊中直接使用的內置對象。

(6)session屬性

session 屬性用于指定當前頁面中是否可以直接使用內置對象 session。默認為 true,可以使用。查看JSP翻譯為的Servlet,可以看到session的創建,使用的是無參方法getSession()。該方法的功能是,若當前具有 session,則使用當前的 session;若當前沒有 session,則會新建一個 session。即 session 對象肯定不為 null。

但,有些情況下,我們希望的僅僅是獲取到之前已經存在的 session,若之前沒有 session,則并不需要創建 session,即讓 session 為 null。顯示使用默認的 session 屬性為 true 已經無法滿足需求了。此時,就需要將 session 屬性設置為 false,即不使用內置對象session,而是在JSP 頁面的代碼塊中使用 request 的帶參getSession()方法。

HttpSession session = request.getSession(false);

若設置 session 屬性的值為 false,查看生成的 Servlet 代碼,會發現根本就沒有出現內置對象 session。

2.2 include指令

include 指令,即包含指令,用于將指定的文件包含到當前的 JSP 文件中。該指令只有一個屬性 file,用于指定要包含的文件。

(1)用法:被 include 指定包含的文件,可以是 JSP 動態頁面文件,也可以是 HTML 靜態頁面文件。這里定義一個名為 left.jsp 的動態文件。其中定義了一個變量 sum。

left jsp page
<%
    int sum=100;
%>

再定義一個 index.jsp,不僅將 left.jsp 文件包含了進來,還訪問了變量 sum。

index jsp page
<br>
<%@ include file="/left.jsp" %>
<br>
<%=sum %>

運行結果:

index jsp page
left jsp page
100

(2)靜態聯編

查看 Tomcat 的 work 目錄中相關子目錄,發現只生成了一個 index_jsp.java 的 Servlet 源文件,并沒有生成 left_jsp.java 文件。那是因為 JSP 翻譯引擎在翻譯時,會將 include 指令所指定的文件內容直接翻譯到當前 JSP 對應的 Servlet 中,形成一個.java 文件。這就說明一個問題:這個包含操作是在編譯之前完成的,是在編譯之前由 JSP 翻譯引擎完成的,不是在程序運行期完成的。這種包含是一種靜態包含,稱為靜態聯編。

由于在編譯期就將這些文件合并為了一個 Servlet 文件,所以,整個過程就一個_jspService()方法。也就是說,這些文件之間是可以相互訪問局部變量的。只要滿足變量聲明與使用的先后順序即可。

6.jpg

(3)為什么使用include指令

對于一個包含很多頁面的系統或站點,很多頁面的頭部、底部,或者左側部分都是相同的。為了減少頁面定義的重復性工作,為了便于對這些相同部分的修改,我們將這些相同的部分,分別定義為了多個頁面。然后,讓其它需要使用這些部分的頁面,使用 include 指令將這些部分包含進來。這樣的話,不僅大大減少了工作量,還做到了對于頁面修改的“一改全改”效果。

三、JSP動作(Action)

在 JSP 頁面中大量使用 Java 代碼塊、表達式塊等內容,會使 JSP 頁面看起來“雜亂無章”。為了使 JSP 頁面看得簡潔明了,為了簡化 Java 代碼,一般情況下,我們會盡量少的使用 Java代碼塊與表達式塊。取而代之的則是使用 EL 表達式、JSTL 標簽,及 JSP 動作。

JSP 動作是指,使用系統定義好的標簽來完成本應由 Java 代碼來完成的功能。

JSP 動作的語法格式為:

<jsp:動作名稱 屬性名=屬性值 屬性名=屬性值 ....></jsp:動作名稱>

<jsp:動作名稱 屬性名=屬性值 屬性名=屬性值 .... />

JSP 動作很多,但在實際開發時常用的就兩個:轉發動作與包含動作。
這兩份個動作的完成,底層使用的是 RequestDispatcher 的 forward()與 include()方法實現的。而這兩份種請求轉發方式的本質區別是,標準輸出流的開啟時間不同。forward()方式的標準輸出流是在目標資源中開啟的標準輸出流,而 include()方式的標準輸出流則是在當前發出包含運作的頁面中開啟的。所以,forward()動作的發起頁面中是無法向標準輸出流中寫入數據的;而 include()動作的發起頁面及目標頁面中均可向標準輸出流中寫入數據。這兩份個動作都具有一個 page 屬性,用于指定要轉向的頁面。

3.1 forward動作

頁面中一旦具有了forward動作,那么當前頁面中的所有顯示的內容都將無法顯示。因為頁面直接轉發到了下一個頁面。

7.jpg

(1)定義index.jsp頁面

<%@ page contentType="text/html; charset=utf-8" %>

頁面中只要具有了forward動作,當前頁面中的所有要顯示的內容都將無法顯示。因為頁面直接轉發到了下一個頁面。

<%
    request.setAttribute("user","beijing");
%>
<jsp:forward page="/next.jsp"/>

(2)定義next.jsp頁面

next page
<br>
<%=request.getAttribute("user") %>

打開 JSP 頁面翻譯為的 Servlet,可以看到要跳轉的路徑出現在了 Servlet 代碼中,即可以使用后臺路徑。

8.jpg

注意,在 JSP 動作中,沒有用于完成重定向的動作。

3.2 include動作

include 動作用于完成將指定頁面包含到當前頁面中的功能。

9.jpg

(1)用法

定義index.jsp頁面

index page
<%
    int sum=50;
%>
<br>

<jsp:include page="/left.jsp"/>
<br>
index page sum = <%=sum %>

定義left.jsp頁面

left page
<%
    int sum = 100;
%>
<br>
left page sum = <%=sum %>

運行結果:

index page
left jsp page
left page sum = 100
index page sum = 50

(2)動態聯編

打開 Tomcat 的 work 目錄的相關子目錄,可以看到有兩個.java 文件:index_jsp.java 與left_jsp.java。也就是說,包含動作的包含,是在運行期完成的,而非在編譯期。這個包含動作,是在程序運行過程中,由 index_jsp 文件中的_jspService()方法通過 JspRuntimeLibrary 類
的 include()方法調用了 left_jsp 文件中的_jspService()方法。在運行期所執行的這種包含,稱為動態聯編。

(3)靜態聯編與動態聯編的應用場景

在靜態聯編與動態聯編均可使用時,一般使用靜態聯編。因為在程序運行時只存在一個Servlet,對資源的消耗較少,且不存在調用問題,執行效率較高。若在兩個文件間需要共享同一變量,此時只能使用靜態聯編。若在兩個文件間存在同名變量,且不能混淆,此時只能使用動態聯編。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1.什么是JSP (1)jsp全稱是Java Server Pages,它和Servlet技術一樣都是sun公司定...
    yjaal閱讀 3,683評論 5 99
  • 1.學習內容 JSP技術入門和常用指令 JSP的內置對象&標簽介紹 EL表達式&EL的內置對象 2.JSP技術入門...
    WendyVIV閱讀 2,161評論 1 18
  • 一、JSP內置對象簡介 JSP內置對象是Web容器創建的一組對象,不使用new關鍵字就可以使用的內置對象。開發者可...
    年少懵懂丶流年夢閱讀 3,786評論 0 8
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,754評論 18 399
  • 前面講了servlet入門實踐現在開始介紹jsp入門實踐,開發環境的搭建請參考我前面的tomcat的文章,jsp入...
    伊豚wall閱讀 3,384評論 2 56