Servlet 有兩個缺點是沒法克服的:首先,寫在 Servlet 中的全部 HTML 標籤必須包含 Java 字符串,這使得處理HTTP響應報文的工做十分繁瑣;第二,全部的文本和 HTML 標記是硬編碼,致使即便是表現層的微小變化,如改變背景顏色,也須要從新編譯。html
JavaServer Pages(JSP)解決了上述兩個問題。同時,JSP 不會取代 Servlet,相反,它們具備互補性。
JSP 頁面本質上是一個 Servlet。然而,用 JSP 頁面開發比使用 Servlet 更容易。首先,沒必要編譯 JSP 頁面;其次,JSP 頁面是一個以 jsp 爲擴展名的文本文件,可使用任何文本編輯器來編寫它們。 java
JSP 不須要添加註解或在部署描述符配置映射 URL。應用程序目錄中的每個JSP頁面能夠直接在瀏覽器中輸入路徑頁面來訪問。添加新的 JSP 界面後,無需重啓 Tomcat。apache
JSP頁面在JSP容器中運行,一個Servlet容器一般也是JSP容器。例如,Tomcat 就是一個 Servlet/JSP 容器。
當一個 JSP 頁面第一次被請求時,Servlet/JSP 容器主要作如下兩件事情:瀏覽器
1. 把 JSP 頁面轉換到 JSP 頁面實現類,該實現類是一個實現 javax.servlet.jsp.JspPage 接口或子接口 javax.servlet.jsp.HttpJspPage 的 Java 類。JspPage 是 javax.servlet.Servlet 的子接口,這使得每個 JSP 頁面都是一個 Servlet。該實現類的類名由 Servlet/JSP 容器生成。若是出現轉換錯誤,則相關錯誤信息將被髮送到客戶端。
2. 若是轉換成功,Servlet/JSP 容器隨後編譯該 Servlet 類,並裝載和實例化該類,像其餘正常的 Servlet 同樣執行生命週期操做。安全
對於同一個 JSP 頁面的後續請求,Servlet/JSP 容器會先檢查 JSP 頁面是否被修改過。若是是,則該 JSP 頁面會被從新轉換、編譯並執行。若是不是,則執行已經在內存中的 JSP Servlet。
這樣一來,一個JSP頁面的第一次調用的實際花費總比後來的花費多。session
JSP頁面能夠包含模板數據和語法元素(如:'<%'元素表示Java代碼塊的開始)。除語法元素以外的一切都是模板數據。模板數據會原樣發送給瀏覽器。例如,JSP頁面中的HTML標記和文字都是模板數據。jsp
在 Tomcat 中,welcome.jsp 頁面在第一次請求時被轉換成名爲 welcome_jsp 的 Servlet。你能夠在 Tomcat 工做目錄下的子目錄中找到生成的 Servlet,該 Servlet 繼承自 org.apache.jasper.
runtime.HttpJspBase,這是一個抽象類,它繼承自 javax.servlet.http.HttpServlet 並實現了 javax.
servlet.jsp.HttpJspPage。編輯器
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ page import="java.util.Date" %> <%@ page import="java.text.DateFormat" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Date</title> </head> <body> <% DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG); out.println(dateFormat.format(new Date())); %> </body> </html>
JSP支持兩種不一樣的註釋格式:學習
Servlet 容器會傳遞幾個對象給它運行的 Servlet。例如,能夠經過 Servlet 的 service 方法獲取 HttpServletRequest 和 HttpServletResponse 對象。在 JSP 中,能夠經過隱式對象來訪問上述對象。
編碼
pageContext 提供了上下文信息,能夠用於獲取和設置屬性(getAttribute, setAttribute)。屬性值可被存儲在4個範圍之一:頁面(JSP),請求(ServletRequest),會話(HttpSession),應用程序(ServletContext)。
public void setAttribute(String name, Object value); // page scope public Object getAttribute(String name); // page scope public void setAttribute(String name, Object value, int scope); public Object getAttribute(String name, int scope);
out 引用了一個 javax.servlet.jsp.JspWriter 對象,這相似於你在調用 HttpServletResponse 的 getWriter 方法時獲得 java.io.PrintWriter。能夠經過調用它的 print 方法將消息發送到瀏覽器。
指令指示 JSP 轉換器如何把 JSP 頁面轉換爲 Servlet。
<%@ page attribute1="value1" attribute2="value2" ... %>
attributes :
大部分 page 指令能夠出如今頁面的任何位置,但當 contentType 或 pageEncoding 屬性時,必須出如今 Java 代碼發送任何內容以前。
page 指令也能夠出現屢次,但出現屢次的指令屬性必須具備相同的值,import 屬性除外,多個包含 import 屬性的 page 指令的結果是累加的。
include 指令將其餘文件中的內容包含到當前JSP頁面。
<%@ include file="url" %>
taglib 指令引入一個自定義標籤集合的定義,包括庫路徑、自定義標籤。
<%@ taglib uri="uri" prefix="prefixOfTag" %>
腳本程序是 java 代碼塊,以"<%"符號開始,以"%>"符號結束。
Today is <% out. print(Calendar.getInstance().getTime()); %>
表達式會被JSP容器執行,並使用隱式對象 out 的打印方法輸出結果。表達式以
"<%="開始,並由"%>"結束。表達式無需分號結尾。
Today is <%= Calendar.getInstance().getTime() %>
聲明以"<%!"開始,以"%>"結束,聲明頁面中使用的變量和方法。
<%! public String getTodaysDate() { return new Date().toString(); } %> <!DOCTYPE html> <html> <head><title>Declarations</title></head> <body> Today is <%= getTodaysDate() %> </body> </html>
在 JSP 頁面中,一個聲明能夠出如今任何地方,而且一個頁面能夠有多個聲明。
可使用聲明來重寫 JSP 頁面,實現類的 init 和 destroy 方法。經過聲明 jsplnit 方法,來重寫 init 方法。經過聲明 jspDestroy 方法,來重寫 destory 方法。
注意:儘可能不要在 JSP 頁面中編寫 Java 代碼。除非應用程序只包含一個或兩個簡單的 JSP 頁面,而且永遠不會增加;不然,你應該採用模型2,它規定 JSP 頁面僅用於顯示 Java 對象中的值。
動做是第三種類型的語法元素,它們被轉換成 Java 代碼來執行操做,如訪問一個 Java 對象或調用方法。
useBean將建立一個關聯 Java 對象的腳本變量。這是早期分離表示層和業務邏輯的努力之一。隨着其餘技術的發展,如自定義標籤和表達語言,如今不多使用useBean方式。
setProperty 動做可對一個 Java 對象設置屬性,而 getProperty 則會輸出 Java 對象的一個屬性。
include 動做用來動態地引入另外一個資源。能夠引入另外一個 JSP 頁面,也能夠引入一個 Servlet 或一個靜態的 HTML 頁面。
<! DOCTYPE html> <html><head> <title>Include action</title> </head> <body> <jsp:include page="menu.jsp"> <jsp:param name="text" value="How are you?"/> </jsp:include> </body></html>
對於 include 指令,資源引入發生在頁面轉換時,即當 JSP 容器把頁面轉換爲生成的 Servlet 時。而 include 動做,資源引入發生在請求頁面時。所以,使用 include 動做是能夠傳遞參數的,而 include 指令不支持。
forward 動做把當前頁面轉向到其餘資源。
<jsp:forward page="login.jsp"> <jsp:param name="text" value="Please login"/> </jsp:forward>
用於傳遞參數。能夠經過 request.getParameter(String name) 取出參數值。
用於指定插件。
page 指令的 isErrorPage 屬性標誌一個 JSP 頁面是否爲錯誤頁面。
page 指令的 errorPage 屬性指向錯誤處理頁面。
<%-- errorHandler.jsp --%> <%@ page isErrorPage="true" %> <! DOCTYPE html><html> <head><title>Error</title></head> <body> An error has occurred.<br/> Error message: <% out.print1n(exception. toString()); %> </body></html>
<%@ page errorPage="errorHandler.jsp"%> Deliberately throw an exception <% Integer. parseInt("Throw me"); %>
參考資料:《Spring MVC 學習指南》 Paul Deck 著