如今的Java Web開發已經不多使用JSP腳本了,業務邏輯都交給Servlet處理,JSP只負責顯示視圖,因此接下來的內容就對JSP腳本不作敘述了。。。html
JSP全名爲Java Server Page,是爲了簡化Servlet的工做而出現的替代品。JSP是一種基於文本的程序,其特色是HTML與Java程序共同存在。執行時JSP會被Tomcat自動編譯,編譯後的JSP和HttpServlet同樣,都是javax.servlet.Servlet接口的子類,所以JSP是另外一種形式的Servlet。java
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會被容器轉譯爲Servlet源代碼,自動編譯爲.class文件,載入.class文件,而後生成Servlet對象,如圖:數組
JSP也是Servlet,運行時只有一個實例。和Servlet同樣,JSP實例化,銷燬時也會調用Servlet的init()方法與destroy()方法。另外JSP還有本身的初始化方法與銷燬方法_jspInit()與_jspDestroy()。Servlet的init方法和destory()方法會相應的調用_jspInit()與_jspDestroy()方法。注意到這兩個方法名稱前有個下劃線,表示這些方法時由容器轉譯時維護,因此你不能重寫這些方法。若是你想對JSP作些初始化工做或收尾工做,你能夠重寫jspInit()方法或jspDestory方法。瀏覽器
JSP指令的主要目的,在於指示容器將JSP轉譯爲Servlet源代碼時,一些必須遵照的信息,JSP指令的語法以下所示:緩存
<%@ 指示類型 [屬性="值"]* %>安全
在JSP中有三種常見的指令:page、include 與 taglib。page指令告知容器如何轉譯目前的JSP網頁。include指令告知容器將別的JSP頁面包括進來進行轉譯。taglib指令告知容器如何轉譯這個頁面中的標籤庫。服務器
page指令cookie
page指令是最經常使用的指令,能夠聲明JSP頁面的屬性等。JSP指令的多個屬性能夠寫在一個page指令裏,也能夠寫在多個page指令裏。每一個屬性只能出現一次,不然出現編譯錯誤。(import屬性除外)。session
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
page指令的常見的屬性:
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"%>
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>
Servlet和JSP中輸出數據都須要使用out對象。Servlet中的out對象是經過response.getWriter()獲得的。而JSP中沒有定義out對象,卻能夠直接使用。這是由於out是JSP的內置對象。JSP中一共內置了9個內置對象,分別爲out、request、response、config、session、application、page、pageContent、exception。
JSP可使用EL表達式從page、request、session、application域中獲取屬性,還能夠進行簡單的運算和判斷,這樣能夠大大減小JSP頁面上Scriptlet的使用。
pageContext對象
EL表達式中的pageContext隱式對象與JSP頁面中的pageContext對象相對應,EL表達式能夠經過pageContext隱式對象訪問其它JSP隱式對象,如訪問request、response對象屬性時,可使用表達式$ {pageContext.response.contentType}等。
表明特定域屬性的隱式對象(共4個)
EL表達式中的pageScope、requestScope、sessionScope和applicationScope四個隱式對象分別用於訪問JSP頁面的page、request、session、application四個域中的屬性。在EL表達式中也能夠不使用這些隱式對象來指定查找域,而是直接引用這些域中的屬性名稱。例如,表達式$ {userName}就會在page、request、session、application這四個做用域內按順序依次查找userName屬性,直到找到爲止。
表明請求參數的隱式對象(2個)
EL表達式中的隱式對象param和paramValues用於獲取客戶端訪問JSP頁面時傳遞的請求參數的值,因爲HTTP協議容許使用一個請求參數名出現屢次,即一個請求參數可能會有多個值,因此,EL表達式提供了param和paramValues這兩個隱式對象來分別獲取請求參數的某個值和全部值。Param隱式對象用於返回一個請求參數的某個值,若是同一個請求參數有多個值,則返回第一個參數的值。paramValues隱式對象用於返回一個請求參數的全部值,返回結果爲該參數的全部值組成的字符串數組,例如表達式${paramValues.username[0]}用於返回數組中第一個元素的值。
表明HTTP請求消息的隱式對象(2個)
EL表達式中的隱式對象header和headerValues用於獲取客戶端訪問JSP頁面時傳遞的請求頭字段的值。因爲HTTP協議容許一些請求頭字段出現屢次,即一個請求頭字段可能會有多個值,因此,EL表達式提供了header和headerValues兩個隱式對象分別用於獲取請求頭字段的某個值和全部值。header隱式對象返回一個請求頭字段的某個值,若是同一個請求頭字段有多個值,則返回第一個值,例如,使用表達式${header.referer}能夠很是方便的獲取referer請求頭字段的值。headerValues隱式對象用於返回一個請求頭字段全部值組成的字符串數組。
cookie隱式對象
EL表達式中的隱式對象cookie是一個表明全部Cookie信息的Map集合,Map集合中元素的關鍵字爲各個Cookie的名稱,值則爲對應的Cookie對象。使用cookie隱式對象能夠訪問某個Cookie對象,這些Cookie對象則是經過調用HTTPServletRequest.getCookies()方法獲得的,若是多個Cookie共用一個名稱,則返回Cookie對象數組中的第一個Cookie對象。例如,要訪問一個名爲userName的Cookie對象,可使用表達式${cookie.userName}。
initParam隱式對象
EL表達式中的initParam是一個表明Web應用程序中的全部初始化參數的Map對象,每一個初始化參數的值是ServletContext.getInitParameter(String name)方法返回的字符串。
EL表達式默認是以page、request、session、application的順序來尋找EL中指定的屬性的。EL經過[ ]運算符和 . 運算符來獲取指定的屬性。
簡單來講就是有下標的使用[ ],沒下標的都用 。
${book.name}
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表達式鏈接字符串,你可能會想到使用${ 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>
網頁顯示結果: