JSP
此條目或其章節極大或完全地依賴於某個單一的來源。 (2019年2月24日) |
此條目包含過多行話或專業術語,可能需要簡化或提出進一步解釋。 (2016年2月22日) |
JSP(全稱Jakarta Server Pages,曾稱為JavaServer Pages)是由昇陽電腦公司主導建立的一種動態網頁技術標準。JSP部署於網路伺服器上,可以回應客戶端傳送的請求,並根據請求內容動態地生成HTML、XML或其他格式文件的Web網頁,然後返回給請求者。JSP技術以Java語言作為手稿語言,為使用者的HTTP請求提供服務,並能與伺服器上的其它Java程式共同處理複雜的業務需求。
副檔名 |
.jsp, .jspx, .jspf |
---|---|
網路媒體型式 |
application/jsp |
開發者 | Eclipse基金會 |
首次發布 | 1999年 |
最新版本 | 3.0 2020年10月21日 |
格式類型 | 動態網頁 |
標準 | JSR 245 |
免費格式? | 是 |
網站 | projects |
JSP將Java程式碼和特定變動內容嵌入到靜態的頁面中,實現以靜態頁面為模板,動態生成其中的部分內容。JSP引入了被稱為「JSP動作」的XML標籤,用來呼叫內建功能。另外,可以建立JSP標籤庫,然後像使用標準HTML或XML標籤一樣使用它們。標籤庫能增強功能和伺服器效能,而且不受跨平台問題的限制。JSP檔案在執行時會被其編譯器轉換成更原始的Servlet程式碼。JSP編譯器可以把JSP檔案編譯成用Java程式碼寫的Servlet,然後再由Java編譯器來編譯成能快速執行的二進制機器碼,也可以直接編譯成二進制碼。
綜述
此章節需要擴充。 (2018年6月17日) |
JSP從2.0版本開始,增加了表達式語言(EL),以提供更快更簡單的新增標籤的方法,並允許開發者建立Velocity式模板。如舊版本代碼「Hello, <%=request.getParameter("visitor")%>
」可簡化為「Hello, ${param.visitor}”
。
特點
- 能以模板化的方式簡單、高效地添加動態網頁內容。[1]
- 可利用JavaBean和標籤庫技術復用常用的功能代碼(設計好的組件容易實現重複利用,減少重複勞動)。標籤庫不僅帶有通用的內建標籤(JSTL),而且支援可延伸功能的自訂標籤。[1]
- 有良好的工具支援。[1]
- 繼承了Java語言的相對易用性。[1]
- 繼承了Java的跨平台優勢,實現「一次編寫,處處執行」。因為支援Java及其相關技術的開發平台多,網站開發人員可以選擇在最適合自己的系統平台上進行JSP開發;不同環境下開發的JSP專案,在所有客戶端上都能順利訪問。[1]
- 頁面中的動(控制變動內容的部分)/靜(內容不需變動的部分)區域以分散但又有序的形式組合在一起,能使人更直觀地看出頁面代碼的整體結構,也使得設計頁面效果和程式邏輯這2部分工作容易分離(外觀視圖與邏輯分離)。從而方便分配人員並行揮各自長處,實現高效地分工合作。[1]
- 可與其它企業級Java技術相互配合。JSP可以只專門負責頁面中的資料呈現,實現分層開發。[1]
包含內容
JSP指令
JSP指令控制JSP編譯器如何去生成servlet,以下是可用的指令:
- 包含指令include –包含指令通知JSP編譯器把另外一個檔案完全包含入當前檔案中。效果就好像被包含檔案的內容直接被貼上到當前檔案中一樣。這個功能和C預處理器所提供的很類似。被包含檔案的副檔名一般都是"jspf"(即JSP Fragment,JSP片段):
<%@ include file="somefile.jsp" %>
- 頁面指令page –頁面指令有以下幾個選項:
import | 使一個JAVA匯入聲明被插入到最終頁面檔案。 |
contentType | 規定了生成內容的類型。當生成非HTML內容或者當前字元集並非預設字元集時使用。 |
errorPage | 處理HTTP請求時,如果出現異常則顯示該錯誤提示資訊頁面。 |
isErrorPage | 如果設定為TRUE,則表示當前檔案是一個錯誤提示頁面。 |
isThreadSafe | 表示最終生成的servlet是否具有執行緒安全性。 |
<%@ page import="java.util.*" %> //example import导入样例
<%@ page contentType="text/html" %> //example contentType页面类型样例
<%@ page isErrorPage=false %> //example for non error page无错误页面样例
<%@ page isThreadSafe=true %> //example for a thread safe JSP执行序安全JSP样例
注意:在同一個JSP檔案中只有「import」匯入頁面指令可以被多次使用。
- 標籤庫指令taglib –標籤庫指令描述了要使用的JSP標籤庫。該指令需要指定一個字首prefix(和C++的命名空間很類似)和標籤庫的描述URI:
<%@ taglib prefix="myprefix" uri="taglib/mytag.tld" %>
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; out.println(localStackBasedVariable); %>
- 一種是表達式標籤,在JAVA SERVLET的類中放入待賦值的表達式,表達式注意不能以分號結尾。
<%= "expanded inline data " + 1 %>
JSP動作
JSP動作是一系列可以呼叫內建於網路伺服器中的功能的XML標籤。JSP提供了以下動作:
jsp:include | 和子過程類似,JAVA SERVLET暫時接管對其它指定的JSP頁的請求和回應。當處理完該JSP頁後就馬上把控制權交還當前JSP頁。這樣JSP代碼就可以在多個JSP頁中共享而不用複製。 |
jsp:param | 可以在jsp:include, jsp:forward或jsp:params塊之間使用。指定一個將加入請求的當前參陣列中的參數。 |
jsp:forward | 用於處理對另一個JSP或SERVLET的請求和回應。控制權永遠不會交還給當前JSP頁。 |
jsp:getProperty | 從指定的JavaBean中取得一個屬性值。 |
jsp:setProperty | 在指定的JavaBean中設定一個屬性值。 |
jsp:useBean | 建立或者復用一個JavaBean變數到JSP頁。 |
標籤樣例
jsp:include
<html>
<head></head>
<body>
<jsp:include page="mycommon.jsp" >
<jsp:param name="extraparam" value="myvalue" />
</jsp:include>
name:<%=request.getParameter("extraparam")%>
</body>
</html>
jsp:forward
<jsp:forward page="subpage.jsp" >
<jsp:param name="forwardedFrom" value="this.jsp" />
</jsp:forward>
在本例中,請求被傳遞到"subpage.jsp",而且請求的處理權不會再返回前者。
jsp:useBean
<jsp:useBean id="myBean" class="com.foo.MyBean" scope="request" />
<jsp:getProperty name="myBean" property="lastChanged" />
<jsp:setProperty name="myBean" property="lastChanged" 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 uri="mytaglib.tld" prefix="myprefix" %>
...
<myprefix:myaction> <%-- the start tag %>
...
</myprefix:myaction> <%-- the end tag %>
...
JSP編譯器將會載入mytaglib.tld這個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
}
在地化
模型-視圖-控制器 模式
為了把表現層(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 2.1 API的擴充而應用。Servlets和JSP最早都是由昇陽電腦開發的。從JSP1.2版本以來,JSP處於JCP開發模式下。JSR-53規定了JSP 1.2和Servlet 2.4的規範,JSR-152規定了JSP 2.0的規範。2006年5月,JSP 2.1的規範作為Java EE 5的一部份,在JSR-245中發布。
靜態資料在輸入檔案中的內容和輸出給HTTP回應的內容完全一致。此時,該JSP輸入檔案會是一個沒有內嵌JAVA或動作的HTML頁面。而且,客戶端每次請求都會得到相同的回應內容。
樣例
不管JSP編譯器是生成SERVLET的JAVA原始碼,或者是直接發布二進制碼,了解一下JSP編譯器是如何把檔案轉換成一個JAVA SERVLET,都是很有幫助的。例如,看一下如下輸入JSP和它最後生成的JAVA SERVLET:
輸入JSP
<%@ page errorPage="myerror.jsp" %>
<%@ page import="com.foo.bar" %>
<html>
<head>
<%! int serverInstanceVariable = 1;%>
...
<% int localStackBasedVariable = 1; %>
<table>
<tr><td><%= "expanded inline data " + 1 %></td></tr>
...
最後生成的JAVA SERVLET
package jsp_servlet;
import java.util.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import com.foo.bar; //imported as a result of <%@ page import="com.foo.bar" %>
import ...
class _myserlvet implements javax.servlet.Servlet, javax.servlet.jsp.HttpJspPage {
//inserted as a
//result of <%! int serverInstanceVariable = 1;%>
int serverInstanceVariable = 1;
...
public void _jspService( javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response )
throws javax.servlet.ServletException,
java.io.IOException
{
javax.servlet.ServletConfig config = ...;//get the servlet config
Object page = this;
PageContext pageContext = ...;//get the page context for this request
javax.servlet.jsp.JspWriter out = pageContext.getOut();
HttpSession session = request.getSession( true );
try {
out.print( "<html>\r\n" );
out.print( "<head>\r\n" );
...
//from <% int localStackBasedVariable = 1; %>
int localStackBasedVariable = 1;
...
out.print( "<table>\r\n" );
out.print( " <tr><td>" );
//note, toStringOrBlank() converts the expression into a string or if
// the expression is null, it uses the empty string.
//from <%= "expanded inline data " + 1 %>
out.print( toStringOrBlank( "expanded inline data " + 1 ) );
out.print( " </td></tr>\r\n" );
...
} catch ( Exception _exception ) {
//clean up and redirect to error page in <%@ page errorPage="myerror.jsp" %>
}
}
}
參見
參考資料
文內參照
書目
- Kin-man Chung. JavaServer Pages Specification (pdf) 2.3. 甲骨文公司. 2013 [2018年3月16日].
- Hans Bergsten. JavaServer Pages 3. Sebastopol, California: O'Reilly. 2003 [2006-07-20]. ISBN 0-596-00563-6. (原始內容存檔於2019-10-17).