JSP（全稱 Jakarta Server Pages，曾稱為 JavaServer Pages）是由昇陽電腦公司主導建立的一種動態網頁技術標準。JSP 部署於網路伺服器上，可以響應客戶端傳送的請求，並根據請求內容動態地生成 HTML、XML 或其他格式文件的 Web 網頁，然後返回給請求者。JSP 技術以 Java 語言作為指令碼語言，為使用者的 HTTP 請求提供服務，並能與伺服器上的其它 Java 程式共同處理複雜的業務需求。 JSP 將 Java 程式碼和特定變動內容嵌入到靜態的頁面中，實現以靜態頁面為模板，動態生成其中的部分內容。JSP 引入了被稱為 JSP 動作 的 XML 標籤，用來呼叫內建功能。另外，可以建立 JSP 標籤庫，然後像使用標準 HTML 或 XML 標籤一樣使用它們。標籤庫能增強功能和伺服器效能，而且不受跨平臺問題的限制。JSP 檔案在執行時會被其編譯器轉換成更原始的 Servlet 程式碼。JSP 編譯器可以把 JSP 檔案編譯成用 Java 程式碼寫的 Servlet，然後再由 Java 編譯器來編譯成能快速執行的二進位制機器碼，也可以直接編譯成二進位制碼。 綜述 JSP 從 20 版本開始，增加了表示式語言（EL），以提供更快更簡單的建立新標籤的方法，並允許開發者建立 Velocity 式模板。如舊版本程式碼 Hello requestgetParameter visitor 可簡化為 Hello paramvisitor。 特點 能以模板化的方式簡單、高效地新增動態網頁內容。 可利用 JavaBean 和標籤庫技術複用常用的功能程式碼（設計好的元件容易實現重複利用，減少重複勞動）。標籤庫不僅帶有通用的內建標籤（JSTL，而且支援可擴充套件功能的自定義標籤。 有良好的工具支援。 繼承了 Java 語言的相對易用性。 繼承了 Java 的跨平臺優勢，實現 一次編寫，處處執行。因為支援 Java 及其相關技術的開發平臺多，網站開發人員可以選擇在最適合自己的系統平臺上進行 JSP 開發；不同環境下開發的 JSP 專案，在所有客戶端上都能順利訪問。 頁面中的動（控制變動內容的部分）／靜（內容不需變動的部分）區域以分散但又有序的形式組合在一起，能使人更直觀地看出頁面程式碼的整體結構，也使得設計頁面效果和程式邏輯這 2 部分工作容易分離（外觀檢視與邏輯分離）。從而方便分配人員併發揮各自長處，實現高效地分工合作。 可與其它企業級 Java 技術相互配合。JSP 可以只專門負責頁面中的資料呈現，實現分層開發。 包含內容 JSP 指令 JSP 指令控制 JSP 編譯器如何去生成 servlet，以下是可用的指令： 包含指令 include 包含指令通知 JSP 編譯器把另外一個檔案完全包含入當前檔案中。效果就好像被包含檔案的內容直接被貼上到當前檔案中一樣。這個功能和 C 預處理器所提供的很類似。被包含檔案的副檔名一般都是 jspf（即 JSP Fragment，JSP 片段） include filesomefilejsp 頁面指令 page 頁面指令有以下幾個選項： import 使一個 JAVA 匯入宣告被插入到最終頁面檔案。 contentType 規定了生成內容的型別。當生成非 HTML 內容或者當前字元集並非預設字元集時使用。 errorPage 處理 HTTP 請求時，如果出現異常則顯示該錯誤提示資訊頁面。 isErrorPage 如果設定為 TRUE，則表示當前檔案是一個錯誤提示頁面。 isThreadSafe 表示最終生成的 servlet 是否具有執行緒安全性。 page importjavautil example import 匯入樣例 page contentTypetexthtml example contentType 頁面型別樣例 page isErrorPagefalse example for non error page 無錯誤頁面樣例 page isThreadSafetrue example for a thread safe JSP 執行序安全 JSP 樣例 注意：在同一個 JSP 檔案中只有 import 匯入頁面指令可以被多次使用。 標籤庫指令 taglib 標籤庫指令描述了要使用的 JSP 標籤庫。該指令需要指定一個字首 prefix（和 C 的名稱空間很類似）和標籤庫的描述 URI taglib prefixmyprefix uritaglibmytagtld JSP 指令碼元素和變數 標準指令碼變數 以下是永遠可用的指令碼變數： out：JSPWriter，用來寫入響應流的資料 page：servlet 自身 pageContext：一個 PageContext 例項包括和整個頁面相聯絡的資料，一個給定的 HTML 頁面可以在多個 JSP 之間傳遞。 request：HTTP request（請求）物件 response：HTTP response（響應）物件 session：HTTP session（服務端會話）物件 指令碼元素 有三個基本的指令碼元素，作用是使 JAVA 程式碼可以直接插入 servlet 一種是宣告標籤，在 JAVA SERVLET 的類體中放入一個變數或方法的定義。靜態的資料成員也可以如此定義。 int serverInstanceVariable 1 一種是指令碼標籤，在 JAVA SERVLET 的類的_jspService 方法中放入所包含的語句。 int localStackBasedVariable 1 outprintln localStackBasedVariable 一種是表示式標籤，在 JAVA SERVLET 的類中放入待賦值的表示式，表示式注意不能以分號結尾。 expanded inline data 1 JSP 動作 JSP 動作是一系列可以呼叫內建於網路伺服器中的功能的 XML 標籤。JSP 提供了以下動作： jspinclude 和子過程類似，JAVA SERVLET 暫時接管對其它指定的 JSP 頁的請求和響應。當處理完該 JSP 頁後就馬上把控制權交還當前 JSP 頁。這樣 JSP 程式碼就可以在多個 JSP 頁中共享而不用複製。 jspparam 可以在 jspinclude jspforward 或 jspparams 塊之間使用。指定一個將加入請求的當前引數組中的引數。 jspforward 用於處理對另一個 JSP 或 SERVLET 的請求和響應。控制權永遠不會交還給當前 JSP 頁。 jspgetProperty 從指定的 JavaBean 中獲取一個屬性值。 jspsetProperty 在指定的 JavaBean 中設定一個屬性值。 jspuseBean 建立或者複用一個 JavaBean 變數到 JSP 頁。 標籤樣例 jspinclude html headhead body jspinclude pagemycommonjsp jspparam nameextraparam valuemyvalue jspinclude namerequestgetParameter extraparam body html jspforward jspforward pagesubpagejsp jspparam nameforwardedFrom valuethisjsp jspforward 在本例中，請求被傳遞到 subpagejsp，而且請求的處理權不會再返回前者。 jspuseBean jspuseBean idmyBean classcomfooMyBean scoperequest jspgetProperty namemyBean propertylastChanged jspsetProperty namemyBean propertylastChanged value new Date scope 屬性可以是 request page session or application，它有以下用意： request 該屬性在請求的生命週期內有效，一旦請求被所有的 JSP 頁處理完後，那麼該屬性就不可引用。 page 該屬性只是當前頁中有效。 session 該屬性在使用者會話的生命週期內有效。 application 該屬性在各種情況下都有效，並且永遠不會被變為不可引用，和全域性變數 global variable 相同。 上述例子將會用一個建立一個類的例項，並且把該例項儲存在屬性中，該屬性將在該請求的生命週期內有效。它可以在所有被包含或者從主頁面（最先接收請求的頁面）轉向到的 JSP 頁之間共享。 JSP 標籤庫 除了 JSP 預定義動作之外，開發者還可以使用 JSP 標籤擴充套件 API 新增他們自定義的動作。開發者寫一種實現一個標籤的介面和一個標籤庫的 XML 描述檔案的 JAVA 類，這就能指定標籤和實現標籤的 JAVA 類 請看如下 JSP： taglib urimytaglibtld prefixmyprefix myprefixmyaction the start tag myprefixmyaction the end tag JSP 編譯器將會載入 mytaglibtld 這個 XML 檔案，然後可以看到標籤 myaction 由 JAVA 類 MyActionTag 實現。當該標籤首次在檔案中使用時，將會建立一個 MyActionTag 的例項。然後（而且當每次該標籤被使用時），當出現開始標籤時，將會呼叫 doStartTag 方法，根據開始標籤的結果，來決定如何處理標籤的主體。主體是指開始標籤和結束標籤之間的文字。這個 doStartTag 方法將會返回如下之一： SKIP_BODY 標籤之間不做處理。 EVAL_BODY_INCLUDE 對標籤之內主體進行賦值。 EVAL_BODY_TAG 對標籤之內主體進行賦值並把結果輸出到流（儲存在標籤的主體內容屬性中）。 注意：如果標籤擴充套件了 BodyTagSupport 類，當主體被執行時會在呼叫 doEndTag 之前呼叫 doAfterBody 方法。該方法用於實現迴圈結構。 當結束標籤出現時，它會呼叫 doEndTag 方法，該方法會返回如下兩做之一： EVAL_PAGE 表示 JSP 檔案的剩餘部份將會被執行。this indicates that the rest of the JSP file should be processed SKIP_PAGE 表示將不會再有更多執行操作。當前 JSP 頁交出控制權。就象在轉發動作中的作用一樣。 上述 myaction 標籤 tag 會有一個類似下面例子的用於實現的類： public class MyActionTag extends TagSupport Releases all instance variables public void release public MyActionTag called for the start tag public int doStartTag called at the end tag 本地化 JSP 的本地化是透過和 JAVA 應用程式相同的方式完成的，即使用資源包。 模型 檢視 控制器 模式 為了把表現層（presentation）從請求處理（request processing）和資料儲存（data storage）中分離開來（這樣更利於開發、查錯和功能擴充套件），昇陽公司推薦在 JSP 檔案中使用一種稱作模型 檢視 控制器（MVC）的架構模式。按照此設計，當用戶訪問網站上的特定網址時，使用者的處理請求會先由網站伺服器獲取到，然後先交由網站的控制器程式作初步處理。使用者的訪問請求可能多種多樣，比如查詢資訊或進行資料計算都是常見的網站業務。控制器程式會初步判斷使用者請求的種類，然後把使用者請求轉發給與特定業務對應的 Servlet 程式或者另一個獨立的 JSP 檔案進行業務處理。當請求處理完後，再透過一個專門負責輸出資訊的 JSP 頁以清晰、美觀的方式向用戶的瀏覽器輸出結果。簡而言之，先由控制器攔截使用者請求並做初步判斷，再由業務處理程式訪問資料（從資料庫中訪問）和處理業務，最後由檢視元件生成結果頁面併發送結果給使用者。其中 JSP 一般用作展示輸出結果，可以用於展示經 Servlet 查詢或處理後的結果；也可以用一個 JSP 檔案處理業務邏輯，再用另一個 JSP 檔案展示結果。按功能做這樣的檔案拆分（而非由一個臃腫的 JSP 頁面包攬所有功能）是為了便於團隊分工。MVC 本身是一種由來已久的設計思想，基於 JSP 的技術只是實現 MVC 架構的流行方案之一。Struts 和 Spring 框架等好幾種流行的網站建設框架都是基於 MVC 模式設計的。 JSP 和 Servlets 從架構上說，JSP 可以被看作是從 Servlets 高階提煉而作為 Java Servlet 21 API 的擴充套件而應用。Servlets 和 JSP 最早都是由昇陽電腦開發的。從 JSP12 版本以來，JSP 處於 JCP 開發模式下。JSR53 規定了 JSP 12 和 Servlet 24 的規範，JSR152 規定了 JSP 20 的規範。2006 年 5 月，JSP 21 的規範作為 Java EE 5 的一部份，在 JSR245 中釋出。 靜態資料在輸入檔案中的內容和輸出給 HTTP 響應的內容完全一致。此時，該 JSP 輸入檔案會是一個沒有內嵌 JAVA 或動作的 HTML 頁面。而且，客戶端每次請求都會得到相同的響應內容。 樣例 不管 JSP 編譯器是生成 SERVLET 的 JAVA 原始碼，或者是直接釋出二進位制碼，瞭解一下 JSP 編譯器是如何把檔案轉換成一個 JAVA SERVLET，都是很有幫助的。例如，看一下如下輸入 JSP 和它最後生成的 JAVA SERVLET： 輸入 JSP page errorPagemyerrorjsp page importcomfoobar html head int serverInstanceVariable 1 int localStackBasedVariable 1 expanded inline data 1 最後生成的 JAVA SERVLET package jsp_servlet import javautil import javaio import javaxservlet import javaxservlethttp import javaxservletjsp import javaxservletjsptagext import comfoobar imported as a result of page importcomfoobar import class _myserlvet implements javaxservletServlet javaxservletjspHttpJspPage inserted as a result of int serverInstanceVariable 1 int serverInstanceVariable 1 public void _jspService javaxservlethttpHttpServletRequest request javaxservlethttpHttpServletResponse response throws javaxservletServletException javaioIOException javaxservletServletConfig config get the servlet config Object page this PageContext pageContext get the page context for this request javaxservletjspJspWriter out pageContextgetOut HttpSession session requestgetSession true try outprint htmlrn outprint headrn from int localStackBasedVariable 1 int localStackBasedVariable 1 outprint rn outprint note toStringOrBlank converts the expression into a string or if the expression is null it uses the empty string from expanded inline data 1 outprint toStringOrBlank expanded inline data 1 outprint rn catch Exception _exception clean up and redirect to error page in page errorPagemyerrorjsp 參見 JSTL Java 企業版 JavaServer Faces Java Servlet SSJS WAR file format EAR file format JAR file format Tomcat 伺服器 參考資料 文內引用 書目 外部連結 Suns JSP product description JSR 245 JSP 21 JSR 152 JSP 20 JSR 53 JSP 12 CategoryJava 企業平臺 CategoryJava 規範請求