Java Web(六) JSP

如今的Java Web開發已經不多使用JSP腳本了,業務邏輯都交給Servlet處理,JSP只負責顯示視圖,因此接下來的內容就對JSP腳本不作敘述了。。。html

JSP概述

JSP全名爲Java Server Page,是爲了簡化Servlet的工做而出現的替代品。JSP是一種基於文本的程序,其特色是HTML與Java程序共同存在。執行時JSP會被Tomcat自動編譯,編譯後的JSP和HttpServlet同樣,都是javax.servlet.Servlet接口的子類,所以JSP是另外一種形式的Servlet。java

JSP工做原理

JSP是一種Servlet,可是與HttpServlet的工做方式不太同樣。HttpServlet是先由源代碼編譯爲class文件後部署到服務器下的,先編譯後部署。而JSP則是先部署源代碼後編譯爲class文件的,先部署後編譯。JSP會在客戶端第一次請求JSP文件時被編譯爲HttpJspPage類(接口Servlet的一個子類)。該類會被服務器臨時存放在服務器工做目錄上面。之後客戶端訪問這個JSP時,服務器再也不編譯這個JSP文件,而是直接調用已有的class文件進行響應。因此客戶端第一次請求時會感受比較慢,由於JSP須要編譯,而以後速度就快多了。但若是JSP被修改,或者class文件被刪除,Tomcat可以檢測到,Tomcat會在下一次請求時從新編譯JSP,而不須要重啓Tomcat。(這種自動檢測功能是默認的,能夠在web.xml中關閉)web

JSP生命週期

JSP會被容器轉譯爲Servlet源代碼,自動編譯爲.class文件,載入.class文件,而後生成Servlet對象,如圖:數組

  img

JSP也是Servlet,運行時只有一個實例。和Servlet同樣,JSP實例化,銷燬時也會調用Servlet的init()方法與destroy()方法。另外JSP還有本身的初始化方法與銷燬方法_jspInit()與_jspDestroy()。Servlet的init方法和destory()方法會相應的調用_jspInit()與_jspDestroy()方法。注意到這兩個方法名稱前有個下劃線,表示這些方法時由容器轉譯時維護,因此你不能重寫這些方法。若是你想對JSP作些初始化工做或收尾工做,你能夠重寫jspInit()方法或jspDestory方法。瀏覽器

JSP指令

JSP指令的主要目的,在於指示容器將JSP轉譯爲Servlet源代碼時,一些必須遵照的信息,JSP指令的語法以下所示:緩存

<%@ 指示類型 [屬性="值"]* %>安全

在JSP中有三種常見的指令:page、include 與 taglib。page指令告知容器如何轉譯目前的JSP網頁。include指令告知容器將別的JSP頁面包括進來進行轉譯。taglib指令告知容器如何轉譯這個頁面中的標籤庫。服務器

  1. page指令cookie

    page指令是最經常使用的指令,能夠聲明JSP頁面的屬性等。JSP指令的多個屬性能夠寫在一個page指令裏,也能夠寫在多個page指令裏。每一個屬性只能出現一次,不然出現編譯錯誤。(import屬性除外)。session

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

    page指令的常見的屬性:

    • language:指明解釋該JSP時採用的語言。通常爲Java語言。默認爲Java語言。
    • import:指明編譯該JSP時繼承哪一個類。
    • session:指明該JSP是否內置Session對象。true則內置,false不內置。默認爲true。
    • autoFlush:是否容許緩存。若是爲true,則使用out.println()等方法輸出字符不會馬上到達服務器,而是暫時存在緩存裏,緩存滿時或者程序執行完畢或者執行out.flush()操做時纔到客戶端。默認爲true。
    • buffer:指定緩存大小。當autoFlush設爲true時纔有效,例如:<%@ page buffer="10kb" %>。
    • isThreadSafe:指定是否線程安全。若是爲true,則運行對個線程同時運行該JSP,不然只運行一個線程,其他線程等待。默認爲false。
    • isErrorPage:指定該頁面是否爲錯誤處理頁面。若是爲true,則該JSP內置有一個Exception對象,可直接使用,不然沒有,默認爲false。
    • errorPage:指明一個錯誤顯示頁面。若是該JSP程序拋出了一個未捕捉的異常,則轉到errorPage指定的頁面。errorPage指定的頁面一般是isErrorPage屬性爲true,且內置的Exception對象爲未捕捉的異常。
    • contentType:客戶端瀏覽器根據屬性判斷文檔類型。
    • info:指明JSP的信息。該信息能夠經過Servlet.getServletInfo()方法獲得。
    • trimDirectiveWhitespaces:是否去掉指令先後的空白字符。默認爲fasle。
  2. include指令

    include指令比較簡單,只有一種形式:<%@ inlcude file="relativeURL" %>。relativeURL是另外一個JSP文件或HTML文件的路徑。例如,網站內全部網站均有一個統一風格的導航欄head.jsp與頁腳版權的foot.jsp,就可使用include指令。include指令能夠實現頁面的區塊化。

    <%@include file="head.jsp"%>
    <h2>Hello World</h2>
    <%@include file="foot.jsp"%>
  3. taglib

    JSP支持標籤技術,使用標籤功能可以實現視圖代碼重用,不多量的代碼就可以實現很複雜的顯示效果。taglib指令用來指明JSP頁面內使用的JSP標籤庫。taglib指令有兩個屬性,uri爲類庫的地址,prefix爲便籤的前綴。

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>book</title>
    </head>
    <body>
    <c:forEach var="book" items="books">
        <h2>${book.name}</h2>
    </c:forEach>
    </body>
    </html>

JSP九大隱式對象

Servlet和JSP中輸出數據都須要使用out對象。Servlet中的out對象是經過response.getWriter()獲得的。而JSP中沒有定義out對象,卻能夠直接使用。這是由於out是JSP的內置對象。JSP中一共內置了9個內置對象,分別爲out、request、response、config、session、application、page、pageContent、exception。

  • out爲javax.servlet.jsp.JspWriter類的實例、服務器向客戶端輸出的字符內容能夠經過out對象輸出。
  • request爲javax.servlet.ServletRequest類的實例,表明着客戶端的請求。
  • response爲javax.servlet.ServletResponse類的實例,表明着服務器的響應。
  • config是java.servlet.ServletConfig類的實例。ServletConfig封裝了配置在web.xml中初始化JSP的參數。
  • session是java.servlet.http.HttpSession的實例。Session是記錄客戶會話狀態的機制。
  • application是java.servlet.ServletContext的實例。application封裝了JSP所在的Web應用程序的信息。
  • page是java.servlet.jsp.HttpJspPage類的實例、page對象表明當前JSP頁面,是JSP編譯後的Servlet類的對象。至關於java語言中的this。
  • pageContext爲java.servlet.jsp.PageContext的實例,PageContext對象表明當前頁面編譯後的內容。經過PageContext對象可以獲得JSP中的資源。  
  • exception爲java.lang.Exception類的對象,Exception對象封裝了JSP拋出的異常,要使用exception隱藏對象,須要設置<%@ isErrorPage="true" %>。exception一般用來處理錯誤頁面。

EL表達式

JSP可使用EL表達式從page、request、session、application域中獲取屬性,還能夠進行簡單的運算和判斷,這樣能夠大大減小JSP頁面上Scriptlet的使用。

EL表達式的11個隱式對象

  • pageContext對應於JSP頁面中的pageContext對象。
  • pageScope表明page域中保存屬性的Map對象。
  • requestScope表明request域中保存屬性的Map對象。
  • sessionScope表明session域中保寸屬性的Map對象。
  • applicationScope表明application域中保存屬性的Map對象。
  • param表明保持了全部請求參數的Map對象。
  • paramValues表明保存了全部請求參數的Map對象,他對於某個請求參數,返回的是一個String類型的數組。
  • header表明一個保存類全部頭字段的Map對象。
  • headerValues表明一個保存類全部頭字段的Map對象,返回String類型數組。
  • cookie表示類一個保存類全部cookie的Map對象。
  • initParam表示一個保存了全部Web應用初始化參數的Map對象。
  1. pageContext對象

    EL表達式中的pageContext隱式對象與JSP頁面中的pageContext對象相對應,EL表達式能夠經過pageContext隱式對象訪問其它JSP隱式對象,如訪問request、response對象屬性時,可使用表達式$ {pageContext.response.contentType}等。

  2. 表明特定域屬性的隱式對象(共4個)

    EL表達式中的pageScope、requestScope、sessionScope和applicationScope四個隱式對象分別用於訪問JSP頁面的page、request、session、application四個域中的屬性。在EL表達式中也能夠不使用這些隱式對象來指定查找域,而是直接引用這些域中的屬性名稱。例如,表達式$ {userName}就會在page、request、session、application這四個做用域內按順序依次查找userName屬性,直到找到爲止。

  3. 表明請求參數的隱式對象(2個)

    EL表達式中的隱式對象param和paramValues用於獲取客戶端訪問JSP頁面時傳遞的請求參數的值,因爲HTTP協議容許使用一個請求參數名出現屢次,即一個請求參數可能會有多個值,因此,EL表達式提供了param和paramValues這兩個隱式對象來分別獲取請求參數的某個值和全部值。Param隱式對象用於返回一個請求參數的某個值,若是同一個請求參數有多個值,則返回第一個參數的值。paramValues隱式對象用於返回一個請求參數的全部值,返回結果爲該參數的全部值組成的字符串數組,例如表達式${paramValues.username[0]}用於返回數組中第一個元素的值。

  4. 表明HTTP請求消息的隱式對象(2個)

    EL表達式中的隱式對象header和headerValues用於獲取客戶端訪問JSP頁面時傳遞的請求頭字段的值。因爲HTTP協議容許一些請求頭字段出現屢次,即一個請求頭字段可能會有多個值,因此,EL表達式提供了header和headerValues兩個隱式對象分別用於獲取請求頭字段的某個值和全部值。header隱式對象返回一個請求頭字段的某個值,若是同一個請求頭字段有多個值,則返回第一個值,例如,使用表達式${header.referer}能夠很是方便的獲取referer請求頭字段的值。headerValues隱式對象用於返回一個請求頭字段全部值組成的字符串數組。

  5. cookie隱式對象

    EL表達式中的隱式對象cookie是一個表明全部Cookie信息的Map集合,Map集合中元素的關鍵字爲各個Cookie的名稱,值則爲對應的Cookie對象。使用cookie隱式對象能夠訪問某個Cookie對象,這些Cookie對象則是經過調用HTTPServletRequest.getCookies()方法獲得的,若是多個Cookie共用一個名稱,則返回Cookie對象數組中的第一個Cookie對象。例如,要訪問一個名爲userName的Cookie對象,可使用表達式${cookie.userName}。

  6. initParam隱式對象

    EL表達式中的initParam是一個表明Web應用程序中的全部初始化參數的Map對象,每一個初始化參數的值是ServletContext.getInitParameter(String name)方法返回的字符串。

EL表達式獲取屬性

EL表達式默認是以page、request、session、application的順序來尋找EL中指定的屬性的。EL經過[ ]運算符和 . 運算符來獲取指定的屬性。

  • 若是使用 . 運算符,則左邊能夠是JavaBean、Map對象或自定義對象。
  • 若是使用[ ]運算符,則左邊能夠是JavaBean、Map、數組、List對象或自定義對象。

簡單來講就是有下標的使用[ ],沒下標的都用 。

${book.name}

EL表達式運算

EL表達式支持簡單的運算,包括加(+)、減(-)、乘(*)、除(/或者div)、取餘(%或者mod)、三目運算符等,例如:

${1 + 2}<!--輸出3-->
${1 == 2 ? 3 : 4}<!--輸出4-->

EL表達式支持簡單的比較運算,包括大於(> 或 gt),小於(< 或 lt),等於(== 或 eq),不等於(!= 或 ne),大於等於(>= 或 ge),小於等於(<= 或 le)等,例如:

${1 < 2}<!--輸出true-->
${5 >= 2}<!--輸出false-->

EL表達式還支持邏輯運算,且(&& 或 and),或(|| 或 or),否(! 或 not),例如:

${1 < 2 && 5 >= 2}<!--輸出false-->

還能夠結合JSTL標籤庫判斷域中某值是否爲空,而後能夠在界面上顯示不一樣的信息,例如:

<c:if test="${empty user}">
    <h3>請先登入</h3>
</c:if>
<c:if test="${not empty user}">
    <h3>${user.name},歡迎您</h3>
</c:if>

自定義EL函數

支持自定義EL函數的功能,若是咱們想使用EL表達式鏈接字符串,你可能會想到使用${ str1 + str2 },可是這是錯的,由於EL表達式中的 + 只表明加法,要實現該功能,你能夠自定義EL函數。

第一步:編寫類,這個函數必須是公開的(public)且是靜態方法(static),例如:

package Utils;

public class Util {
    public static String strcat(String str1, String str2) {
        return str1 + str2;
    }
}

第二步:編寫標籤程序庫描述(Tag Liabrary Descriptor)文件,這個文件是一個XML文件。

<?xml version="1.0" encoding="utf-8"?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
        version="2.0">

    <tlib-version>1.0</tlib-version>
    <short-name>util</short-name>
    <uri>http://kindleheart.com/util</uri>
    <function>
        <name>strcat</name>
        <function-class>Utils.Util</function-class>
        <function-signature>
            java.lang.String strcat(java.lang.String,java.lang.String)
        </function-signature>
    </function>
</taglib>

第三步:直接使用該標籤,例如:

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="util" uri="http://kindleheart.com/util" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>自定義EL函數</title>
</head>
<body>
<%
    String str1 = "今每天氣";
    String str2 = "真好";
    request.setAttribute("str1", str1);
    request.setAttribute("str2", str2);
%>
${util:strcat(requestScope.str1, requestScope.str2)}
</body>
</html>

網頁顯示結果:

    

相關文章
相關標籤/搜索