JSP 快速指南



JSP - 概述

什麼是 JavaServer Pages?

JavaServer Pages (JSP) 是一種用於開發支援動態內容的網頁的技術。這有助於開發人員透過使用特殊的 JSP 標籤(大多數以 <% 開頭,以 %> 結尾)在 HTML 頁面中插入 Java 程式碼。

JavaServer Pages 元件是一種型別的 Java servlet,旨在充當 Java Web 應用程式的使用者介面。Web 開發人員將 JSP 編寫為文字檔案,這些檔案結合了 HTML 或 XHTML 程式碼、XML 元素以及嵌入的 JSP 動作和命令。

使用 JSP,您可以透過網頁表單收集使用者輸入,顯示來自資料庫或其他來源的記錄,以及動態建立網頁。

JSP 標籤可用於各種目的,例如從資料庫檢索資訊或註冊使用者偏好、訪問 JavaBeans 元件、在頁面之間傳遞控制以及在請求、頁面等之間共享資訊。

為什麼要使用 JSP?

JavaServer Pages 通常與使用 **通用閘道器介面 (CGI)** 實現的程式具有相同的用途。但與 CGI 相比,JSP 提供了幾個優勢。

  • 效能顯著提高,因為 JSP 允許在 HTML 頁面本身嵌入動態元素,而不是擁有單獨的 CGI 檔案。

  • JSP 始終在伺服器處理之前進行編譯,而 CGI/Perl 則需要伺服器每次請求頁面時載入直譯器和目標指令碼。

  • JavaServer Pages 建立在 Java Servlet API 之上,因此與 Servlet 一樣,JSP 也能夠訪問所有強大的企業級 Java API,包括 **JDBC、JNDI、EJB、JAXP** 等。

  • JSP 頁面可以與處理業務邏輯的 servlet 結合使用,這是 Java servlet 模板引擎支援的模型。

最後,JSP 是 Java EE 的一部分,Java EE 是一個完整的企業級應用程式平臺。這意味著 JSP 可以參與最簡單的應用程式到最複雜和最苛刻的應用程式。

JSP 的優點

下表列出了使用 JSP 相比其他技術的其他優勢:

與 Active Server Pages (ASP) 相比

JSP 的優勢有兩方面。首先,動態部分是用 Java 編寫的,而不是 Visual Basic 或其他 MS 特定的語言,因此它更強大且更易於使用。其次,它可以移植到其他作業系統和非 Microsoft Web 伺服器。

與純 Servlet 相比

編寫(和修改!)常規 HTML 比編寫大量生成 HTML 的 println 語句更方便。

與伺服器端包含 (SSI) 相比

SSI 實際上僅用於簡單的包含,不適用於使用表單資料、建立資料庫連線等“真實”程式。

與 JavaScript 相比

JavaScript 可以在客戶端動態生成 HTML,但幾乎無法與 Web 伺服器互動以執行諸如資料庫訪問和影像處理等複雜任務。

與靜態 HTML 相比

當然,常規 HTML 不能包含動態資訊。

接下來是什麼?

我將逐步指導您設定環境以開始使用 JSP。我假設您對 Java 程式設計有很好的實踐經驗,以便繼續學習 JSP。

如果您不瞭解 Java 程式語言,那麼我們建議您瀏覽我們的 Java 教程 以瞭解 Java 程式設計。

JSP - 環境搭建

開發環境是您開發 JSP 程式、測試它們並最終執行它們的地方。

本教程將指導您設定 JSP 開發環境,這包括以下步驟:

設定 Java 開發工具包

此步驟涉及下載 Java 軟體開發工具包 (SDK) 的實現並適當地設定 PATH 環境變數。

您可以從 Oracle 的 Java 網站下載 SDK:Java SE 下載

下載 Java 實現後,請按照給定的說明安裝和配置設定。最後,設定 **PATH 和 JAVA_HOME** 環境變數以引用包含 **java** 和 **javac** 的目錄,通常分別為 **java_install_dir/bin** 和 **java_install_dir**。

如果您執行的是 Windows 並將 SDK 安裝在 **C:\jdk1.5.0_20** 中,則需要在 **C:\autoexec.bat** 檔案中新增以下行。

set PATH = C:\jdk1.5.0_20\bin;%PATH%
set JAVA_HOME = C:\jdk1.5.0_20

或者,在 **Windows NT/2000/XP** 上,您也可以右鍵單擊 **我的電腦**,選擇 **屬性**,然後選擇 **高階**,然後選擇 **環境變數**。然後,您將更新 PATH 值並按確定按鈕。

在 Unix(Solaris、Linux 等)上,如果 SDK 安裝在 **/usr/local/jdk1.5.0_20** 中並且您使用的是 C shell,則您將在 **.cshrc** 檔案中放入以下內容。

setenv PATH /usr/local/jdk1.5.0_20/bin:$PATH
setenv JAVA_HOME /usr/local/jdk1.5.0_20

或者,如果您使用 **整合開發環境 (IDE)**(如 **Borland JBuilder、Eclipse、IntelliJ IDEA** 或 **Sun ONE Studio**),請編譯並執行一個簡單的程式以確認 IDE 知道您安裝 Java 的位置。

設定 Web 伺服器:Tomcat

市場上提供許多支援 JavaServer Pages 和 Servlet 開發的 Web 伺服器。一些 Web 伺服器可以免費下載,Tomcat 就是其中之一。

Apache Tomcat 是 JavaServer Pages 和 Servlet 技術的開源軟體實現,可以充當測試 JSP 和 Servlet 的獨立伺服器,並且可以與 Apache Web 伺服器整合。以下是您在機器上設定 Tomcat 的步驟:

  • https://tomcat.apache.org/ 下載最新版本的 Tomcat。

  • 下載安裝程式後,將二進位制分發版解壓縮到一個方便的位置。例如,在 Windows 上的 **C:\apache-tomcat-5.5.29** 中,或在 Linux/Unix 上的 **/usr/local/apache-tomcat-5.5.29** 中,並建立指向這些位置的 **CATALINA_HOME** 環境變數。

可以透過在 Windows 機器上執行以下命令來啟動 Tomcat:

%CATALINA_HOME%\bin\startup.bat
 
or
 
C:\apache-tomcat-5.5.29\bin\startup.bat

可以透過在 Unix(Solaris、Linux 等)機器上執行以下命令來啟動 Tomcat:

$CATALINA_HOME/bin/startup.sh
 
or
 
/usr/local/apache-tomcat-5.5.29/bin/startup.sh

成功啟動後,可以透過訪問 **https://:8080/** 來使用 Tomcat 附帶的預設 Web 應用程式。

執行後,您將收到以下輸出:

Tomcat Home page

有關配置和執行 Tomcat 的更多資訊,請參閱此處包含的文件,以及 Tomcat 網站:https://tomcat.apache.org/

可以透過在 Windows 機器上執行以下命令來停止 Tomcat:

%CATALINA_HOME%\bin\shutdown
or

C:\apache-tomcat-5.5.29\bin\shutdown

可以透過在 Unix(Solaris、Linux 等)機器上執行以下命令來停止 Tomcat:

$CATALINA_HOME/bin/shutdown.sh

or

/usr/local/apache-tomcat-5.5.29/bin/shutdown.sh

設定 CLASSPATH

由於 servlet 不是 Java Platform Standard Edition 的一部分,因此您必須將 servlet 類識別給編譯器。

如果您執行的是 Windows,則需要在 **C:\autoexec.bat** 檔案中新增以下行。

set CATALINA = C:\apache-tomcat-5.5.29
set CLASSPATH = %CATALINA%\common\lib\jsp-api.jar;%CLASSPATH%

或者,在 **Windows NT/2000/XP** 上,您也可以右鍵單擊 **我的電腦**,選擇 **屬性**,然後選擇 **高階**,然後選擇 **環境變數**。然後,您將更新 CLASSPATH 值並按確定按鈕。

在 Unix(Solaris、Linux 等)上,如果您使用的是 C shell,則您將在 **.cshrc** 檔案中新增以下行。

setenv CATALINA = /usr/local/apache-tomcat-5.5.29
setenv CLASSPATH $CATALINA/common/lib/jsp-api.jar:$CLASSPATH

**注意** - 假設您的開發目錄是 **C:\JSPDev (Windows)** 或 **/usr/JSPDev (Unix)**,那麼您也需要將這些目錄新增到 CLASSPATH 中。

JSP - 架構

Web 伺服器需要一個 JSP 引擎,即一個容器來處理 JSP 頁面。JSP 容器負責攔截對 JSP 頁面的請求。本教程使用 Apache,它具有內建的 JSP 容器來支援 JSP 頁面的開發。

JSP 容器與 Web 伺服器一起工作,為 JSP 提供執行時環境和其他服務。它知道如何理解 JSP 中包含的特殊元素。

下圖顯示了 JSP 容器和 JSP 檔案在 Web 應用程式中的位置。

JSP Architecture

JSP 處理

以下步驟說明了 Web 伺服器如何使用 JSP 建立網頁:

  • 與普通頁面一樣,您的瀏覽器會向 Web 伺服器傳送 HTTP 請求。

  • Web 伺服器識別出 HTTP 請求是針對 JSP 頁面的,並將其轉發到 JSP 引擎。這是透過使用 URL 或 JSP 頁面完成的,該頁面以 **.jsp** 而不是 **.html** 結尾。

  • JSP 引擎從磁碟載入 JSP 頁面並將其轉換為 servlet 內容。這種轉換非常簡單,其中所有模板文字都轉換為 println( ) 語句,所有 JSP 元素都轉換為 Java 程式碼。此程式碼實現了頁面的相應動態行為。

  • JSP 引擎將 servlet 編譯為可執行類,並將原始請求轉發到 servlet 引擎。

  • Web伺服器的一部分,稱為Servlet引擎,載入Servlet類並執行它。在執行過程中,Servlet以HTML格式生成輸出。Servlet引擎在HTTP響應中將輸出進一步傳遞給Web伺服器。

  • Web伺服器將HTTP響應轉發到您的瀏覽器,將其視為靜態HTML內容。

  • 最後,Web瀏覽器處理HTTP響應中動態生成的HTML頁面,就像處理靜態頁面一樣。

所有上述步驟都可以在下圖中看到:

JSP Processing

通常,JSP引擎會檢查JSP檔案對應的Servlet是否存在,以及JSP檔案的修改日期是否早於Servlet。如果JSP檔案早於其生成的Servlet,則JSP容器假定JSP檔案沒有更改,並且生成的Servlet仍然與JSP檔案的內容匹配。這使得該過程比其他指令碼語言(如PHP)更有效率,因此速度更快。

因此,從某種意義上說,JSP頁面實際上只是編寫Servlet的另一種方式,無需成為Java程式設計高手。除了轉換階段外,JSP頁面的處理方式與普通Servlet完全相同。

JSP - 生命週期

在本章中,我們將討論JSP的生命週期。理解JSP底層功能的關鍵是瞭解它們遵循的簡單生命週期。

JSP生命週期定義為從建立到銷燬的過程。這類似於Servlet生命週期,但增加了一個步驟,即需要將JSP編譯成Servlet。

JSP遵循的路徑

以下是JSP遵循的路徑:

  • 編譯
  • 初始化
  • 執行
  • 清理

JSP生命週期的四個主要階段與Servlet生命週期非常相似。下面描述了這四個階段:

JSP Life Cycle

JSP編譯

當瀏覽器請求JSP時,JSP引擎首先檢查是否需要編譯頁面。如果頁面從未被編譯過,或者自上次編譯以來JSP檔案已被修改,則JSP引擎會編譯該頁面。

編譯過程包括三個步驟:

  • 解析JSP。
  • 將JSP轉換為Servlet。
  • 編譯Servlet。

JSP初始化

當容器載入JSP時,它會在服務任何請求之前呼叫jspInit()方法。如果您需要執行特定於JSP的初始化,請覆蓋jspInit()方法:

public void jspInit(){
   // Initialization code...
}

通常,初始化僅執行一次,並且與servlet的init方法一樣,您通常在jspInit方法中初始化資料庫連線、開啟檔案和建立查詢表。

JSP執行

JSP生命週期的這一階段表示與請求的所有互動,直到JSP被銷燬。

每當瀏覽器請求JSP並且頁面已被載入和初始化時,JSP引擎都會呼叫JSP中的_jspService()方法。

_jspService()方法以HttpServletRequestHttpServletResponse作為其引數,如下所示:

void _jspService(HttpServletRequest request, HttpServletResponse response) {
   // Service handling code...
}

JSP的_jspService()方法是根據請求呼叫的。它負責為該請求生成響應,並且該方法還負責為所有七種HTTP方法生成響應,即GET、POST、DELETE等。

JSP清理

JSP生命週期的銷燬階段表示容器正在將JSP從使用中移除。

jspDestroy()方法是Servlet的destroy方法在JSP中的等效方法。當您需要執行任何清理操作(例如釋放資料庫連線或關閉開啟的檔案)時,請覆蓋jspDestroy。

jspDestroy()方法具有以下形式:

public void jspDestroy() {
   // Your cleanup code goes here.
}

JSP - 語法

在本章中,我們將討論JSP中的語法。我們將瞭解與JSP開發相關的簡單語法(即元素)的基本用法。

JSP元素

下面描述了JSP元素:

指令碼片段

指令碼片段可以包含任意數量的JAVA語言語句、變數或方法宣告,或在頁面指令碼語言中有效的表示式。

以下是指令碼片段的語法:

<% code fragment %>

您可以將上述語法的XML等效形式寫成如下:

<jsp:scriptlet>
   code fragment
</jsp:scriptlet>

您編寫的任何文字、HTML標籤或JSP元素都必須位於指令碼片段之外。以下是JSP的簡單且第一個示例:

<html>
   <head><title>Hello World</title></head>
   
   <body>
      Hello World!<br/>
      <%
         out.println("Your IP address is " + request.getRemoteAddr());
      %>
   </body>
</html>

注意 - 假設Apache Tomcat安裝在C:\apache-tomcat-7.0.2中,並且您的環境已根據環境設定教程進行設定。

讓我們將上述程式碼儲存在名為hello.jsp的JSP檔案中,並將此檔案放在C:\apache-tomcat7.0.2\webapps\ROOT目錄中。使用URLhttps://:8080/hello.jsp瀏覽它。上述程式碼將生成以下結果:

Hello World

JSP宣告

宣告宣告一個或多個變數或方法,您可以在JSP檔案後面的Java程式碼中使用這些變數或方法。您必須在JSP檔案中使用變數或方法之前宣告它。

以下是JSP宣告的語法:

<%! declaration; [ declaration; ]+ ... %>

您可以將上述語法的XML等效形式寫成如下:

<jsp:declaration>
   code fragment
</jsp:declaration>

以下是JSP宣告的示例:

<%! int i = 0; %> 
<%! int a, b, c; %> 
<%! Circle a = new Circle(2.0); %> 

JSP表示式

JSP表示式元素包含一個被求值的指令碼語言表示式,該表示式被轉換為字串,並插入到JSP檔案中表達式出現的位置。

因為表示式的值被轉換為字串,所以您可以在文字行中使用表示式,無論它是否用HTML標記,都在JSP檔案中。

表示式元素可以包含任何根據Java語言規範有效的表示式,但您不能使用分號來結束表示式。

以下是JSP表示式的語法:

<%= expression %>

您可以將上述語法的XML等效形式寫成如下:

<jsp:expression>
   expression
</jsp:expression>

以下示例顯示了一個JSP表示式:

<html> 
   <head><title>A Comment Test</title></head> 
   
   <body>
      <p>Today's date: <%= (new java.util.Date()).toLocaleString()%></p>
   </body> 
</html> 

上述程式碼將生成以下結果:

Today's date: 11-Sep-2010 21:24:25

JSP註釋

JSP註釋標記JSP容器應忽略的文字或語句。當您想要隱藏或“註釋掉”JSP頁面的一部分時,JSP註釋很有用。

以下是JSP註釋的語法:

<%-- This is JSP comment --%>

以下示例顯示了JSP註釋:

<html> 
   <head><title>A Comment Test</title></head> 
   
   <body> 
      <h2>A Test of Comments</h2> 
      <%-- This comment will not be visible in the page source --%> 
   </body> 
</html> 

上述程式碼將生成以下結果:

A Test of Comments

在各種情況下,您可以使用少量特殊的構造來插入註釋或字元,否則這些註釋或字元將被特殊處理。以下是摘要:

序號 語法和用途
1

<%-- comment --%>

JSP註釋。被JSP引擎忽略。

2

<!-- comment -->

HTML註釋。被瀏覽器忽略。

3

<\%

表示靜態<%字面量。

4

%\>

表示靜態%>字面量。

5

\'

使用單引號的屬性中的單引號。

6

\"

使用雙引號的屬性中的雙引號。

JSP指令

JSP指令影響Servlet類的整體結構。它通常具有以下形式:

<%@ directive attribute="value" %>

指令標籤有三種類型:

序號 指令和說明
1

<%@ page ... %>

定義頁面相關的屬性,例如指令碼語言、錯誤頁面和緩衝要求。

2

<%@ include ... %>

在轉換階段包含檔案。

3

<%@ taglib ... %>

宣告一個標籤庫,其中包含在頁面中使用的自定義操作

我們將在單獨的章節JSP - 指令中解釋JSP指令

JSP操作

JSP操作使用XML語法中的構造來控制Servlet引擎的行為。您可以動態插入檔案、重用JavaBeans元件、將使用者轉發到另一個頁面或為Java外掛生成HTML。

操作元素只有一個語法,因為它符合XML標準:

<jsp:action_name attribute="value" />

操作元素基本上是預定義的函式。下表列出了可用的JSP操作:

序號 語法和用途
1

jsp:include

在請求頁面時包含檔案。

2

jsp:useBean

查詢或例項化JavaBean。

3

jsp:setProperty

設定JavaBean的屬性。

4

jsp:getProperty

將JavaBean的屬性插入輸出中。

5

jsp:forward

將請求者轉發到新頁面。

6

jsp:plugin

生成特定於瀏覽器的程式碼,為Java外掛建立OBJECT或EMBED標籤。

7

jsp:element

動態定義XML元素。

8

jsp:attribute

定義動態定義的XML元素的屬性。

9

jsp:body

定義動態定義的XML元素的主體。

10

jsp:text

用於在JSP頁面和文件中編寫模板文字。

我們將在單獨的章節JSP - 操作中解釋JSP操作

JSP隱式物件

JSP支援九個自動定義的變數,也稱為隱式物件。這些變數是:

序號 物件和說明
1

request

這是與請求關聯的HttpServletRequest物件。

2

response

這是與對客戶端的響應關聯的HttpServletResponse物件。

3

out

這是用於向客戶端傳送輸出的PrintWriter物件。

4

session

這是與請求關聯的HttpSession物件。

5

application

這是與應用程式上下文關聯的ServletContext物件。

6

config

這是與頁面關聯的ServletConfig物件。

7

pageContext

它封裝了伺服器特定功能的使用,例如更高效能的JspWriters

8

page

這僅僅是this的同義詞,用於呼叫翻譯後的Servlet類定義的方法。

9

Exception

Exception物件允許透過指定的JSP訪問異常資料。

我們將在單獨的章節JSP - 隱式物件中解釋JSP隱式物件。

控制流語句

您可以在JSP程式設計中使用Java的所有API和構建塊,包括決策語句、迴圈等。

決策語句

if...else塊的開頭像一個普通的指令碼片段,但在每一行結束時都會關閉指令碼片段,並在指令碼片段標籤之間包含HTML文字。

<%! int day = 3; %> 
<html> 
   <head><title>IF...ELSE Example</title></head> 
   
   <body>
      <% if (day == 1 || day == 7) { %>
         <p> Today is weekend</p>
      <% } else { %>
         <p> Today is not weekend</p>
      <% } %>
   </body> 
</html> 

上述程式碼將生成以下結果:

Today is not weekend

現在看一下以下switch...case塊,它使用out.println()並在指令碼片段內以稍微不同的方式編寫:

<%! int day = 3; %> 
<html> 
   <head><title>SWITCH...CASE Example</title></head> 
   
   <body>
      <% 
         switch(day) {
            case 0:
               out.println("It\'s Sunday.");
               break;
            case 1:
               out.println("It\'s Monday.");
               break;
            case 2:
               out.println("It\'s Tuesday.");
               break;
            case 3:
               out.println("It\'s Wednesday.");
               break;
            case 4:
               out.println("It\'s Thursday.");
               break;
            case 5:
               out.println("It\'s Friday.");
               break;
            default:
               out.println("It's Saturday.");
         }
      %>
   </body> 
</html> 

上述程式碼將生成以下結果:

It's Wednesday.

迴圈語句

您還可以使用Java中的三種基本型別的迴圈塊:for、while和do…while塊在您的JSP程式設計中。

讓我們看一下以下for迴圈示例:

<%! int fontSize; %> 
<html> 
   <head><title>FOR LOOP Example</title></head> 
   
   <body>
      <%for ( fontSize = 1; fontSize <= 3; fontSize++){ %>
         <font color = "green" size = "<%= fontSize %>">
            JSP Tutorial
      </font><br />
      <%}%>
   </body> 
</html> 

上述程式碼將生成以下結果:


   JSP Tutorial

JSP Tutorial
JSP Tutorial

上述示例可以使用while迴圈寫成如下:

<%! int fontSize; %> 
<html> 
   <head><title>WHILE LOOP Example</title></head> 
   
   <body>
      <%while ( fontSize <= 3){ %>
         <font color = "green" size = "<%= fontSize %>">
            JSP Tutorial
         </font><br />
         <%fontSize++;%>
      <%}%>
   </body> 
</html> 

上述程式碼將生成以下結果:


   JSP Tutorial



   JSP Tutorial



   JSP Tutorial

JSP運算子

JSP支援Java支援的所有邏輯和算術運算子。下表列出了所有運算子,其中優先順序最高的出現在表頂部,優先順序最低的出現在底部。

在一個表示式中,優先順序較高的運算子將首先被求值。

類別 運算子 結合性
字尾 () [] . (點運算子) 從左到右
一元 ++ - - ! ~ 從右到左
乘法 * / % 從左到右
加法 + - 從左到右
移位 >> >>> << 從左到右
關係 > >= < <= 從左到右
相等 == != 從左到右
按位與 & 從左到右
按位異或 ^ 從左到右
按位或 | 從左到右
邏輯與 && 從左到右
邏輯或 || 從左到右
條件 ?: 從右到左
賦值 = += -= *= /= %= >>= <<= &= ^= |= 從右到左
逗號 , 從左到右

JSP字面量

JSP表示式語言定義了以下字面量:

  • 布林型 - true 和 false

  • 整數 - 與Java相同

  • 浮點數 - 與Java相同

  • 字串 - 使用單引號和雙引號;" 被轉義為 \", ' 被轉義為 \', \ 被轉義為 \\。

  • - null

JSP - 指令

在本章中,我們將討論JSP中的指令。這些指令為容器提供方向和說明,告訴它如何處理JSP處理的某些方面。

JSP指令影響Servlet類的整體結構。它通常具有以下形式:

<%@ directive attribute = "value" %>

指令可以具有許多屬性,您可以將這些屬性列為鍵值對,並用逗號分隔。

@符號和指令名稱之間以及最後一個屬性和結束%>之間的空格是可選的。

指令標籤有三種類型:

序號 指令和說明
1

<%@ page ... %>

定義頁面相關的屬性,例如指令碼語言、錯誤頁面和緩衝要求。

2

<%@ include ... %>

在轉換階段包含檔案。

3

<%@ taglib ... %>

宣告一個標籤庫,其中包含在頁面中使用的自定義操作

JSP - page指令

page 指令用於向容器提供指令。這些指令與當前 JSP 頁面相關。您可以在 JSP 頁面的任何位置編寫 page 指令。按照慣例,page 指令寫在 JSP 頁面的頂部。

以下是 page 指令的基本語法:

<%@ page attribute = "value" %>

您可以將上述語法的XML等效形式寫成如下:

<jsp:directive.page attribute = "value" />

屬性

下表列出了與 page 指令關聯的屬性:

序號 屬性 & 用途
1

buffer

指定輸出流的緩衝模型。

2

autoFlush

控制 servlet 輸出緩衝的行為。

3

contentType

定義字元編碼方案。

4

errorPage

定義另一個 JSP 的 URL,該 JSP 報告 Java 未經檢查的執行時異常。

5

isErrorPage

指示此 JSP 頁面是否為另一個 JSP 頁面的 errorPage 屬性指定的 URL。

6

extends

指定生成的 servlet 必須擴充套件的超類。

7

import

指定 JSP 中使用的包或類的列表,就像 Java import 語句對 Java 類所做的那樣。

8

info

定義一個字串,可以透過 servlet 的 getServletInfo() 方法訪問。

9

isThreadSafe

定義生成的 servlet 的執行緒模型。

10

language

定義 JSP 頁面中使用的程式語言。

11

session

指定 JSP 頁面是否參與 HTTP 會話

12

isELIgnored

指定是否忽略 JSP 頁面中的 EL 表示式。

13

isScriptingEnabled

確定是否允許使用指令碼元素。

有關所有上述屬性的更多詳細資訊,請檢視 Page 指令

include 指令

include 指令用於在翻譯階段包含檔案。此指令告訴容器在翻譯階段將其他外部檔案的內容與當前 JSP 合併。您可以在 JSP 頁面的任何位置編寫 include 指令。

此指令的一般使用形式如下:

<%@ include file = "relative url" >

include 指令中的檔名實際上是相對 URL。如果您只指定一個檔名而不帶關聯路徑,則 JSP 編譯器會假定該檔案與您的 JSP 位於同一目錄中。

您可以將上述語法的XML等效形式寫成如下:

<jsp:directive.include file = "relative url" />

有關 include 指令的更多詳細資訊,請檢視 Include 指令

taglib 指令

JavaServer Pages API 允許您定義自定義 JSP 標記,這些標記看起來像 HTML 或 XML 標記,而標記庫是一組實現自定義行為的使用者定義標記。

taglib 指令宣告您的 JSP 頁面使用一組自定義標記,標識庫的位置,並提供識別 JSP 頁面中自定義標記的方法。

taglib 指令遵循以下語法:

<%@ taglib uri="uri" prefix = "prefixOfTag" >

這裡,uri 屬性值解析為容器理解的位置,prefix 屬性通知容器哪些標記是自定義操作。

您可以將上述語法的XML等效形式寫成如下:

<jsp:directive.taglib uri = "uri" prefix = "prefixOfTag" />

有關 taglib 指令的更多詳細資訊,請檢視 Taglib 指令

JSP - 動作

在本章中,我們將討論 JSP 中的動作。這些動作使用 XML 語法中的構造來控制 servlet 引擎的行為。您可以動態插入檔案、重用 JavaBeans 元件、將使用者轉發到另一個頁面或為 Java 外掛生成 HTML。

操作元素只有一個語法,因為它符合XML標準:

<jsp:action_name attribute = "value" />

動作元素基本上是預定義的函式。下表列出了可用的 JSP 動作:

序號 語法和用途
1

jsp:include

在請求頁面時包含檔案。

2

jsp:useBean

查詢或例項化JavaBean。

3

jsp:setProperty

設定JavaBean的屬性。

4

jsp:getProperty

將JavaBean的屬性插入輸出中。

5

jsp:forward

將請求者轉發到新頁面。

6

jsp:plugin

生成特定於瀏覽器的程式碼,為Java外掛建立OBJECT或EMBED標籤。

7

jsp:element

動態定義XML元素。

8

jsp:attribute

定義動態定義的XML元素的屬性。

9

jsp:body

定義動態定義的XML元素的主體。

10

jsp:text

用於在JSP頁面和文件中編寫模板文字。

常用屬性

所有動作元素都有兩個共同屬性:id 屬性和 scope 屬性。

Id 屬性

id 屬性唯一標識動作元素,並允許在 JSP 頁面內部引用該動作。如果動作建立了一個物件的例項,則可以使用 id 值透過隱式物件 PageContext 來引用它。

Scope 屬性

此屬性標識動作元素的生命週期。id 屬性和 scope 屬性直接相關,因為 scope 屬性決定了與 id 關聯的物件的生命週期。scope 屬性有四個可能的值:(a) page,(b) request,(c) session(d) application

<jsp:include> 動作

此動作允許您將檔案插入正在生成的頁面中。語法如下:

<jsp:include page = "relative URL" flush = "true" />

include 指令不同,後者在 JSP 頁面被翻譯成 servlet 時插入檔案,此動作在請求頁面時插入檔案。

下表列出了與 include 動作關聯的屬性:

序號 屬性 & 描述
1

page

要包含的頁面的相對 URL。

2

flush

布林屬性確定在包含包含資源之前是否將其緩衝區重新整理。

示例

讓我們定義以下兩個檔案 (a) date.jsp(b) main.jsp 如下:

以下是 date.jsp 檔案的內容:

<p>Today's date: <%= (new java.util.Date()).toLocaleString()%></p>

以下是 main.jsp 檔案的內容:

<html>
   <head>
      <title>The include Action Example</title>
   </head>
   
   <body>
      <center>
         <h2>The include action Example</h2>
         <jsp:include page = "date.jsp" flush = "true" />
      </center>
   </body>
</html>

現在讓我們將所有這些檔案儲存在根目錄中,並嘗試訪問 main.jsp。您將收到以下輸出:

The include action Example

Today's date: 12-Sep-2010 14:54:22

<jsp:useBean> 動作

useBean 動作非常通用。它首先使用 id 和 scope 變數搜尋現有物件。如果未找到物件,則嘗試建立指定的物件。

載入 bean 的最簡單方法如下:

<jsp:useBean id = "name" class = "package.class" />

載入 bean 類後,您可以使用 jsp:setPropertyjsp:getProperty 動作修改和檢索 bean 屬性。

下表列出了與 useBean 動作關聯的屬性:

序號 屬性 & 描述
1

class

指定 bean 的完整包名稱。

2

type

指定將引用物件的變數的型別。

3

beanName

給出由 java.beans.Beans 類的 instantiate() 方法指定的 bean 的名稱。

在提供與這些動作相關的有效示例之前,讓我們先討論 jsp:setPropertyjsp:getProperty 動作。

<jsp:setProperty> 動作

setProperty 動作設定 Bean 的屬性。在執行此動作之前必須先定義 Bean。有兩種基本方法可以使用 setProperty 動作:

您可以如下所示在 jsp:useBean 元素之後但在其外部使用 jsp:setProperty

<jsp:useBean id = "myName" ... />
...
<jsp:setProperty name = "myName" property = "someProperty" .../>

在這種情況下,無論是否例項化了新的 bean 或找到了現有的 bean,都會執行 jsp:setProperty

jsp:setProperty 可以出現的第二個上下文是在 jsp:useBean 元素的主體內部,如下所示:

<jsp:useBean id = "myName" ... >
   ...
   <jsp:setProperty name = "myName" property = "someProperty" .../>
</jsp:useBean>

這裡,只有在例項化了一個新物件時才會執行 jsp:setProperty,而不是在找到一個現有物件時。

下表列出了與 setProperty 動作關聯的屬性:

序號 屬性 & 描述
1

name

指定將設定其屬性的 bean。必須事先定義 Bean。

2

property

指示要設定的屬性。值“*”表示所有名稱與 bean 屬性名稱匹配的請求引數都將傳遞到相應的 setter 方法。

3

value

要分配給給定屬性的值。如果引數的值為 null 或引數不存在,則忽略 setProperty 動作。

4

param

param 屬性是要接收屬性值的請求引數的名稱。您不能同時使用 value 和 param,但允許兩者都不使用。

<jsp:getProperty> 動作

getProperty 動作用於檢索給定屬性的值並將其轉換為字串,最後將其插入輸出中。

getProperty 動作只有兩個屬性,這兩個屬性都是必需的。getProperty 動作的語法如下:

<jsp:useBean id = "myName" ... />
...
<jsp:getProperty name = "myName" property = "someProperty" .../>

下表列出了與 getProperty 動作關聯的必需屬性:

序號 屬性 & 描述
1

name

具有要檢索的屬性的 Bean 的名稱。必須事先定義 Bean。

2

property

property 屬性是要檢索的 Bean 屬性的名稱。

示例

讓我們定義一個測試 bean,該 bean 將在我們的示例中進一步使用:

/* File: TestBean.java */
package action;
 
public class TestBean {
   private String message = "No message specified";
 
   public String getMessage() {
      return(message);
   }
   public void setMessage(String message) {
      this.message = message;
   }
}

將上述程式碼編譯到生成的 TestBean.class 檔案中,並確保您將 TestBean.class 複製到 C:\apache-tomcat-7.0.2\webapps\WEB-INF\classes\action 資料夾中,並且 CLASSPATH 變數也應設定為該資料夾:

現在在 main.jsp 檔案中使用以下程式碼。這將載入 bean 並設定/獲取一個簡單的字串引數:

<html>
   
   <head>
      <title>Using JavaBeans in JSP</title>
   </head>
   
   <body>
      <center>
         <h2>Using JavaBeans in JSP</h2>
         <jsp:useBean id = "test" class = "action.TestBean" />
         <jsp:setProperty name = "test"  property = "message" 
            value = "Hello JSP..." />
            
         <p>Got message....</p>
         <jsp:getProperty name = "test" property = "message" />
      </center>
   </body>
</html>

現在讓我們嘗試訪問 main.jsp,它將顯示以下結果:

Using JavaBeans in JSP

Got message.... Hello JSP...

<jsp:forward> 動作

forward 動作終止當前頁面的操作並將請求轉發到另一個資源,例如靜態頁面、另一個 JSP 頁面或 Java Servlet。

以下是 forward 動作的語法:

<jsp:forward page = "Relative URL" />

下表列出了與 forward 動作關聯的必需屬性:

序號 屬性 & 描述
1

page

應包含另一個資源的相對 URL,例如靜態頁面、另一個 JSP 頁面或 Java Servlet。

示例

讓我們重用以下兩個檔案 (a) date.jsp(b) main.jsp 如下:

以下是 date.jsp 檔案的內容:

<p>Today's date: <%= (new java.util.Date()).toLocaleString()%></p>

以下是 main.jsp 檔案的內容:

<html>
   <head>
      <title>The include Action Example</title>
   </head>
   
   <body>
      <center>
         <h2>The include action Example</h2>
         <jsp:forward page = "date.jsp" />
      </center>
   </body>
</html>

現在讓我們將所有這些檔案儲存在根目錄中,並嘗試訪問 main.jsp。這將顯示如下所示的結果。

這裡它丟棄了主頁面中的內容,只顯示了從轉發頁面中獲取的內容。

Today's date: 12-Sep-2010 14:54:22

<jsp:plugin> 動作

plugin 動作用於將 Java 元件插入 JSP 頁面。它確定瀏覽器的型別並根據需要插入 <object><embed> 標記。

如果所需的外掛不存在,它將下載外掛,然後執行 Java 元件。Java 元件可以是 Applet 或 JavaBean。

plugin 動作有幾個屬性,對應於用於格式化 Java 元件的常用 HTML 標記。<param> 元素也可用於向 Applet 或 Bean 傳送引數。

以下是使用 plugin 動作的典型語法:

<jsp:plugin type = "applet" codebase = "dirname" code = "MyApplet.class"
   width = "60" height = "80">
   <jsp:param name = "fontcolor" value = "red" />
   <jsp:param name = "background" value = "black" />
 
   <jsp:fallback>
      Unable to initialize Java Plugin
   </jsp:fallback>
 
</jsp:plugin>

如果您有興趣,可以使用一些 applet 來嘗試此操作。一個新的元素,<fallback> 元素,可以用來指定一個錯誤字串,在元件失敗的情況下發送給使用者。

The <jsp:element> Action

The <jsp:attribute> Action

The <jsp:body> Action

<jsp:element>,<jsp:attribute><jsp:body> 動作用於動態定義 XML 元素。動態這個詞很重要,因為它意味著 XML 元素可以在請求時生成,而不是在編譯時靜態生成。

以下是一個動態定義 XML 元素的簡單示例:

<%@page language = "java" contentType = "text/html"%>
<html xmlns = "http://www.w3c.org/1999/xhtml"
   xmlns:jsp = "http://java.sun.com/JSP/Page">
   
   <head><title>Generate XML Element</title></head>
   
   <body>
      <jsp:element name = "xmlElement">
         <jsp:attribute name = "xmlElementAttr">
            Value for the attribute
         </jsp:attribute>
         
         <jsp:body>
            Body for XML element
         </jsp:body>
      
      </jsp:element>
   </body>
</html>

這將在執行時生成以下 HTML 程式碼:

<html xmlns = "http://www.w3c.org/1999/xhtml" xmlns:jsp = "http://java.sun.com/JSP/Page">
   <head><title>Generate XML Element</title></head>
   
   <body>
      <xmlElement xmlElementAttr = "Value for the attribute">
         Body for XML element
      </xmlElement>
   </body>
</html>

<jsp:text> 動作

<jsp:text> 動作可用於在 JSP 頁面和文件中編寫模板文字。以下是此操作的簡單語法:

<jsp:text>Template data</jsp:text>

模板的主體不能包含其他元素;它只能包含文字和 EL 表示式(注意 - EL 表示式將在後續章節中解釋)。請注意,在 XML 檔案中,您不能使用諸如 ${whatever > 0} 之類的表示式,因為大於號是非法的。相反,使用 gt 形式,例如 ${whatever gt 0} 或另一種方法是將值嵌入到 CDATA 部分中。

<jsp:text><![CDATA[<br>]]></jsp:text>

如果您需要包含一個DOCTYPE宣告,例如對於XHTML,您也必須使用<jsp:text>元素,如下所示:

<jsp:text><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "DTD/xhtml1-strict.dtd">]]></jsp:text>

   <head><title>jsp:text action</title></head>
   
   <body>
      <books><book><jsp:text>  
         Welcome to JSP Programming
      </jsp:text></book></books>
   </body>
</html>

嘗試使用和不使用<jsp:text>操作來執行上面的示例。

JSP - 隱式物件

在本章中,我們將討論JSP中的隱式物件。這些物件是JSP容器在每個頁面中提供給開發人員的Java物件,開發人員可以直接呼叫它們,而無需顯式宣告。JSP隱式物件也稱為預定義變數

下表列出了JSP支援的九個隱式物件:

序號 物件和說明
1

request

這是與請求關聯的HttpServletRequest物件。

2

response

這是與對客戶端的響應關聯的HttpServletResponse物件。

3

out

這是用於向客戶端傳送輸出的PrintWriter物件。

4

session

這是與請求關聯的HttpSession物件。

5

application

這是與應用程式上下文關聯的ServletContext物件。

6

config

這是與頁面關聯的ServletConfig物件。

7

pageContext

它封裝了伺服器特定功能的使用,例如更高效能的JspWriters

8

page

這僅僅是this的同義詞,用於呼叫翻譯後的Servlet類定義的方法。

9

Exception

Exception物件允許透過指定的JSP訪問異常資料。

request物件

request物件是javax.servlet.http.HttpServletRequest物件的例項。每次客戶端請求頁面時,JSP引擎都會建立一個新的物件來表示該請求。

request物件提供方法來獲取HTTP標頭資訊,包括表單資料、cookie、HTTP方法等。

我們可以在後續章節中介紹與request物件相關的一整套方法:JSP - 客戶端請求

response物件

response物件是javax.servlet.http.HttpServletResponse物件的例項。就像伺服器建立request物件一樣,它還會建立一個物件來表示對客戶端的響應。

response物件還定義了處理建立新的HTTP標頭的介面。透過此物件,JSP程式設計師可以新增新的cookie或日期戳、HTTP狀態程式碼等。

我們將在後續章節中介紹與response物件相關的一整套方法:JSP - 伺服器響應

out物件

out隱式物件是javax.servlet.jsp.JspWriter物件的例項,用於在響應中傳送內容。

根據頁面是否已緩衝,初始的JspWriter物件例項化的方式不同。可以透過使用頁面指令的buffered = 'false'屬性輕鬆關閉緩衝。

JspWriter物件包含與java.io.PrintWriter類大部分相同的方法。但是,JspWriter有一些額外的方法用於處理緩衝。與PrintWriter物件不同,JspWriter會丟擲IOExceptions

下表列出了我們將用於寫入布林值、字元、整數、雙精度數、物件、字串等的重要方法。

序號 方法及描述
1

out.print(dataType dt)

列印資料型別值

2

out.println(dataType dt)

列印資料型別值,然後用換行符終止該行。

3

out.flush()

重新整理流。

session物件

session物件是javax.servlet.http.HttpSession的例項,其行為與Java Servlet中的session物件完全相同。

session物件用於在客戶端請求之間跟蹤客戶端會話。我們將在後續章節中介紹session物件的完整用法:JSP - 會話跟蹤

application物件

application物件是生成的Servlet的ServletContext物件的直接包裝器,實際上是javax.servlet.ServletContext物件的例項。

此物件在其整個生命週期中表示JSP頁面。此物件在JSP頁面初始化時建立,並在JSP頁面被jspDestroy()方法移除時移除。

透過向application新增屬性,您可以確保構成Web應用程式的所有JSP檔案都可以訪問它。

我們將在JSP - 點選計數器章節中檢查Application物件的用法。

config物件

config物件是javax.servlet.ServletConfig的例項化,是生成的servlet的ServletConfig物件的直接包裝器。

此物件允許JSP程式設計師訪問Servlet或JSP引擎初始化引數,例如路徑或檔案位置等。

以下是您可能唯一會使用到的config方法,其用法非常簡單:

config.getServletName();

這將返回servlet名稱,即WEB-INF\web.xml檔案中定義的<servlet-name>元素中包含的字串。

pageContext物件

pageContext物件是javax.servlet.jsp.PageContext物件的例項。pageContext物件用於表示整個JSP頁面。

此物件旨在作為一種訪問頁面資訊的方式,同時避免大多數實現細節。

此物件儲存對每個請求的request和response物件的引用。application、config、session和out物件都是透過訪問此物件的屬性派生的。

pageContext物件還包含有關發出到JSP頁面的指令的資訊,包括緩衝資訊、errorPageURL和頁面範圍。

PageContext類定義了幾個欄位,包括PAGE_SCOPE、REQUEST_SCOPE、SESSION_SCOPEAPPLICATION_SCOPE,它們標識四個範圍。它還支援40多種方法,其中大約一半是從javax.servlet.jsp.JspContext類繼承的。

其中一個重要的方法是removeAttribute。此方法接受一個或兩個引數。例如,pageContext.removeAttribute ("attrName")將從所有範圍內刪除屬性,而以下程式碼僅將其從頁面範圍內刪除:

pageContext.removeAttribute("attrName", PAGE_SCOPE);

可以在JSP - 檔案上傳章節中檢視pageContext的用法。

page物件

此物件是對頁面的例項的實際引用。可以將其視為表示整個JSP頁面的物件。

page物件實際上是this物件的同義詞。

exception物件

exception物件是一個包裝器,包含從前一個頁面丟擲的異常。它通常用於生成對錯誤情況的適當響應。

我們將在JSP - 異常處理章節中介紹此物件的完整用法。

JSP - 客戶端請求

在本章中,我們將討論JSP中的客戶端請求。當瀏覽器請求網頁時,它會向Web伺服器傳送大量資訊。無法直接讀取這些資訊,因為這些資訊作為HTTP請求標頭的一部分傳輸。您可以檢視HTTP協議以獲取更多資訊。

下表列出了來自瀏覽器的重要的標頭資訊。這些資訊在Web程式設計中經常使用:

序號 標頭及描述
1

Accept

此標頭指定瀏覽器或其他客戶端可以處理的MIME型別。image/pngimage/jpeg的值是最常見的兩種可能性。

2

Accept-Charset

此標頭指定瀏覽器可以使用哪些字元集來顯示資訊。例如,ISO-8859-1

3

Accept-Encoding

此標頭指定瀏覽器知道如何處理的編碼型別。gzipcompress的值是最常見的兩種可能性。

4

Accept-Language

如果servlet可以用多種語言生成結果,則此標頭指定客戶端的首選語言。例如en、en-us、ru等。

5

Authorization

此標頭用於客戶端在訪問受密碼保護的網頁時識別自己。

6

Connection

此標頭指示客戶端是否可以處理永續性HTTP連線。永續性連線允許客戶端或其他瀏覽器使用單個請求檢索多個檔案。Keep-Alive的值表示應使用永續性連線。

7

Content-Length

此標頭僅適用於POST請求,並以位元組為單位給出POST資料的尺寸。

8

Cookie

此標頭將cookie返回給之前將其傳送到瀏覽器的伺服器。

9

Host

此標頭指定原始URL中給出的主機和埠。

10

If-Modified-Since

此標頭指示客戶端僅在指定日期之後頁面發生更改時才需要頁面。如果不存在更新的結果,伺服器將傳送程式碼304,這意味著未修改標頭。

11

If-Unmodified-Since

此標頭與If-Modified-Since相反;它指定操作僅在文件早於指定日期時才應成功。

12

Referer

此標頭指示引用網頁的URL。例如,如果您位於網頁1並點選指向網頁2的連結,則當瀏覽器請求網頁2時,網頁1的URL將包含在Referer標頭中。

13

User-Agent

此標頭標識發出請求的瀏覽器或其他客戶端,可用於向不同型別的瀏覽器返回不同的內容。

HttpServletRequest物件

request物件是javax.servlet.http.HttpServletRequest物件的例項。每次客戶端請求頁面時,JSP引擎都會建立一個新的物件來表示該請求。

request物件提供方法來獲取HTTP標頭資訊,包括表單資料、cookie、HTTP方法等。

下表列出了可用於在JSP程式中讀取HTTP標頭的重要方法。這些方法可用於表示客戶端對Web伺服器請求的HttpServletRequest物件。

序號 方法及描述
1

Cookie[] getCookies()

返回一個包含客戶端隨此請求傳送的所有Cookie物件的陣列。

2

Enumeration getAttributeNames()

返回一個包含此請求可用的屬性名稱的列舉。

3

Enumeration getHeaderNames()

返回此請求包含的所有標頭名稱的列舉。

4

Enumeration getParameterNames()

返回一個包含此請求中包含的引數名稱的String物件的列舉。

5

HttpSession getSession()

返回與此請求關聯的當前會話,或者如果請求沒有會話,則建立一個新的會話。

6

HttpSession getSession(boolean create)

返回與此請求關聯的當前HttpSession,或者如果不存在當前會話且create為true,則返回一個新的會話。

7

Locale getLocale()

根據Accept-Language標頭返回客戶端將接受內容的首選Locale。

8

Object getAttribute(String name)

返回值為指定名稱的屬性,如果不存在給定名稱的屬性,則返回null。

9

ServletInputStream getInputStream()

使用ServletInputStream檢索請求的主體作為二進位制資料。

10

String getAuthType()

返回用於保護servlet的身份驗證方案的名稱,例如“BASIC”或“SSL”,或者如果JSP未受保護,則返回null。

11

String getCharacterEncoding()

返回在此請求主體中使用的字元編碼的名稱。

12

String getContentType()

返回請求主體的MIME型別,或者如果型別未知,則返回null。

13

String getContextPath()

返回請求URI中指示請求上下文的片段。

14

String getHeader(String name)

返回值為指定請求標頭的值。

15

String getMethod()

返回發出此請求的HTTP方法的名稱,例如GET、POST或PUT。

16

String getParameter(String name)

返回值為請求引數的值,或者如果引數不存在,則返回null。

17

String getPathInfo()

返回客戶端在發出此請求時傳送的 URL 中關聯的任何額外路徑資訊。

18

String getProtocol()

返回請求使用的協議的名稱和版本。

19

String getQueryString()

返回請求 URL 中路徑之後包含的查詢字串。

20

String getRemoteAddr()

返回傳送請求的客戶端的網際網路協議 (IP) 地址。

21

String getRemoteHost()

返回傳送請求的客戶端的完全限定域名。

22

String getRemoteUser()

如果使用者已透過身份驗證,則返回發出此請求的使用者的登入名;如果使用者未透過身份驗證,則返回 null。

23

String getRequestURI()

返回此請求的 URL 中從協議名稱到 HTTP 請求第一行中的查詢字串的部分。

24

String getRequestedSessionId()

返回客戶端指定的會話 ID。

25

String getServletPath()

返回此請求的 URL 中呼叫 JSP 的部分。

26

String[] getParameterValues(String name)

返回一個包含給定請求引數的所有值的 String 物件陣列,如果引數不存在,則返回 null。

27

boolean isSecure()

返回一個布林值,指示此請求是否使用安全通道(例如 HTTPS)發出。

28

int getContentLength()

返回請求正文的長度(以位元組為單位),並透過輸入流提供,如果長度未知,則返回 -1。

29

int getIntHeader(String name)

將指定請求頭的值作為 int 返回。

30

int getServerPort()

返回接收此請求的埠號。

HTTP 頭請求示例

以下示例使用 HttpServletRequestgetHeaderNames() 方法讀取 HTTP 頭資訊。此方法返回一個包含與當前 HTTP 請求關聯的頭資訊的列舉。

獲得列舉後,我們可以以標準方式迴圈遍歷列舉。我們將使用 hasMoreElements() 方法確定何時停止,並使用 nextElement() 方法獲取每個引數名稱的名稱。

<%@ page import = "java.io.*,java.util.*" %>

<html>
   <head>
      <title>HTTP Header Request Example</title>
   </head>

   <body>
      <center>
         <h2>HTTP Header Request Example</h2>
         
         <table width = "100%" border = "1" align = "center">
            <tr bgcolor = "#949494">
               <th>Header Name</th>
               <th>Header Value(s)</th>
            </tr>
            <%
               Enumeration headerNames = request.getHeaderNames();
               while(headerNames.hasMoreElements()) {
                  String paramName = (String)headerNames.nextElement();
                  out.print("<tr><td>" + paramName + "</td>\n");
                  String paramValue = request.getHeader(paramName);
                  out.println("<td> " + paramValue + "</td></tr>\n");
               }
            %>
         </table>
      </center>
   
   </body>
</html>

現在讓我們將上述程式碼放入 main.jsp 中並嘗試訪問它。

HTTP 頭請求示例

頭名稱 頭值
accept */*
accept-language en-us
user-agent Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; InfoPath.2; MS-RTC LM 8)
accept-encoding gzip, deflate
host localhost:8080
connection Keep-Alive
cache-control no-cache

您可以嘗試以類似的方式處理所有方法。

JSP - 伺服器響應

在本章中,我們將討論 JSP 中的伺服器響應。當 Web 伺服器響應 HTTP 請求時,響應通常包含狀態行、一些響應頭、空行和文件。典型的響應如下所示:

HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
   (Blank Line)
<!doctype ...>

<html>
   <head>...</head>
   <body>
      ...
   </body>
</html>

狀態行由 HTTP 版本(示例中為 HTTP/1.1)、狀態程式碼(示例中為 200)和與狀態程式碼相對應的一條非常簡短的訊息(示例中為 OK)組成。

以下是返回到瀏覽器中從 Web 伺服器返回的最有用的 HTTP 1.1 響應頭的摘要。這些標頭在 Web 程式設計中經常使用:

序號 標頭及描述
1

Allow

此標頭指定伺服器支援的請求方法(GET、POST 等)。

2

Cache-Control

此標頭指定可以安全快取響應文件的情況。它可以具有值public、privateno-cache 等。Public 表示文件可快取,Private 表示文件僅供單個使用者使用,並且只能儲存在私有(非共享)快取中,no-cache 表示文件永遠不應快取。

3

Connection

此標頭指示瀏覽器是否使用永續性 HTTP 連線。值為 close 指示瀏覽器不使用永續性 HTTP 連線,keep-alive 表示使用永續性連線。

4

Content-Disposition

此標頭允許您請求瀏覽器要求使用者將響應儲存到具有給定名稱的檔案的磁碟中。

5

Content-Encoding

此標頭指定在傳輸過程中頁面編碼的方式。

6

Content-Language

此標頭表示文件的書寫語言。例如,en、en-us、ru 等。

7

Content-Length

此標頭指示響應中的位元組數。只有當瀏覽器使用永續性 (keep-alive) HTTP 連線時,才需要此資訊。

8

Content-Type

此標頭提供響應文件的MIME多用途網際網路郵件擴充套件)型別。

9

Expires

此標頭指定內容應被視為過時且不再快取的時間。

10

Last-Modified

此標頭指示文件上次更改的時間。然後,客戶端可以快取文件並在以後的請求中透過 If-Modified-Since 請求頭提供日期。

11

Location

此標頭應包含在所有具有 300 多狀態程式碼的響應中。這會通知瀏覽器文件地址。瀏覽器會自動重新連線到此位置並檢索新文件。

12

Refresh

此標頭指定瀏覽器應請求更新頁面的時間。您可以指定頁面重新整理後的秒數。

13

Retry-After

此標頭可以與 503(服務不可用)響應一起使用,以告訴客戶端它可以何時重複其請求。

14

Set-Cookie

此標頭指定與頁面關聯的 Cookie。

HttpServletResponse 物件

響應物件是 javax.servlet.http.HttpServletResponse 物件的例項。就像伺服器建立請求物件一樣,它還會建立一個物件來表示對客戶端的響應。

響應物件還定義了用於建立新 HTTP 標頭的介面。透過此物件,JSP 程式設計師可以新增新的 Cookie 或日期戳、HTTP 狀態程式碼等。

以下方法可用於在 servlet 程式中設定 HTTP 響應頭。這些方法可用於 HttpServletResponse 物件。此物件表示伺服器響應。

序號 方法及描述
1

String encodeRedirectURL(String url)

對指定的 URL 進行編碼,以便在 sendRedirect 方法中使用,或者如果不需要編碼,則返回未更改的 URL。

2

String encodeURL(String url)

透過在其中包含會話 ID 對指定的 URL 進行編碼,或者如果不需要編碼,則返回未更改的 URL。

3

boolean containsHeader(String name)

返回一個布林值,指示是否已設定命名響應頭。

4

boolean isCommitted()

返回一個布林值,指示響應是否已提交。

5

void addCookie(Cookie cookie)

將指定的 Cookie 新增到響應中。

6

void addDateHeader(String name, long date)

新增一個具有給定名稱和日期值的響應頭。

7

void addHeader(String name, String value)

新增一個具有給定名稱和值的響應頭。

8

void addIntHeader(String name, int value)

新增一個具有給定名稱和整數值的響應頭。

9

void flushBuffer()

強制將緩衝區中的任何內容寫入客戶端。

10

void reset()

清除緩衝區中存在的任何資料以及狀態程式碼和標頭。

11

void resetBuffer()

清除響應中底層緩衝區的內容,而不清除標頭或狀態程式碼。

12

void sendError(int sc)

使用指定的狀態程式碼向客戶端傳送錯誤響應,並清除緩衝區。

13

void sendError(int sc, String msg)

使用指定的狀態向客戶端傳送錯誤響應。

14

void sendRedirect(String location)

使用指定的重定向位置 URL 向客戶端傳送臨時重定向響應。

15

void setBufferSize(int size)

設定響應正文的首選緩衝區大小。

16

void setCharacterEncoding(String charset)

設定傳送到客戶端的響應的字元編碼(MIME 字元集),例如 UTF-8。

17

void setContentLength(int len)

設定響應中內容正文的長度在 HTTP servlet 中;此方法還會設定 HTTP Content-Length 標頭。

18

void setContentType(String type)

設定傳送到客戶端的響應的內容型別,如果響應尚未提交。

19

void setDateHeader(String name, long date)

設定一個具有給定名稱和日期值的響應頭。

20

void setHeader(String name, String value)

設定一個具有給定名稱和值的響應頭。

21

void setIntHeader(String name, int value)

設定一個具有給定名稱和整數值的響應頭。

22

void setLocale(Locale loc)

設定響應的區域設定,如果響應尚未提交。

23

void setStatus(int sc)

設定此響應的狀態程式碼。

HTTP 頭響應示例

以下示例將使用 setIntHeader() 方法設定 Refresh 標頭以模擬數字時鐘:

<%@ page import = "java.io.*,java.util.*" %>

<html>
   
   <head>
      <title>Auto Refresh Header Example</title>
   </head>
   
   <body>
      <center>
         <h2>Auto Refresh Header Example</h2>
         <%
            // Set refresh, autoload time as 5 seconds
            response.setIntHeader("Refresh", 5);
            
            // Get current time
            Calendar calendar = new GregorianCalendar();
            
            String am_pm;
            int hour = calendar.get(Calendar.HOUR);
            int minute = calendar.get(Calendar.MINUTE);
            int second = calendar.get(Calendar.SECOND);
            
            if(calendar.get(Calendar.AM_PM) == 0) 
               am_pm = "AM";
            else
               am_pm = "PM";
               String CT = hour+":"+ minute +":"+ second +" "+ am_pm;
               out.println("Current Time is: " + CT + "\n");
         %>
      </center>
   
   </body>
</html>

現在將上述程式碼放入 main.jsp 中並嘗試訪問它。這將每 5 秒顯示一次當前系統時間,如下所示。執行 JSP。您將收到以下輸出:

Auto Refresh Header Example

Current Time is: 9:44:50 PM

您可以嘗試以類似的方式處理其他方法。

JSP - HTTP 狀態碼

在本章中,我們將討論 JSP 中的 HTTP 狀態程式碼。HTTP 請求和 HTTP 響應訊息的格式類似,將具有以下結構:

  • 初始狀態行 + CRLF(回車 + 換行,即換行)

  • 零個或多個標頭行 + CRLF

  • 空行,即 CRLF

  • 可選的訊息正文,如檔案、查詢資料或查詢輸出。

例如,伺服器響應頭如下所示:

HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
   (Blank Line)
<!doctype ...>

<html>
   <head>...</head>
   
   <body>
      ...
   </body>
</html>

狀態行由 HTTP 版本(示例中為 HTTP/1.1)、狀態程式碼(示例中為 200)和與狀態程式碼相對應的一條非常簡短的訊息(示例中為 OK)組成。

下表列出了 Web 伺服器可能返回的 HTTP 狀態程式碼和關聯訊息:

程式碼 訊息 描述
100 100 伺服器僅接收了請求的一部分,但只要未被拒絕,客戶端就應繼續發出請求。
101 101 伺服器切換協議。
200 200 請求成功。
201 201 請求已完成,並建立了一個新資源。
202 202 請求已接受處理,但處理尚未完成。
203 203
204 無內容。
205 伺服器已成功處理請求,但未返回任何內容,並且希望客戶端重置其文件檢視。
206 伺服器已成功處理了部分 GET 請求。
300 Multiple Choices 連結列表;使用者可以選擇一個連結並轉到該位置。最多五個地址。
301 Moved Permanently 請求的頁面已永久移動到新的 URL。
302 Found 請求的頁面已臨時移動到新的 URL。
303 See Other 請求的頁面可以在不同的 URL 下找到。
304 請求的資源未修改。
305 請求的資源必須透過代理訪問。
306 Unused 此程式碼在早期版本中使用過。它不再使用,但該程式碼已保留。
307 請求的資源已臨時移動到不同的 URL,並且客戶端應繼續使用相同的請求方法進行重定向。 請求的頁面已臨時移動到新的 URL。
400 Bad Request 伺服器不理解請求。
401 Unauthorized 請求的頁面需要使用者名稱和密碼。
402 Payment Required 您尚不能使用此程式碼。
403 Forbidden 禁止訪問請求的頁面。
404 Not Found 伺服器找不到請求的頁面。
405 Method Not Allowed 請求中指定的方法不允許。
406 Not Acceptable 伺服器只能生成客戶端不接受的響應。
407 Proxy Authentication Required 在提供此請求之前,您必須對代理伺服器進行身份驗證。
408 Request Timeout 請求花費的時間超過了伺服器準備等待的時間。
409 Conflict 由於衝突,無法完成請求。
410 Gone 請求的頁面不再可用。
411 長度要求 "Content-Length" 未定義。伺服器在沒有此欄位的情況下不會接受請求。
412 前提條件失敗 伺服器評估請求中給定的前提條件為假。
413 請求實體過大 伺服器不會接受請求,因為請求實體過大。
414 請求URL過長 伺服器不會接受請求,因為URL過長。當您將"post"請求轉換為帶有長查詢資訊的"get"請求時,就會發生這種情況。
415 不支援的媒體型別 伺服器不會接受請求,因為不支援媒體型別。
417 期望失敗
500 內部伺服器錯誤 請求未完成。伺服器遇到了意外情況。
501 未實現 請求未完成。伺服器不支援所需的功能。
502 錯誤閘道器 請求未完成。伺服器從上游伺服器收到了無效的響應。
503 服務不可用 請求未完成。伺服器暫時過載或宕機。
504 閘道器超時 閘道器超時。
505 不支援的HTTP版本 伺服器不支援"http協議"版本。

設定HTTP狀態碼的方法

以下方法可用於在servlet程式中設定HTTP狀態碼。這些方法可透過HttpServletResponse物件使用。

序號 方法及描述
1

public void setStatus ( int statusCode )

此方法設定任意狀態碼。setStatus方法以int(狀態碼)作為引數。如果您的響應包含特殊狀態碼和文件,請確保在使用PrintWriter實際返回任何內容之前呼叫setStatus

2

public void sendRedirect(String url)

此方法生成302響應以及一個Location標頭,其中提供了新文件的URL。

3

public void sendError(int code, String message)

此方法傳送狀態碼(通常為404)以及一條簡短訊息,該訊息會自動格式化為HTML文件併發送到客戶端。

HTTP狀態碼示例

以下示例顯示如何將407錯誤程式碼傳送到客戶端瀏覽器。之後,瀏覽器將顯示"需要身份驗證!!!"訊息。

<html>
   <head>
      <title>Setting HTTP Status Code</title>
   </head>
   
   <body>
      <%
         // Set error code and reason.
         response.sendError(407, "Need authentication!!!" );
      %>
   </body>
</html>

您將收到以下輸出:

HTTP Status 407 - Need authentication!!!

type Status report

message Need authentication!!!

description The client must first authenticate itself with the proxy (Need authentication!!!).

Apache Tomcat/5.5.29

要更熟悉HTTP狀態碼,請嘗試設定不同的狀態碼及其描述。

JSP - 表單處理

在本章中,我們將討論JSP中的表單處理。您肯定遇到過許多需要將一些資訊從瀏覽器傳遞到Web伺服器,最終傳遞到後端程式的情況。瀏覽器使用兩種方法將此資訊傳遞到Web伺服器。這些方法是GET方法和POST方法。

表單處理中的方法

現在讓我們討論表單處理中的方法。

GET方法

GET方法傳送附加到頁面請求的編碼使用者資訊。頁面和編碼資訊由?字元分隔,如下所示:

http://www.test.com/hello?key1=value1&key2=value2

GET方法是將資訊從瀏覽器傳遞到Web伺服器的預設方法,它會生成一個出現在瀏覽器位置:框中的長字串。建議最好不要使用GET方法,如果您需要將密碼或其他敏感資訊傳遞到伺服器。

GET方法有大小限制:請求字串中只能包含1024個字元

此資訊使用QUERY_STRING標頭傳遞,可以透過QUERY_STRING環境變數訪問,可以使用請求物件的getQueryString()getParameter()方法進行處理。

POST方法

將資訊傳遞到後端程式的更可靠的方法通常是POST方法。

此方法以與GET方法完全相同的方式打包資訊,但它不是將其作為文字字串附加到URL中的?之後傳送,而是將其作為單獨的訊息傳送。此訊息以標準輸入的形式到達後端程式,您可以對其進行解析並用於處理。

JSP使用getParameter()方法處理此類請求以讀取簡單引數,並使用getInputStream()方法讀取來自客戶端的二進位制資料流。

使用JSP讀取表單資料

JSP根據情況自動處理表單資料解析,使用以下方法:

  • getParameter() - 您呼叫request.getParameter()方法獲取表單引數的值。

  • getParameterValues() - 如果引數出現多次並返回多個值,例如複選框,則呼叫此方法。

  • getParameterNames() - 如果您想要當前請求中所有引數的完整列表,則呼叫此方法。

  • getInputStream() - 呼叫此方法讀取來自客戶端的二進位制資料流。

使用URL的GET方法示例

以下URL將使用GET方法將兩個值傳遞給HelloForm程式。

https://:8080/main.jsp?first_name=ZARA&last_name=ALI

以下是處理Web瀏覽器提供的輸入的main.jsp JSP程式。我們將使用getParameter()方法,這使得訪問傳遞的資訊變得非常容易:

<html>
   <head>
      <title>Using GET Method to Read Form Data</title>
   </head>
   
   <body>
      <h1>Using GET Method to Read Form Data</h1>
      <ul>
         <li><p><b>First Name:</b>
            <%= request.getParameter("first_name")%>
         </p></li>
         <li><p><b>Last  Name:</b>
            <%= request.getParameter("last_name")%>
         </p></li>
      </ul>
   
   </body>
</html>

現在在瀏覽器的位置:框中輸入https://:8080/main.jsp?first_name=ZARA&last_name=ALI。這將生成以下結果:

使用GET方法讀取表單資料

  • 名字:ZARA

  • 姓氏:ALI

使用表單的GET方法示例

以下是一個使用HTML表單和提交按鈕傳遞兩個值的示例。我們將使用相同的JSP main.jsp來處理此輸入。

<html>
   <body>
      
      <form action = "main.jsp" method = "GET">
         First Name: <input type = "text" name = "first_name">
         <br />
         Last Name: <input type = "text" name = "last_name" />
         <input type = "submit" value = "Submit" />
      </form>
      
   </body>
</html>

將此HTML儲存在名為Hello.htm的檔案中,並將其放在<Tomcat-安裝目錄>/webapps/ROOT目錄中。當您訪問https://:8080/Hello.htm時,您將收到以下輸出。

名字
姓氏
< p>嘗試輸入名字和姓氏,然後單擊提交按鈕以檢視Tomcat正在執行的本地計算機上的結果。根據提供的輸入,它將生成與上述示例類似的結果。

使用表單的POST方法示例

讓我們對上述JSP進行一些修改以處理GET和POST方法。以下是處理Web瀏覽器使用GET或POST方法提供的輸入的main.jsp JSP程式。

實際上,上述JSP沒有變化,因為傳遞引數的唯一方式發生了變化,並且沒有二進位制資料被傳遞到JSP程式。與檔案處理相關的概念將在單獨的章節中解釋,在這些章節中我們需要讀取二進位制資料流。

<html>
   <head>
      <title>Using GET and POST Method to Read Form Data</title>
   </head>
   
   <body>
      <center>
      <h1>Using POST Method to Read Form Data</h1>
      
      <ul>
         <li><p><b>First Name:</b>
            <%= request.getParameter("first_name")%>
         </p></li>
         <li><p><b>Last  Name:</b>
            <%= request.getParameter("last_name")%>
         </p></li>
      </ul>
   
   </body>
</html>

以下是Hello.htm檔案的內容:

<html>
   <body>
      
      <form action = "main.jsp" method = "POST">
         First Name: <input type = "text" name = "first_name">
         <br />
         Last Name: <input type = "text" name = "last_name" />
         <input type = "submit" value = "Submit" />
      </form>
      
   </body>
</html>

現在讓我們將main.jsp和hello.htm放在<Tomcat-安裝目錄>/webapps/ROOT目錄中。當您訪問https://:8080/Hello.htm時,您將收到以下輸出。

名字
姓氏

嘗試輸入名字和姓氏,然後單擊提交按鈕以檢視Tomcat正在執行的本地計算機上的結果。

根據提供的輸入,您將收到與上述示例類似的結果。

將複選框資料傳遞到JSP程式

當需要選擇多個選項時,使用複選框。

以下是帶有兩個複選框的表單的示例HTML程式碼,CheckBox.htm

<html>
   <body>
      
      <form action = "main.jsp" method = "POST" target = "_blank">
         <input type = "checkbox" name = "maths" checked = "checked" /> Maths
         <input type = "checkbox" name = "physics"  /> Physics
         <input type = "checkbox" name = "chemistry" checked = "checked" /> Chemistry
         <input type = "submit" value = "Select Subject" />
      </form>
      
   </body>
</html>

上述程式碼將生成以下結果:

數學物理化學

以下是處理Web瀏覽器為複選框按鈕提供的輸入的main.jsp JSP程式。

<html>
   <head>
      <title>Reading Checkbox Data</title>
   </head>
   
   <body>
      <h1>Reading Checkbox Data</h1>
      
      <ul>
         <li><p><b>Maths Flag:</b>
            <%= request.getParameter("maths")%>
         </p></li>
         <li><p><b>Physics Flag:</b>
            <%= request.getParameter("physics")%>
         </p></li>
         <li><p><b>Chemistry Flag:</b>
            <%= request.getParameter("chemistry")%>
         </p></li>
      </ul>
   
   </body>
</html>

上述程式將生成以下結果:

Reading Checkbox Data

  • Maths Flag :: on

  • Physics Flag:: null

  • Chemistry Flag:: on

讀取所有表單引數

以下是一個通用示例,它使用HttpServletRequest的getParameterNames()方法讀取所有可用的表單引數。此方法返回一個Enumeration,其中包含引數名稱,但順序未指定。

獲得Enumeration後,我們可以使用標準方式遍歷Enumeration,使用hasMoreElements()方法確定何時停止,並使用nextElement()方法獲取每個引數名稱。

<%@ page import = "java.io.*,java.util.*" %>

<html>
   <head>
      <title>HTTP Header Request Example</title>
   </head>

   <body>
      <center>
         <h2>HTTP Header Request Example</h2>
         <table width = "100%" border = "1" align = "center">
            <tr bgcolor = "#949494">
               <th>Param Name</th>
               <th>Param Value(s)</th>
            </tr>
            <%
               Enumeration paramNames = request.getParameterNames();
               while(paramNames.hasMoreElements()) {
                  String paramName = (String)paramNames.nextElement();
                  out.print("<tr><td>" + paramName + "</td>\n");
                  String paramValue = request.getHeader(paramName);
                  out.println("<td> " + paramValue + "</td></tr>\n");
               }
            %>
         </table>
      </center>
   
   </body>
</html>

以下是Hello.htm的內容:

<html>
   <body>
      
      <form action = "main.jsp" method = "POST" target = "_blank">
         <input type = "checkbox" name = "maths" checked = "checked" /> Maths
         <input type = "checkbox" name = "physics"  /> Physics
         <input type = "checkbox" name = "chemistry" checked = "checked" /> Chem
         <input type = "submit" value = "Select Subject" />
      </form>
   
   </body>
</html>

現在嘗試使用上述Hello.htm呼叫JSP;這將根據提供的輸入生成類似於以下的結果:

讀取所有表單引數

引數名稱 引數值(s)
數學 開啟
化學 開啟

您可以嘗試使用上述JSP讀取任何其他表單的資料,這些表單包含其他物件,例如文字框、單選按鈕或下拉列表等。

JSP - 過濾器

在本章中,我們將討論JSP中的過濾器。Servlet和JSP過濾器是Java類,可以在Servlet和JSP程式設計中用於以下目的:

  • 在客戶端訪問後端資源之前攔截來自客戶端的請求。

  • 在伺服器將響應傳送回客戶端之前操作響應。

規範建議有各種型別的過濾器:

  • 身份驗證過濾器
  • 資料壓縮過濾器
  • 加密過濾器
  • 觸發資源訪問事件的過濾器
  • 影像轉換過濾器
  • 日誌記錄和審計過濾器
  • MIME-TYPE鏈過濾器
  • 標記化過濾器
  • 轉換XML內容的XSL/T過濾器

過濾器部署在部署描述符檔案web.xml中,然後對映到應用程式部署描述符中的servlet或JSP名稱或URL模式。部署描述符檔案web.xml可以在<Tomcat-安裝目錄>\conf目錄中找到。

當JSP容器啟動您的Web應用程式時,它會建立您在部署描述符中宣告的每個過濾器的例項。過濾器按其在部署描述符中宣告的順序執行。

Servlet過濾器方法

過濾器只是一個實現javax.servlet.Filter介面的Java類。javax.servlet.Filter介面定義了三種方法:

序號 方法及描述
1

public void doFilter (ServletRequest, ServletResponse, FilterChain)

每次由於客戶端對鏈末端資源的請求而透過鏈傳遞請求/響應對時,容器都會呼叫此方法。

2

public void init(FilterConfig filterConfig)

Web容器呼叫此方法以指示過濾器正在被投入使用。

3

public void destroy()

Web容器呼叫此方法以指示過濾器正在被停止使用。

JSP過濾器示例

以下示例顯示瞭如何每次訪問任何JSP檔案時列印客戶端的IP地址和當前日期時間。此示例將為您提供對JSP過濾器的基本瞭解,但您可以使用相同的概念編寫更復雜的過濾器應用程式:

// Import required java libraries
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
 
// Implements Filter class
public class LogFilter implements Filter  {
   public void  init(FilterConfig config) throws ServletException {
      // Get init parameter 
      String testParam = config.getInitParameter("test-param"); 
 
      //Print the init parameter 
      System.out.println("Test Param: " + testParam); 
   }
   public void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
      throws java.io.IOException, ServletException {
      
      // Get the IP address of client machine.   
      String ipAddress = request.getRemoteAddr();
      
      // Log the IP address and current timestamp.
      System.out.println("IP "+ ipAddress + ", Time "+ new Date().toString());
      
      // Pass request back down the filter chain
      chain.doFilter(request,response);
   }
   public void destroy( ) {
      /* Called before the Filter instance is removed 
      from service by the web container*/
   }
}

以通常的方式編譯LogFilter.java,並將您的LogFilter.class檔案放在<Tomcat-安裝目錄>/webapps/ROOT/WEB-INF/classes中。

Web.xml中的JSP過濾器對映

過濾器定義後,對映到URL或JSP檔名,這與Servlet定義後對映到URL模式的方式非常相似,在web.xml檔案中。在部署描述符檔案web.xml中建立以下過濾器標籤條目

<filter>
   <filter-name>LogFilter</filter-name>
   <filter-class>LogFilter</filter-class>
   
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>

<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

上述過濾器將應用於所有servlet和JSP,因為我們在配置中指定了/*。如果您只想對少數servlet或JSP應用過濾器,則可以指定特定的servlet或JSP路徑。

現在嘗試呼叫任何servlet或JSP,您將在Web伺服器日誌中看到生成的日誌。您可以使用Log4J記錄器將上述日誌記錄到單獨的檔案中。

使用多個過濾器

您的 Web 應用程式可能定義了幾個具有特定用途的不同過濾器。例如,您定義了兩個過濾器AuthenFilterLogFilter。除了需要建立如下所述的不同對映之外,其餘過程將保持與上面解釋的相同。

<filter>
   <filter-name>LogFilter</filter-name>
   <filter-class>LogFilter</filter-class>
   
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>
 
<filter>
   <filter-name>AuthenFilter</filter-name>
   <filter-class>AuthenFilter</filter-class>
   <init-param>
      <param-name>test-param</param-name>
      <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>
 
<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
 
<filter-mapping>
   <filter-name>AuthenFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

過濾器應用程式順序

web.xml 中過濾器對映元素的順序決定了 Web 容器將過濾器應用於 servlet 或 JSP 的順序。要反轉過濾器的順序,您只需要反轉web.xml檔案中的過濾器對映元素即可。

例如,上面的示例將首先應用 LogFilter,然後將其應用於任何 servlet 或 JSP;下面的示例將反轉順序:

<filter-mapping>
   <filter-name>AuthenFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
 
<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

JSP - 處理 Cookie

在本章中,我們將討論 JSP 中的 Cookie 處理。Cookie 是儲存在客戶端計算機上的文字檔案,它們用於各種資訊跟蹤目的。JSP 使用底層的 servlet 技術透明地支援 HTTP Cookie。

識別和返回使用者涉及三個步驟:

  • 伺服器指令碼向瀏覽器傳送一組 Cookie。例如,名稱、年齡或識別號等。

  • 瀏覽器將此資訊儲存在本地機器上以供將來使用。

  • 當瀏覽器下次向 Web 伺服器傳送任何請求時,它會將這些 Cookie 資訊傳送到伺服器,伺服器使用這些資訊來識別使用者,或者可能用於其他目的。

本章將教您如何使用 JSP 程式設定或重置 Cookie、如何訪問它們以及如何刪除它們。

Cookie 的結構

Cookie 通常設定在 HTTP 標頭中(儘管 JavaScript 也可以直接在瀏覽器上設定 Cookie)。設定 Cookie 的 JSP 可能傳送如下所示的標頭:

HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name = xyz; expires = Friday, 04-Feb-07 22:03:38 GMT; 
   path = /; domain = tutorialspoint.com
Connection: close
Content-Type: text/html

如您所見,Set-Cookie 標頭包含名稱值對、GMT 日期、路徑。名稱和值將進行 URL 編碼。expires欄位是指示瀏覽器在給定的時間和日期後“忘記”Cookie 的指令。

如果瀏覽器配置為儲存 Cookie,則它會將此資訊保留到過期日期。如果使用者將瀏覽器指向與 Cookie 的路徑和域匹配的任何頁面,它將重新發送 Cookie 到伺服器。瀏覽器的標頭可能如下所示:

GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.6 (X11; I; Linux 2.2.6-15apmac ppc)
Host: zink.demon.co.uk:1126

Accept: image/gif, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Cookie: name = xyz

然後,JSP 指令碼可以透過請求方法request.getCookies()訪問 Cookie,該方法返回一個Cookie物件的陣列。

Servlet Cookie 方法

下表列出了與 Cookie 物件相關的一些有用方法,您可以在 JSP 中操作 Cookie 時使用這些方法:

序號 方法及描述
1

public void setDomain(String pattern)

此方法設定 Cookie 應用到的域;例如,tutorialspoint.com。

2

public String getDomain()

此方法獲取 Cookie 應用到的域;例如,tutorialspoint.com。

3

public void setMaxAge(int expiry)

此方法設定 Cookie 過期前應經過多長時間(以秒為單位)。如果您不設定此值,則 Cookie 將僅持續當前會話。

4

public int getMaxAge()

此方法返回 Cookie 的最大年齡(以秒為單位),預設值為-1,表示 Cookie 將持續到瀏覽器關閉。

5

public String getName()

此方法返回 Cookie 的名稱。建立後無法更改名稱。

6

public void setValue(String newValue)

此方法設定與 Cookie 關聯的值。

7

public String getValue()

此方法獲取與 Cookie 關聯的值。

8

public void setPath(String uri)

此方法設定此 Cookie 應用到的路徑。如果您未指定路徑,則 Cookie 將返回當前頁面以及所有子目錄中所有 URL。

9

public String getPath()

此方法獲取此 Cookie 應用到的路徑。

10

public void setSecure(boolean flag)

此方法設定布林值,指示 Cookie 是否應僅透過加密(即 SSL)連線傳送。

11

public void setComment(String purpose)

此方法指定描述 Cookie 目的的註釋。如果瀏覽器將 Cookie 顯示給使用者,則註釋很有用。

12

public String getComment()

此方法返回描述此 Cookie 目的的註釋,如果 Cookie 沒有註釋,則返回 null。

使用 JSP 設定 Cookie

使用 JSP 設定 Cookie 涉及三個步驟:

步驟 1:建立 Cookie 物件

您使用 Cookie 名稱和 Cookie 值(兩者均為字串)呼叫 Cookie 建構函式。

Cookie cookie = new Cookie("key","value");

請記住,名稱和值都不應包含空格或以下任何字元:

[ ] ( ) = , " / ? @ : ;

步驟 2:設定最大年齡

您使用setMaxAge指定 Cookie 應有效多長時間(以秒為單位)。以下程式碼將設定 Cookie 24 小時。

cookie.setMaxAge(60*60*24); 

步驟 3:將 Cookie 傳送到 HTTP 響應標頭

您使用response.addCookie在 HTTP 響應標頭中新增 Cookie,如下所示

response.addCookie(cookie);

示例

讓我們修改我們的表單示例以設定姓氏和名字的 Cookie。

<%
   // Create cookies for first and last names.      
   Cookie firstName = new Cookie("first_name", request.getParameter("first_name"));
   Cookie lastName = new Cookie("last_name", request.getParameter("last_name"));
   
   // Set expiry date after 24 Hrs for both the cookies.
   firstName.setMaxAge(60*60*24); 
   lastName.setMaxAge(60*60*24); 
   
   // Add both the cookies in the response header.
   response.addCookie( firstName );
   response.addCookie( lastName );
%>

<html>
   <head>
      <title>Setting Cookies</title>
   </head>
   
   <body>
      <center>
         <h1>Setting Cookies</h1>
      </center>
      <ul>
         <li><p><b>First Name:</b>
            <%= request.getParameter("first_name")%>
         </p></li>
         <li><p><b>Last  Name:</b>
            <%= request.getParameter("last_name")%>
         </p></li>
      </ul>
   
   </body>
</html>

讓我們將上述程式碼放在main.jsp檔案中,並在以下 HTML 頁面中使用它:

<html>
   <body>
      
      <form action = "main.jsp" method = "GET">
         First Name: <input type = "text" name = "first_name">
         <br />
         Last Name: <input type = "text" name = "last_name" />
         <input type = "submit" value = "Submit" />
      </form>
      
   </body>
</html>

將上述 HTML 內容儲存在hello.jsp檔案中,並將hello.jspmain.jsp放在<Tomcat-安裝目錄>/webapps/ROOT目錄中。當您訪問https://:8080/hello.jsp時,以下是上述表單的實際輸出。

名字
姓氏

嘗試輸入名字和姓氏,然後單擊提交按鈕。這將在螢幕上顯示名字和姓氏,並設定兩個 CookiefirstNamelastName。下次單擊提交按鈕時,這些 Cookie 將被傳回伺服器。

在下一節中,我們將解釋如何在 Web 應用程式中訪問這些 Cookie。

使用 JSP 讀取 Cookie

要讀取 Cookie,您需要透過呼叫HttpServletRequestgetCookies( )方法建立一個javax.servlet.http.Cookie物件的陣列。然後遍歷陣列,並使用getName()getValue()方法訪問每個 Cookie 和關聯的值。

示例

現在讓我們讀取在上一個示例中設定的 Cookie:

<html>
   <head>
      <title>Reading Cookies</title>
   </head>
   
   <body>
      <center>
         <h1>Reading Cookies</h1>
      </center>
      <%
         Cookie cookie = null;
         Cookie[] cookies = null;
         
         // Get an array of Cookies associated with the this domain
         cookies = request.getCookies();
         
         if( cookies != null ) {
            out.println("<h2> Found Cookies Name and Value</h2>");
            
            for (int i = 0; i < cookies.length; i++) {
               cookie = cookies[i];
               out.print("Name : " + cookie.getName( ) + ",  ");
               out.print("Value: " + cookie.getValue( )+" <br/>");
            }
         } else {
            out.println("<h2>No cookies founds</h2>");
         }
      %>
   </body>
   
</html>

現在讓我們將上述程式碼放在main.jsp檔案中並嘗試訪問它。如果您將first_name Cookie設定為“John”,將last_name Cookie設定為“Player”,則執行https://:8080/main.jsp將顯示以下結果:

Found Cookies Name and Value

Name : first_name, Value: John

Name : last_name, Value: Player

使用 JSP 刪除 Cookie

刪除 Cookie 非常簡單。如果您想刪除 Cookie,則只需執行以下三個步驟:

  • 讀取已存在的 Cookie 並將其儲存在 Cookie 物件中。

  • 使用setMaxAge()方法將 Cookie 年齡設定為零以刪除現有 Cookie。

  • 將此 Cookie 添加回響應標頭。

示例

以下示例將向您展示如何刪除名為“first_name”的現有 Cookie,以及下次執行 main.jsp JSP 時,它將為 first_name 返回 null 值。

<html>
   <head>
      <title>Reading Cookies</title>
   </head>
   
   <body>
      <center>
         <h1>Reading Cookies</h1>
      </center>
      <%
         Cookie cookie = null;
         Cookie[] cookies = null;
         
         // Get an array of Cookies associated with the this domain
         cookies = request.getCookies();
         
         if( cookies != null ) {
            out.println("<h2> Found Cookies Name and Value</h2>");
            
            for (int i = 0; i < cookies.length; i++) {
               cookie = cookies[i];
               
               if((cookie.getName( )).compareTo("first_name") == 0 ) {
                  cookie.setMaxAge(0);
                  response.addCookie(cookie);
                  out.print("Deleted cookie: " + 
                  cookie.getName( ) + "<br/>");
               }
               out.print("Name : " + cookie.getName( ) + ",  ");
               out.print("Value: " + cookie.getValue( )+" <br/>");
            }
         } else {
            out.println(
            "<h2>No cookies founds</h2>");
         }
      %>
   </body>
   
</html>

現在讓我們將上述程式碼放在main.jsp檔案中並嘗試訪問它。它將顯示以下結果:

Cookies Name and Value

Deleted cookie : first_name

Name : first_name, Value: John

Name : last_name, Value: Player

現在再次執行https://:8080/main.jsp,它應該只顯示一個 Cookie,如下所示:

Found Cookies Name and Value

Name : last_name, Value: Player

您可以在 Internet Explorer 中手動刪除 Cookie。從“工具”選單開始,然後選擇“Internet 選項”。要刪除所有 Cookie,請單擊“刪除 Cookie”按鈕。

JSP - 會話跟蹤

在本章中,我們將討論 JSP 中的會話跟蹤。HTTP 是一種“無狀態”協議,這意味著每次客戶端檢索網頁時,客戶端都會開啟與 Web 伺服器的單獨連線,並且伺服器不會自動保留任何先前客戶端請求的記錄。

維護 Web 客戶端和伺服器之間的會話

現在讓我們討論一些在 Web 客戶端和 Web 伺服器之間維護會話的選項:

Cookie

Web 伺服器可以為每個 Web 客戶端分配一個唯一的會話 ID 作為 Cookie,並且對於客戶端的後續請求,可以使用接收到的 Cookie 識別它們。

這可能不是一種有效的方法,因為瀏覽器有時不支援 Cookie。不建議使用此過程來維護會話。

隱藏表單欄位

Web 伺服器可以傳送一個隱藏的 HTML 表單欄位以及一個唯一的會話 ID,如下所示:

<input type = "hidden" name = "sessionid" value = "12345">

此條目表示,當提交表單時,指定的名稱和值將自動包含在GETPOST資料中。每次 Web 瀏覽器傳送請求時,session_id值可用於跟蹤不同的 Web 瀏覽器。

這可能是跟蹤會話的一種有效方法,但單擊常規(<A HREF...>)超文字連結不會導致表單提交,因此隱藏表單欄位也不能支援常規會話跟蹤。

URL 重寫

您可以在每個 URL 的末尾附加一些額外的資料。此資料標識會話;伺服器可以將該會話識別符號與其儲存的有關該會話的資料相關聯。

例如,對於https://tutorialspoint.tw/file.htm;sessionid=12345,會話識別符號附加為sessionid = 12345,可以在 Web 伺服器上訪問以識別客戶端。

URL 重寫是維護會話的一種更好方法,並且在瀏覽器不支援 Cookie 時對瀏覽器有效。這裡的缺點是您必須動態生成每個 URL 以分配會話 ID,即使頁面是一個簡單的靜態 HTML 頁面。

session物件

除了上述選項之外,JSP 還利用 servlet 提供的 HttpSession 介面。此介面提供了一種跨以下方面識別使用者的方法。

  • 一個頁面請求或
  • 訪問網站或
  • 儲存有關該使用者的資訊

預設情況下,JSP 已啟用會話跟蹤,並且會為每個新的客戶端自動例項化一個新的 HttpSession 物件。停用會話跟蹤需要透過將頁面指令 session 屬性顯式設定為 false 來關閉它,如下所示:

<%@ page session = "false" %>

JSP 引擎透過隱式session物件向 JSP 作者公開 HttpSession 物件。由於session物件已提供給 JSP 程式設計師,因此程式設計師可以立即開始從物件中儲存和檢索資料,而無需任何初始化或getSession()

以下是透過 session 物件可用的重要方法摘要:

序號 方法及描述
1

public Object getAttribute(String name)

此方法返回在此會話中與指定名稱繫結的物件,如果名稱下沒有繫結任何物件,則返回 null。

2

public Enumeration getAttributeNames()

此方法返回一個 String 物件的 Enumeration,其中包含繫結到此會話的所有物件的名稱。

3

public long getCreationTime()

此方法返回建立此會話的時間,以 1970 年 1 月 1 日午夜以來的毫秒數表示(格林威治標準時間)。

4

public String getId()

此方法返回一個字串,其中包含分配給此會話的唯一識別符號。

5

public long getLastAccessedTime()

此方法返回客戶端上次傳送與此會話關聯的請求的時間,以 1970 年 1 月 1 日午夜以來的毫秒數表示(格林威治標準時間)。

6

public int getMaxInactiveInterval()

此方法返回 servlet 容器在客戶端訪問之間保持此會話開啟的最大時間間隔(以秒為單位)。

7

public void invalidate()

此方法使此會話無效,並取消繫結與其繫結的任何物件。

8

public boolean isNew()

如果客戶端尚不知道該會話或客戶端選擇不加入該會話,則此方法返回 true。

9

public void removeAttribute(String name)

此方法從此會話中刪除與指定名稱繫結的物件。

10

public void setAttribute(String name, Object value)

此方法使用指定的名稱將物件繫結到此會話。

11

public void setMaxInactiveInterval(int interval)

此方法指定客戶端請求之間的時間(以秒為單位),在此時間之後,servlet 容器將使此會話無效。

會話跟蹤示例

此示例描述瞭如何使用 HttpSession 物件查詢會話的建立時間和上次訪問時間。如果不存在會話,我們將與請求關聯一個新的會話。

<%@ page import = "java.io.*,java.util.*" %>
<%
   // Get session creation time.
   Date createTime = new Date(session.getCreationTime());
   
   // Get last access time of this Webpage.
   Date lastAccessTime = new Date(session.getLastAccessedTime());

   String title = "Welcome Back to my website";
   Integer visitCount = new Integer(0);
   String visitCountKey = new String("visitCount");
   String userIDKey = new String("userID");
   String userID = new String("ABCD");

   // Check if this is new comer on your Webpage.
   if (session.isNew() ){
      title = "Welcome to my website";
      session.setAttribute(userIDKey, userID);
      session.setAttribute(visitCountKey,  visitCount);
   } 
   visitCount = (Integer)session.getAttribute(visitCountKey);
   visitCount = visitCount + 1;
   userID = (String)session.getAttribute(userIDKey);
   session.setAttribute(visitCountKey,  visitCount);
%>

<html>
   <head>
      <title>Session Tracking</title>
   </head>
   
   <body>
      <center>
         <h1>Session Tracking</h1>
      </center>
      
      <table border = "1" align = "center"> 
         <tr bgcolor = "#949494">
            <th>Session info</th>
            <th>Value</th>
         </tr> 
         <tr>
            <td>id</td>
            <td><% out.print( session.getId()); %></td>
         </tr> 
         <tr>
            <td>Creation Time</td>
            <td><% out.print(createTime); %></td>
         </tr> 
         <tr>
            <td>Time of Last Access</td>
            <td><% out.print(lastAccessTime); %></td>
         </tr> 
         <tr>
            <td>User ID</td>
            <td><% out.print(userID); %></td>
         </tr> 
         <tr>
            <td>Number of visits</td>
            <td><% out.print(visitCount); %></td>
         </tr> 
      </table> 
   
   </body>
</html>

現在將以上程式碼放入 **main.jsp** 中,並嘗試訪問 **https://:8080/main.jsp**。執行 URL 後,您將收到以下結果:

歡迎訪問我的網站

會話資訊

會話資訊 value
ID 0AE3EC93FF44E3C525B4351B77ABB2D5
建立時間 2010 年 6 月 8 日星期二 17:26:40 GMT+04:00
上次訪問時間 2010 年 6 月 8 日星期二 17:26:40 GMT+04:00
使用者 ID ABCD
訪問次數 0

現在嘗試第二次執行相同的 JSP,您將收到以下結果。

歡迎再次訪問我的網站

會話資訊

資訊型別 value
ID 0AE3EC93FF44E3C525B4351B77ABB2D5
建立時間 2010 年 6 月 8 日星期二 17:26:40 GMT+04:00
上次訪問時間 2010 年 6 月 8 日星期二 17:26:40 GMT+04:00
使用者 ID ABCD
訪問次數 1

刪除會話資料

完成使用者會話資料後,您有以下幾種選擇:

  • **刪除特定屬性** - 您可以呼叫 **public void removeAttribute(String name)** 方法來刪除與特定鍵關聯的值。

  • **刪除整個會話** - 您可以呼叫 **public void invalidate()** 方法來丟棄整個會話。

  • **設定會話超時** - 您可以呼叫 **public void setMaxInactiveInterval(int interval)** 方法為每個會話單獨設定超時。

  • **登出使用者** - 支援 servlet 2.4 的伺服器,您可以呼叫 **logout** 將客戶端登出 Web 伺服器並使屬於所有使用者的全部會話失效。

  • **web.xml 配置** - 如果您使用的是 Tomcat,除了上述方法外,您還可以按如下方式在 web.xml 檔案中配置會話超時。

<session-config>
   <session-timeout>15</session-timeout>
</session-config>

超時以分鐘為單位表示,並覆蓋 Tomcat 中的預設超時(30 分鐘)。

servlet 中的 **getMaxInactiveInterval( )** 方法以秒為單位返回該會話的超時時間段。因此,如果您的會話在 web.xml 中配置為 15 分鐘,則 **getMaxInactiveInterval( )** 返回 900。

JSP - 檔案上傳

在本節中,我們將討論 JSP 中的檔案上傳。JSP 可以與 HTML 表單標籤一起使用,允許使用者將檔案上傳到伺服器。上傳的檔案可以是文字檔案、二進位制檔案、影像檔案或任何文件。

建立檔案上傳表單

現在讓我們瞭解如何建立檔案上傳表單。以下 HTML 程式碼建立了一個上傳表單。以下是要注意的重要事項:

  • 表單的 **method** 屬性應設定為 **POST** 方法,不能使用 GET 方法。

  • 表單的 **enctype** 屬性應設定為 **multipart/form-data**。

  • 表單的 **action** 屬性應設定為一個 JSP 檔案,該檔案將在後端伺服器處理檔案上傳。以下示例使用 **uploadFile.jsp** 程式檔案上傳檔案。

  • 要上傳單個檔案,您應該使用單個 **<input .../>** 標籤,其屬性 **type = "file"**。要允許上傳多個檔案,請包含多個 input 標籤,併為 name 屬性提供不同的值。瀏覽器為每個標籤關聯一個“瀏覽”按鈕。

<html>
   <head>
      <title>File Uploading Form</title>
   </head>
   
   <body>
      <h3>File Upload:</h3>
      Select a file to upload: <br />
      <form action = "UploadServlet" method = "post"
         enctype = "multipart/form-data">
         <input type = "file" name = "file" size = "50" />
         <br />
         <input type = "submit" value = "Upload File" />
      </form>
   </body>
   
</html>

這將顯示以下結果。您現在可以從本地 PC 選擇一個檔案,當用戶點選“上傳檔案”時,表單將與所選檔案一起提交:

File Upload

Select a file to upload −



**注意** - 以上表單只是一個虛擬表單,無法工作,您應該在您的機器上嘗試以上程式碼才能使其工作。

編寫後端 JSP 指令碼

現在讓我們定義一個上傳檔案將儲存的位置。您可以在程式中硬編碼此位置,或者也可以使用外部配置(例如 web.xml 中的 **context-param** 元素)新增此目錄名稱,如下所示:

<web-app>
....
<context-param> 
   <description>Location to store uploaded file</description> 
   <param-name>file-upload</param-name> 
   <param-value>
      c:\apache-tomcat-5.5.29\webapps\data\
   </param-value> 
</context-param>
....
</web-app>

以下是 **UploadFile.jsp** 的原始碼。它可以一次處理多個檔案的上傳。在繼續上傳檔案之前,讓我們考慮以下幾點。

  • 以下示例依賴於 **FileUpload**;確保您的類路徑中包含最新版本的 **commons-fileupload.x.x.jar** 檔案。您可以從 https://commons.apache.org/fileupload/ 下載它。

  • FileUpload 依賴於 Commons IO;確保您的類路徑中包含最新版本的 **commons-io-x.x.jar** 檔案。您可以從 https://commons.apache.org/io/ 下載它。

  • 在測試以下示例時,您應該上傳大小小於 maxFileSize 的檔案,否則檔案將無法上傳。

  • 確保您已提前建立了 **c:\temp** 和 **c:\apache-tomcat5.5.29\webapps\data** 目錄。

<%@ page import = "java.io.*,java.util.*, javax.servlet.*" %>
<%@ page import = "javax.servlet.http.*" %>
<%@ page import = "org.apache.commons.fileupload.*" %>
<%@ page import = "org.apache.commons.fileupload.disk.*" %>
<%@ page import = "org.apache.commons.fileupload.servlet.*" %>
<%@ page import = "org.apache.commons.io.output.*" %>

<%
   File file ;
   int maxFileSize = 5000 * 1024;
   int maxMemSize = 5000 * 1024;
   ServletContext context = pageContext.getServletContext();
   String filePath = context.getInitParameter("file-upload");

   // Verify the content type
   String contentType = request.getContentType();
   
   if ((contentType.indexOf("multipart/form-data") >= 0)) {
      DiskFileItemFactory factory = new DiskFileItemFactory();
      // maximum size that will be stored in memory
      factory.setSizeThreshold(maxMemSize);
      
      // Location to save data that is larger than maxMemSize.
      factory.setRepository(new File("c:\\temp"));

      // Create a new file upload handler
      ServletFileUpload upload = new ServletFileUpload(factory);
      
      // maximum file size to be uploaded.
      upload.setSizeMax( maxFileSize );
      
      try { 
         // Parse the request to get file items.
         List fileItems = upload.parseRequest(request);

         // Process the uploaded file items
         Iterator i = fileItems.iterator();

         out.println("<html>");
         out.println("<head>");
         out.println("<title>JSP File upload</title>");  
         out.println("</head>");
         out.println("<body>");
         
         while ( i.hasNext () ) {
            FileItem fi = (FileItem)i.next();
            if ( !fi.isFormField () ) {
               // Get the uploaded file parameters
               String fieldName = fi.getFieldName();
               String fileName = fi.getName();
               boolean isInMemory = fi.isInMemory();
               long sizeInBytes = fi.getSize();
            
               // Write the file
               if( fileName.lastIndexOf("\\") >= 0 ) {
                  file = new File( filePath + 
                  fileName.substring( fileName.lastIndexOf("\\"))) ;
               } else {
                  file = new File( filePath + 
                  fileName.substring(fileName.lastIndexOf("\\")+1)) ;
               }
               fi.write( file ) ;
               out.println("Uploaded Filename: " + filePath + 
               fileName + "<br>");
            }
         }
         out.println("</body>");
         out.println("</html>");
      } catch(Exception ex) {
         System.out.println(ex);
      }
   } else {
      out.println("<html>");
      out.println("<head>");
      out.println("<title>Servlet upload</title>");  
      out.println("</head>");
      out.println("<body>");
      out.println("<p>No file uploaded</p>"); 
      out.println("</body>");
      out.println("</html>");
   }
%>

現在嘗試使用上面建立的 HTML 表單上傳檔案。當您嘗試 **https://:8080/UploadFile.htm** 時,它將顯示以下結果。這將幫助您從本地機器上傳任何檔案。

File Upload

Select a file to upload −


如果您的 JSP 指令碼執行良好,則您的檔案應上傳到 **c:\apache-tomcat5.5.29\webapps\data\** 目錄。

JSP - 處理日期

在本節中,我們將討論如何在 JSP 中處理資料。使用 JSP 的最重要的優勢之一是您可以使用核心 Java 中的所有可用方法。我們將向您介紹 **java.util** 包中提供的 **Date** 類;此類封裝了當前日期和時間。

Date 類支援兩個建構函式。第一個建構函式使用當前日期和時間初始化物件。

Date( )

以下建構函式接受一個引數,該引數等於自 1970 年 1 月 1 日午夜以來的毫秒數。

Date(long millisec)

一旦您擁有一個 Date 物件,您就可以呼叫以下任何支援方法來處理日期:

序號 方法和描述
1

boolean after(Date date)

如果呼叫 Date 物件包含的日期晚於 date 指定的日期,則返回 true,否則返回 false。

2

boolean before(Date date)

如果呼叫 Date 物件包含的日期早於 date 指定的日期,則返回 true,否則返回 false。

3

Object clone( )

複製呼叫 Date 物件。

4

int compareTo(Date date)

將呼叫物件的 value 與 date 的 value 進行比較。如果值相等,則返回 0。如果呼叫物件早於 date,則返回負值。如果呼叫物件晚於 date,則返回正值。

5

int compareTo(Object obj)

如果 obj 是 Date 類,則與 compareTo(Date) 的操作相同。否則,它將丟擲 ClassCastException。

6

boolean equals(Object date)

如果呼叫 Date 物件包含與 date 指定的日期和時間相同的時間和日期,則返回 true,否則返回 false。

7

long getTime( )

返回自 1970 年 1 月 1 日以來的毫秒數。

8

int hashCode( )

返回呼叫物件的雜湊碼。

9

void setTime(long time)

設定由 time 指定的時間和日期,time 表示自 1970 年 1 月 1 日午夜以來的毫秒數

10

String toString( )

將呼叫 Date 物件轉換為字串並返回結果。

獲取當前日期和時間

使用 JSP 程式,獲取當前日期和時間非常容易。您可以使用帶有 **toString()** 方法的簡單 Date 物件來列印當前日期和時間,如下所示:

<%@ page import = "java.io.*,java.util.*, javax.servlet.*" %>

<html>
   <head>
      <title>Display Current Date & Time</title>
   </head>
   
   <body>
      <center>
         <h1>Display Current Date & Time</h1>
      </center>
      <%
         Date date = new Date();
         out.print( "<h2 align = \"center\">" +date.toString()+"</h2>");
      %>
   </body>
</html>

現在讓我們將程式碼儲存在 **CurrentDate.jsp** 中,然後使用 URL **https://:8080/CurrentDate.jsp** 呼叫此 JSP。您將收到以下結果:

Display Current Date & Time

Mon Jun 21 21:46:49 GMT+04:00 2010

使用 **URL https://:8080/CurrentDate.jsp** 重新整理頁面。每次重新整理時,您都會發現秒數不同。

日期比較

如前幾節所述,您可以在 JSP 指令碼中使用所有可用的 Java 方法。如果您需要比較兩個日期,請考慮以下方法:

  • 您可以使用 **getTime( )** 方法獲取兩個物件自 1970 年 1 月 1 日午夜以來的毫秒數,然後比較這兩個值。

  • 您可以使用 **before( ), after( )** 和 **equals( )** 方法,例如,因為月中的第 12 天早於第 18 天,所以 **new Date(99, 2, 12).before(new Date (99, 2, 18))** 返回 true。

  • 您可以使用 **compareTo( )** 方法;此方法由 **Comparable 介面** 定義並由 Date 實現。

使用 SimpleDateFormat 格式化日期

SimpleDateFormat 是一個用於以區域感知方式格式化和解析日期的具體類。SimpleDateFormat 允許您首先選擇任何使用者定義的日期時間格式模式。

讓我們修改上面的示例,如下所示:

<%@ page import = "java.io.*,java.util.*" %>
<%@ page import = "javax.servlet.*,java.text.*" %>

<html>
   <head>
      <title>Display Current Date & Time</title>
   </head>
   
   <body>
      <center>
         <h1>Display Current Date & Time</h1>
      </center>
      <%
         Date dNow = new Date( );
         SimpleDateFormat ft = 
         new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
         out.print( "<h2 align=\"center\">" + ft.format(dNow) + "</h2>");
      %>
   </body>
</html>

再次編譯以上 servlet,然後使用 URL **https://:8080/CurrentDate** 呼叫此 servlet。您將收到以下結果:

Display Current Date & Time

Mon 2010.06.21 at 10:06:44 PM GMT+04:00

SimpleDateFormat 格式程式碼

要指定時間格式,請使用時間模式字串。在此模式中,所有 ASCII 字母都保留為模式字母,其定義如下:

字元 描述 示例
G 時代指示符 公元
y 四位數年份 2001
M 月份 七月或 07
d 0
h 上午/下午小時(1~12) 2
H 一天中的小時(0~23) 22
m 分鐘 30
s 55
S 毫秒 234
E 星期幾 星期二
D 一年中的第幾天 360
F 一個月中的第幾個星期幾 2(七月中的第二個星期三)
w 一年中的第幾周 40
W 一個月中的第幾周
a 上午/下午標記 下午
k 一天中的小時(1~24) 24
K 上午/下午小時(0~11) 0
z 時區 東部標準時間
' 轉義文字 分隔符
" 單引號 `

有關可用於操作日期的完整常量方法列表,您可以參考標準 Java 文件。

JSP - 頁面重定向

在本節中,我們將討論使用JSP進行頁面重定向。頁面重定向通常用於文件移動到新位置,我們需要將客戶端傳送到此新位置。這可能是由於負載均衡或簡單的隨機化。

將請求重定向到另一個頁面的最簡單方法是使用響應物件的sendRedirect()方法。以下是此方法的簽名:

public void response.sendRedirect(String location)
throws IOException 

此方法將響應連同狀態程式碼和新頁面位置一起傳送回瀏覽器。您還可以將setStatus()setHeader()方法一起使用來實現相同的重定向示例:

....
String site = "http://www.newpage.com" ;
response.setStatus(response.SC_MOVED_TEMPORARILY);
response.setHeader("Location", site); 
....

示例

此示例顯示JSP如何執行到另一個位置的頁面重定向:

<%@ page import = "java.io.*,java.util.*" %>

<html>
   <head>
      <title>Page Redirection</title>
   </head>
   
   <body>
      <center>
         <h1>Page Redirection</h1>
      </center>
      <%
         // New location to be redirected
         String site = new String("http://www.photofuntoos.com");
         response.setStatus(response.SC_MOVED_TEMPORARILY);
         response.setHeader("Location", site); 
      %>
   </body>
</html>

現在,我們將以上程式碼放入PageRedirect.jsp中,並使用URLhttps://:8080/PageRedirect.jsp呼叫此JSP。這將帶您到給定的URLhttp://www.photofuntoos.com

JSP - 訪問計數器

在本節中,我們將討論JSP中的訪問計數器。訪問計數器會告訴您網站特定頁面上的訪問次數。通常,您將訪問計數器與index.jsp頁面關聯,假設人們首先訪問您的主頁。

要實現訪問計數器,您可以使用Application隱式物件以及關聯的方法getAttribute()setAttribute()

此物件在其整個生命週期中表示JSP頁面。此物件在JSP頁面初始化時建立,並在JSP頁面被jspDestroy()方法移除時移除。

以下是設定應用程式級別變數的語法:

application.setAttribute(String Key, Object Value);

您可以使用上述方法設定訪問計數器變數並重置相同的變數。以下是讀取先前方法設定的變數的方法:

application.getAttribute(String Key);

每次使用者訪問您的頁面時,您可以讀取訪問計數器的當前值,將其增加 1,然後再次將其設定為供將來使用。

示例

此示例顯示如何使用JSP計算特定頁面的總訪問次數。如果要計算網站的總訪問次數,則必須在所有JSP頁面中包含相同的程式碼。

<%@ page import = "java.io.*,java.util.*" %>

<html>
   <head>
      <title>Application object in JSP</title>
   </head>
   
   <body>
      <%
         Integer hitsCount = (Integer)application.getAttribute("hitCounter");
         if( hitsCount ==null || hitsCount == 0 ) {
            /* First visit */
            out.println("Welcome to my website!");
            hitsCount = 1;
         } else {
            /* return visit */
            out.println("Welcome back to my website!");
            hitsCount += 1;
         }
         application.setAttribute("hitCounter", hitsCount);
      %>
      <center>
         <p>Total number of visits: <%= hitsCount%></p>
      </center>
   
   </body>
</html>

現在,我們將以上程式碼放入main.jsp中,並使用URLhttps://:8080/main.jsp呼叫此JSP。這將顯示訪問計數器值,該值在您重新整理頁面時會增加。您可以嘗試使用不同的瀏覽器訪問頁面,您會發現訪問計數器將隨著每次訪問而不斷增加,並且您將收到如下結果:

Welcome back to my website!

Total number of visits: 12

訪問計數器重置

當您重新啟動應用程式(即Web伺服器)時會發生什麼?這將重置您的應用程式變數,並且您的計數器將重置為零。為了避免此損失,請考慮以下幾點:

  • 定義一個包含單個計數的資料庫表,例如hitcount。為其分配零值。

  • 每次訪問時,讀取表以獲取hitcount的值。

  • 將hitcount的值增加 1,並使用新值更新表。

  • 將hitcount的新值顯示為總頁面訪問次數。

  • 如果要計算所有頁面的訪問次數,請為所有頁面實現上述邏輯。

JSP - 自動重新整理

在本節中,我們將討論JSP中的自動重新整理。考慮一個顯示即時遊戲比分或股市狀態或貨幣匯率的網頁。對於所有此類頁面,您需要定期使用瀏覽器的重新整理或重新載入按鈕重新整理網頁。

JSP 透過提供一種機制使這項工作變得容易,您可以透過這種機制建立網頁,以便在給定的時間間隔後自動重新整理。

重新整理網頁的最簡單方法是使用響應物件的setIntHeader()方法。以下是此方法的簽名:

public void setIntHeader(String header, int headerValue)

此方法將標頭“Refresh”連同表示以秒為單位的時間間隔的整數值一起傳送回瀏覽器。

自動頁面重新整理示例

在以下示例中,我們將使用setIntHeader()方法設定Refresh標頭。這將有助於模擬數字時鐘:

<%@ page import = "java.io.*,java.util.*" %>

<html>
   <head>
      <title>Auto Refresh Header Example</title>
   </head>
   
   <body>
      <center>
         <h2>Auto Refresh Header Example</h2>
         <%
            // Set refresh, autoload time as 5 seconds
            response.setIntHeader("Refresh", 5);
            
            // Get current time
            Calendar calendar = new GregorianCalendar();
            String am_pm;
            
            int hour = calendar.get(Calendar.HOUR);
            int minute = calendar.get(Calendar.MINUTE);
            int second = calendar.get(Calendar.SECOND);
            
            if(calendar.get(Calendar.AM_PM) == 0)
               am_pm = "AM";
            else
               am_pm = "PM";
            String CT = hour+":"+ minute +":"+ second +" "+ am_pm;
            out.println("Crrent Time: " + CT + "\n");
         %>
      </center>
   
   </body>
</html>

現在將以上程式碼放入main.jsp中並嘗試訪問它。這將在每 5 秒後顯示當前系統時間,如下所示。只需執行JSP並等待檢視結果:

Auto Refresh Header Example

Current Time is: 9:44:50 PM

JSP - 傳送郵件

在本節中,我們將討論如何使用JSP傳送電子郵件。要使用JSP傳送電子郵件,您應該在您的計算機上安裝JavaMail APIJava Activation Framework (JAF)

下載並解壓縮這些檔案,在新建的頂級目錄中。您會發現這兩個應用程式都有許多jar檔案。您需要將mail.jaractivation.jar檔案新增到您的CLASSPATH中。

傳送簡單的電子郵件

這是一個從您的計算機發送簡單電子郵件的示例。假設您的localhost已連線到Internet,並且能夠傳送電子郵件。確保Java Email API包和JAF包中的所有jar檔案都存在於CLASSPATH中。

<%@ page import = "java.io.*,java.util.*,javax.mail.*"%>
<%@ page import = "javax.mail.internet.*,javax.activation.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>

<%
   String result;
   
   // Recipient's email ID needs to be mentioned.
   String to = "abcd@gmail.com";

   // Sender's email ID needs to be mentioned
   String from = "mcmohd@gmail.com";

   // Assuming you are sending email from localhost
   String host = "localhost";

   // Get system properties object
   Properties properties = System.getProperties();

   // Setup mail server
   properties.setProperty("mail.smtp.host", host);

   // Get the default Session object.
   Session mailSession = Session.getDefaultInstance(properties);

   try {
      // Create a default MimeMessage object.
      MimeMessage message = new MimeMessage(mailSession);
      
      // Set From: header field of the header.
      message.setFrom(new InternetAddress(from));
      
      // Set To: header field of the header.
      message.addRecipient(Message.RecipientType.TO,
                               new InternetAddress(to));
      // Set Subject: header field
      message.setSubject("This is the Subject Line!");
      
      // Now set the actual message
      message.setText("This is actual message");
      
      // Send message
      Transport.send(message);
      result = "Sent message successfully....";
   } catch (MessagingException mex) {
      mex.printStackTrace();
      result = "Error: unable to send message....";
   }
%>

<html>
   <head>
      <title>Send Email using JSP</title>
   </head>
   
   <body>
      <center>
         <h1>Send Email using JSP</h1>
      </center>
      
      <p align = "center">
         <% 
            out.println("Result: " + result + "\n");
         %>
      </p>
   </body>
</html>

現在,我們將以上程式碼放入SendEmail.jsp檔案中,並使用URLhttps://:8080/SendEmail.jsp呼叫此JSP。這將有助於將電子郵件傳送到給定的電子郵件IDabcd@gmail.com。您將收到以下回復:

Send Email using JSP

Result: Sent message successfully....

如果要將電子郵件傳送給多個收件人,則可以使用以下方法指定多個電子郵件ID:

void addRecipients(Message.RecipientType type, Address[] addresses)
throws MessagingException

以下是引數的描述:

  • type - 這將設定為TO、CC或BCC。此處CC表示抄送,BCC表示密件抄送。例如Message.RecipientType.TO

  • addresses - 這是電子郵件ID的陣列。在指定電子郵件ID時,您需要使用InternetAddress()方法

傳送HTML電子郵件

這是一個從您的計算機發送HTML電子郵件的示例。假設您的localhost已連線到Internet,並且能夠傳送電子郵件。確保Java Email API包和JAF包中的所有jar檔案都存在於CLASSPATH中。

此示例與前一個示例非常相似,只是在這裡我們使用setContent()方法設定內容,其第二個引數為“text/html”以指定郵件中包含HTML內容。

使用此示例,您可以傳送任意大小的HTML內容。

<%@ page import = "java.io.*,java.util.*,javax.mail.*"%>
<%@ page import = "javax.mail.internet.*,javax.activation.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>

<%
   String result;
   
   // Recipient's email ID needs to be mentioned.
   String to = "abcd@gmail.com";

   // Sender's email ID needs to be mentioned
   String from = "mcmohd@gmail.com";

   // Assuming you are sending email from localhost
   String host = "localhost";

   // Get system properties object
   Properties properties = System.getProperties();

   // Setup mail server
   properties.setProperty("mail.smtp.host", host);

   // Get the default Session object.
   Session mailSession = Session.getDefaultInstance(properties);

   try {
      // Create a default MimeMessage object.
      MimeMessage message = new MimeMessage(mailSession);
      
      // Set From: header field of the header.
      message.setFrom(new InternetAddress(from));
      
      // Set To: header field of the header.
      message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
      
      // Set Subject: header field
      message.setSubject("This is the Subject Line!");
     
      // Send the actual HTML message, as big as you like
      message.setContent("<h1>This is actual message</h1>", "text/html" );
      
      // Send message
      Transport.send(message);
      result = "Sent message successfully....";
   } catch (MessagingException mex) {
      mex.printStackTrace();
      result = "Error: unable to send message....";
   }
%>

<html>
   <head>
      <title>Send HTML Email using JSP</title>
   </head>

   <body>
      <center>
         <h1>Send Email using JSP</h1>
      </center>
      
      <p align = "center">
         <% 
            out.println("Result: " + result + "\n");
         %>
      </p>
   </body>
</html>

現在,讓我們使用以上JSP將HTML郵件傳送到給定的電子郵件ID。

在電子郵件中傳送附件

以下是從您的計算機發送包含附件的電子郵件的示例:

<%@ page import = "java.io.*,java.util.*,javax.mail.*"%>
<%@ page import = "javax.mail.internet.*,javax.activation.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>

<%
   String result;
   
   // Recipient's email ID needs to be mentioned.
   String to = "abcd@gmail.com";

   // Sender's email ID needs to be mentioned
   String from = "mcmohd@gmail.com";

   // Assuming you are sending email from localhost
   String host = "localhost";

   // Get system properties object
   Properties properties = System.getProperties();

   // Setup mail server
   properties.setProperty("mail.smtp.host", host);

   // Get the default Session object.
   Session mailSession = Session.getDefaultInstance(properties);

   try {
      // Create a default MimeMessage object.
      MimeMessage message = new MimeMessage(mailSession);

      // Set From: header field of the header.
      message.setFrom(new InternetAddress(from));

      // Set To: header field of the header.
      message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

      // Set Subject: header field
      message.setSubject("This is the Subject Line!");

      // Create the message part 
      BodyPart messageBodyPart = new MimeBodyPart();

      // Fill the message
      messageBodyPart.setText("This is message body");
      
      // Create a multipart message
      Multipart multipart = new MimeMultipart();

      // Set text message part
      multipart.addBodyPart(messageBodyPart);

      // Part two is attachment
      messageBodyPart = new MimeBodyPart();
      
      String filename = "file.txt";
      DataSource source = new FileDataSource(filename);
      messageBodyPart.setDataHandler(new DataHandler(source));
      messageBodyPart.setFileName(filename);
      multipart.addBodyPart(messageBodyPart);

      // Send the complete message parts
      message.setContent(multipart );

      // Send message
      Transport.send(message);
      String title = "Send Email";
      result = "Sent message successfully....";
   } catch (MessagingException mex) {
      mex.printStackTrace();
      result = "Error: unable to send message....";
   }
%>

<html>
   <head>
      <title>Send Attachment Email using JSP</title>
   </head>
   
   <body>
      <center>
         <h1>Send Attachment Email using JSP</h1>
      </center>
      
      <p align = "center">
         <%out.println("Result: " + result + "\n");%>
      </p>
   </body>
</html>

現在,讓我們執行以上JSP,將檔案作為附件連同郵件一起傳送到給定的電子郵件ID。

使用者身份驗證部分

如果需要向電子郵件伺服器提供使用者ID和密碼以進行身份驗證,則可以按如下方式設定這些屬性:

props.setProperty("mail.user", "myuser");
props.setProperty("mail.password", "mypwd");

其餘的電子郵件傳送機制將保持如上所述。

使用表單傳送電子郵件

您可以使用HTML表單接受電子郵件引數,然後您可以使用request物件獲取所有資訊,如下所示:

String to = request.getParameter("to");
String from = request.getParameter("from");
String subject = request.getParameter("subject");
String messageText = request.getParameter("body");

獲取所有資訊後,您可以使用上述程式傳送電子郵件。

JSP - 標準標籤庫 (JSTL) 教程

在本節中,我們將瞭解JSP中的不同標籤。JavaServer Pages Standard Tag Library (JSTL) 是一個有用的JSP標籤集合,它封裝了許多JSP應用程式共有的核心功能。

JSTL 支援常見的結構化任務,例如迭代和條件語句,用於操作XML文件的標籤、國際化標籤和SQL標籤。它還提供了一個框架,用於將現有的自定義標籤與JSTL標籤整合。

安裝JSTL庫

要開始使用JSP標籤,您需要首先安裝JSTL庫。如果您使用的是Apache Tomcat容器,則請按照以下兩個步驟操作:

步驟 1 - 從Apache Standard Taglib下載二進位制發行版並解壓縮壓縮檔案。

步驟 2 - 要從其Jakarta Taglibs發行版中使用Standard Taglib,只需將發行版“lib”目錄中的JAR檔案複製到應用程式的webapps\ROOT\WEB-INF\lib目錄中即可。

要使用任何庫,您必須在使用該庫的每個JSP頂部包含一個<taglib>指令。

JSTL標籤的分類

根據其功能,JSTL標籤可以分為以下JSTL標籤庫組,這些組可用於建立JSP頁面:

  • 核心標籤

  • 格式化標籤

  • SQL標籤

  • XML標籤

  • JSTL函式

核心標籤

核心標籤組是最常用的JSTL標籤。以下是將JSTL核心庫包含在您的JSP中的語法:

<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>

下表列出了核心JSTL標籤:

序號 標籤 & 描述
1 <c:out>

類似於<%= ... >,但用於表示式。

2 <c:set >

'scope'中設定表示式計算的結果

3 <c:remove >

移除作用域變數(如果指定,則從特定作用域中移除)。

4 <c:catch>

捕獲其主體中發生的任何Throwable,並可以選擇性地公開它。

5 <c:if>

簡單的條件標籤,如果提供的條件為真,則計算其主體。

6 <c:choose>

簡單的條件標籤,它為相互排斥的條件操作建立上下文,由<when><otherwise>標記。

7 <c:when>

<choose>的子標籤,如果其條件計算結果為'true',則包含其主體。

8 <c:otherwise >

<choose>的子標籤,位於<when>標籤之後,僅當所有先前的條件計算結果為'false'時才執行。

9 <c:import>

檢索絕對或相對URL,並將內容公開到頁面、'var'中的字串或'varReader'中的Reader。

10 <c:forEach >

基本的迭代標籤,接受許多不同的集合型別並支援子集和其他功能。

11 <c:forTokens>

遍歷由提供的分隔符分隔的標記。

12 <c:param>

向包含的'import'標籤的URL新增引數。

13 <c:redirect >

重定向到新的URL。

14 <c:url>

建立帶可選查詢引數的URL

格式化標籤

JSTL格式化標籤用於格式化和顯示文字、日期、時間和國際化網站的數字。以下是將格式化庫包含在您的JSP中的語法:

<%@ taglib prefix = "fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %>

下表列出了格式化JSTL標籤:

序號 標籤 & 描述
1 <fmt:formatNumber>

以特定精度或格式呈現數值。

2 <fmt:parseNumber>

分析數字、貨幣或百分比的字串表示形式。

3 <fmt:formatDate>

使用提供的樣式和模式格式化日期和/或時間。

4 <fmt:parseDate>

分析日期和/或時間的字串表示形式

5 <fmt:bundle>

載入其標籤主體將使用的資源包。

6 <fmt:setLocale>

將給定的區域設定儲存在區域設定配置變數中。

7 <fmt:setBundle>

載入資源包並將其儲存在命名的作用域變數或 bundle 配置變數中。

8 <fmt:timeZone>

指定其主體中巢狀的任何時間格式化或解析操作的時間區域。

9 <fmt:setTimeZone>

將給定的時區儲存在時區配置變數中

10 <fmt:message>

顯示國際化訊息。

11 <fmt:requestEncoding>

設定請求字元編碼

SQL標籤

JSTL SQL 標籤庫提供用於與關係資料庫 (RDBMS) 互動的標籤,例如Oracle、mySQLMicrosoft SQL Server

以下是將 JSTL SQL 庫包含在 JSP 中的語法:

<%@ taglib prefix = "sql" uri = "http://java.sun.com/jsp/jstl/sql" %>

下表列出了 SQL JSTL 標籤:

序號 標籤 & 描述
1 <sql:setDataSource>

建立一個僅適用於原型設計的簡單 DataSource

2 <sql:query>

執行其主體中或透過 sql 屬性定義的 SQL 查詢。

3 <sql:update>

執行其主體中或透過 sql 屬性定義的 SQL 更新。

4 <sql:param>

將 SQL 語句中的引數設定為指定值。

5 <sql:dateParam>

將 SQL 語句中的引數設定為指定的 java.util.Date 值。

6 <sql:transaction >

為巢狀的資料庫操作元素提供共享的 Connection,設定為將所有語句作為一個事務執行。

XML標籤

JSTL XML 標籤提供了一種以 JSP 為中心的建立和操作 XML 文件的方法。以下是將 JSTL XML 庫包含在 JSP 中的語法。

JSTL XML 標籤庫具有用於與 XML 資料互動的自定義標籤。這包括解析 XML、轉換 XML 資料以及基於 XPath 表示式的流程控制。

<%@ taglib prefix = "x" 
   uri = "http://java.sun.com/jsp/jstl/xml" %>

在繼續示例之前,您需要將以下兩個與 XML 和 XPath 相關的庫複製到您的<Tomcat 安裝目錄>\lib中:

以下是 XML JSTL 標籤的列表:

序號 標籤 & 描述
1 <x:out>

類似於<%= ... >,但用於 XPath 表示式。

2 <x:parse>

用於解析透過屬性或標籤主體指定的 XML 資料。

3 <x:set >

將變數設定為 XPath 表示式的值。

4 <x:if >

評估測試 XPath 表示式,如果為真,則處理其主體。如果測試條件為假,則忽略主體。

5 <x:forEach>

迴圈遍歷 XML 文件中的節點。

6 <x:choose>

簡單的條件標籤,為相互排斥的條件操作建立上下文,由<when><otherwise>標籤標記。

7 <x:when >

<choose>的子標籤,如果其表示式計算結果為“true”,則包含其主體。

8 <x:otherwise >

<choose>的子標籤,位於<when>標籤之後,僅當所有先前條件計算結果為“false”時才執行。

9 <x:transform >

對 XML 文件應用 XSL 轉換

10 <x:param >

transform標籤一起使用,以在 XSLT 樣式表中設定引數

JSTL函式

JSTL 包含許多標準函式,其中大多數是常見的字串操作函式。以下是將 JSTL 函式庫包含在 JSP 中的語法:

<%@ taglib prefix = "fn" 
   uri = "http://java.sun.com/jsp/jstl/functions" %>

下表列出了各種 JSTL 函式:

序號 函式 & 描述
1 fn:contains()

測試輸入字串是否包含指定的子字串。

2 fn:containsIgnoreCase()

不區分大小寫地測試輸入字串是否包含指定的子字串。

3 fn:endsWith()

測試輸入字串是否以指定的字尾結尾。

4 fn:escapeXml()

轉義可以解釋為 XML 標記的字元。

5 fn:indexOf()

返回字串中指定子字串首次出現的索引。

6 fn:join()

將陣列的所有元素連線成一個字串。

7 fn:length()

返回集合中的專案數或字串中的字元數。

8 fn:replace()

返回一個字串,該字串是透過替換輸入字串中所有出現的給定字串而生成的。

9 fn:split()

將字串拆分為子字串陣列。

10 fn:startsWith()

測試輸入字串是否以指定的字首開頭。

11 fn:substring()

返回字串的子集。

12 fn:substringAfter()

返回特定子字串之後字串的子集。

13 fn:substringBefore()

返回特定子字串之前字串的子集。

14 fn:toLowerCase()

將字串的所有字元轉換為小寫。

15 fn:toUpperCase()

將字串的所有字元轉換為大寫。

16 fn:trim()

刪除字串兩端的白空格。

JSP - 資料庫訪問

在本章中,我們將討論如何使用 JSP 訪問資料庫。我們假設您對 JDBC 應用程式的工作原理有很好的瞭解。在透過 JSP 開始訪問資料庫之前,請確保您已正確設定 JDBC 環境以及資料庫。

有關如何使用 JDBC 訪問資料庫及其環境設定的更多詳細資訊,您可以檢視我們的JDBC 教程

為了開始瞭解基本概念,讓我們建立一個表並在該表中建立一些記錄,如下所示:

建立表

要建立 EMP 資料庫中的Employees表,請使用以下步驟:

步驟 1

開啟命令提示符並更改到安裝目錄,如下所示:

C:\>
C:\>cd Program Files\MySQL\bin
C:\Program Files\MySQL\bin>

步驟 2

登入到資料庫,如下所示:

C:\Program Files\MySQL\bin>mysql -u root -p
Enter password: ********
mysql>

步驟 3

TEST資料庫中建立Employee表,如下所示:

mysql> use TEST;
mysql> create table Employees
   (
      id int not null,
      age int not null,
      first varchar (255),
      last varchar (255)
   );
Query OK, 0 rows affected (0.08 sec)
mysql>

建立資料記錄

現在讓我們在Employee表中建立一些記錄,如下所示:

mysql> INSERT INTO Employees VALUES (100, 18, 'Zara', 'Ali');
Query OK, 1 row affected (0.05 sec)
 
mysql> INSERT INTO Employees VALUES (101, 25, 'Mahnaz', 'Fatma');
Query OK, 1 row affected (0.00 sec)
 
mysql> INSERT INTO Employees VALUES (102, 30, 'Zaid', 'Khan');
Query OK, 1 row affected (0.00 sec)
 
mysql> INSERT INTO Employees VALUES (103, 28, 'Sumit', 'Mittal');
Query OK, 1 row affected (0.00 sec)
 
mysql>

SELECT 操作

以下示例顯示瞭如何在 JSP 程式設計中使用 JTSL 執行SQL SELECT語句:

<%@ page import = "java.io.*,java.util.*,java.sql.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix = "c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix = "sql"%>
 
<html>
   <head>
      <title>SELECT Operation</title>
   </head>

   <body>
      <sql:setDataSource var = "snapshot" driver = "com.mysql.jdbc.Driver"
         url = "jdbc:mysql:///TEST"
         user = "root"  password = "pass123"/>
 
      <sql:query dataSource = "${snapshot}" var = "result">
         SELECT * from Employees;
      </sql:query>
 
      <table border = "1" width = "100%">
         <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
         </tr>
         
         <c:forEach var = "row" items = "${result.rows}">
            <tr>
               <td><c:out value = "${row.id}"/></td>
               <td><c:out value = "${row.first}"/></td>
               <td><c:out value = "${row.last}"/></td>
               <td><c:out value = "${row.age}"/></td>
            </tr>
         </c:forEach>
      </table>
 
   </body>
</html>

訪問上述 JSP,將顯示以下結果:

Emp ID First Name Last Name Age
100 Zara Ali 18
101 Mahnaz Fatma 25
102 Zaid Khan 30
103 Sumit Mittal 28

INSERT 操作

以下示例顯示瞭如何在 JSP 程式設計中使用 JTSL 執行 SQL INSERT 語句:

<%@ page import = "java.io.*,java.util.*,java.sql.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix = "c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix = "sql"%>
 
<html>
   <head>
      <title>JINSERT Operation</title>
   </head>
   
   <body>
      <sql:setDataSource var = "snapshot" driver = "com.mysql.jdbc.Driver"
         url = "jdbc:mysql:///TEST"
         user = "root"  password = "pass123"/>
         <sql:update dataSource = "${snapshot}" var = "result">
         INSERT INTO Employees VALUES (104, 2, 'Nuha', 'Ali');
      </sql:update>
 
      <sql:query dataSource = "${snapshot}" var = "result">
         SELECT * from Employees;
      </sql:query>
 
      <table border = "1" width = "100%">
         <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
         </tr>
         
         <c:forEach var = "row" items = "${result.rows}">
            <tr>
               <td><c:out value = "${row.id}"/></td>
               <td><c:out value = "${row.first}"/></td>
               <td><c:out value = "${row.last}"/></td>
               <td><c:out value = "${row.age}"/></td>
            </tr>
         </c:forEach>
      </table>
 
   </body>
</html>

訪問上述 JSP,將顯示以下結果:

Emp ID First Name Last Name Age
100 Zara Ali 18
101 Mahnaz Fatma 25
102 Zaid Khan 30
103 Sumit Mittal 28
104 Nuha Ali 2

DELETE 操作

以下示例顯示瞭如何在 JSP 程式設計中使用 JTSL 執行SQL DELETE語句:

<%@ page import = "java.io.*,java.util.*,java.sql.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix = "c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix = "sql"%>
 
<html>
   <head>
      <title>DELETE Operation</title>
   </head>
   
   <body>
      <sql:setDataSource var = "snapshot" driver = "com.mysql.jdbc.Driver"
         url = "jdbc:mysql:///TEST"
         user = "root" password = "pass123"/>
 
      <c:set var = "empId" value = "103"/>
 
      <sql:update dataSource = "${snapshot}" var = "count">
         DELETE FROM Employees WHERE Id = ?
         <sql:param value = "${empId}" />
      </sql:update>
 
      <sql:query dataSource = "${snapshot}" var = "result">
         SELECT * from Employees;
      </sql:query>
 
      <table border = "1" width = "100%">
         <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
         </tr>
            
         <c:forEach var = "row" items = "${result.rows}">
            <tr>
               <td><c:out value = "${row.id}"/></td>
               <td><c:out value = "${row.first}"/></td>
               <td><c:out value = "${row.last}"/></td>
               <td><c:out value = "${row.age}"/></td>
            </tr>
         </c:forEach>
      </table>
 
   </body>
</html>

訪問上述 JSP,將顯示以下結果:

Emp ID First Name Last Name Age
100 Zara Ali 18
101 Mahnaz Fatma 25
102 Zaid Khan 30

UPDATE 操作

以下示例顯示瞭如何在 JSP 程式設計中使用 JTSL 執行SQL UPDATE語句:

<%@ page import = "java.io.*,java.util.*,java.sql.*"%>
<%@ page import = "javax.servlet.http.*,javax.servlet.*" %>
<%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c"%>
<%@ taglib uri = "http://java.sun.com/jsp/jstl/sql" prefix = "sql"%>
 
<html>
   <head>
      <title>DELETE Operation</title>
   </head>
   
   <body>
      <sql:setDataSource var = "snapshot" driver = "com.mysql.jdbc.Driver"
         url = "jdbc:mysql:///TEST"
         user = "root" password = "pass123"/>
 
      <c:set var = "empId" value = "102"/>
 
      <sql:update dataSource = "${snapshot}" var = "count">
         UPDATE Employees SET WHERE last = 'Ali'
         <sql:param value = "${empId}" />
      </sql:update>
 
      <sql:query dataSource = "${snapshot}" var = "result">
         SELECT * from Employees;
      </sql:query>
 
      <table border = "1" width = "100%">
         <tr>
            <th>Emp ID</th>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Age</th>
         </tr>
            
         <c:forEach var = "row" items = "${result.rows}">
            <tr>
               <td><c:out value = "${row.id}"/></td>
               <td><c:out value = "${row.first}"/></td>
               <td><c:out value = "${row.last}"/></td>
               <td><c:out value = "${row.age}"/></td>
            </tr>
         </c:forEach>
      </table>
 
   </body>
</html>

訪問上述 JSP,將顯示以下結果:

Emp ID First Name Last Name Age
100 Zara Ali 18
101 Mahnaz Fatma 25
102 Zaid Ali 30

JSP - XML 資料

當您透過 HTTP 傳送 XML 資料時,使用 JSP 處理傳入和傳出 XML 文件是有意義的;例如,RSS 文件。由於 XML 文件僅僅是一堆文字,因此透過 JSP 建立一個 XML 文件比建立 HTML 文件容易得多。

從 JSP 傳送 XML

您可以使用 JSP 以與傳送 HTML 相同的方式傳送 XML 內容。唯一的區別是您必須將頁面的內容型別設定為 text/xml。要設定內容型別,請使用<%@page%>標籤,如下所示:

<%@ page contentType = "text/xml" %>

以下示例將顯示如何將 XML 內容傳送到瀏覽器:

<%@ page contentType = "text/xml" %>

<books>
   <book>
      <name>Padam History</name>
      <author>ZARA</author>
      <price>100</price>
   </book>
</books>

使用不同的瀏覽器訪問上述 XML 以檢視上述 XML 的文件樹表示。

在 JSP 中處理 XML

在繼續使用 JSP 處理 XML 之前,您需要將以下兩個與 XML 和 XPath 相關的庫複製到您的<Tomcat 安裝目錄>\lib中:

讓我們將以下內容放入 books.xml 檔案中:

<books>
   <book>
      <name>Padam History</name>
      <author>ZARA</author>
      <price>100</price>
   </book>
   
   <book>
      <name>Great Mistry</name>
      <author>NUHA</author>
      <price>2000</price>
   </book>
</books>

嘗試以下main.jsp,保留在同一目錄中:

<%@ taglib prefix = "c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix = "x" uri="http://java.sun.com/jsp/jstl/xml" %>
 
<html>
   <head>
      <title>JSTL x:parse Tags</title>
   </head>

   <body>
      <h3>Books Info:</h3>
      <c:import var = "bookInfo" url="https://:8080/books.xml"/>
 
      <x:parse xml = "${bookInfo}" var = "output"/>
      <b>The title of the first book is</b>: 
      <x:out select = "$output/books/book[1]/name" />
      <br>
      
      <b>The price of the second book</b>: 
      <x:out select = "$output/books/book[2]/price" />
   </body>
</html>

使用https://:8080/main.jsp訪問上述 JSP,將顯示以下結果:

Books Info:

The title of the first book is:Padam History The price of the second book: 2000

使用 JSP 格式化 XML

考慮以下 XSLT 樣式表style.xsl

<?xml version = "1.0"?>
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" 
   version = "1.0">
 
   <xsl:output method = "html" indent = "yes"/>
   <xsl:template match = "/">
      <html>
         <body>
            <xsl:apply-templates/>
         </body>
      </html>
   </xsl:template>
    
   <xsl:template match = "books">
      <table border = "1" width = "100%">
         <xsl:for-each select = "book">
            <tr>
               <td>
                  <i><xsl:value-of select = "name"/></i>
               </td>
               
               <td>
                  <xsl:value-of select = "author"/>
               </td>
               
               <td>
                  <xsl:value-of select = "price"/>
               </td>
            </tr>
         </xsl:for-each>
      </table>
   
   </xsl:template>
</xsl:stylesheet>

現在考慮以下 JSP 檔案:

<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix = "x" uri = "http://java.sun.com/jsp/jstl/xml" %>
 
<html>
   <head>
      <title>JSTL x:transform Tags</title>
   </head>
   
   <body>
      <h3>Books Info:</h3>
      <c:set var = "xmltext">
         <books>
            <book>
               <name>Padam History</name>
               <author>ZARA</author>
               <price>100</price>
            </book>
            
            <book>
               <name>Great Mistry</name>
               <author>NUHA</author>
               <price>2000</price>
            </book>
         </books>
      </c:set>
 
      <c:import url = "https://:8080/style.xsl" var = "xslt"/>
      <x:transform xml = "${xmltext}" xslt = "${xslt}"/>
   </body>
</html>

將顯示以下結果:

Books Info:

Padam History ZARA 100
Great Mistry NUHA 2000

要了解有關使用 JSTL 處理 XML 的更多資訊,您可以檢視JSP 標準標籤庫

JSP - JavaBeans

JavaBean 是一個用 Java 編寫的特殊構造的 Java 類,並根據 JavaBeans API 規範進行編碼。

以下是將 JavaBean 與其他 Java 類區分開來的獨特特徵:

  • 它提供一個預設的無引數建構函式。

  • 它應該是可序列化的,並且可以實現Serializable介面。

  • 它可能具有一些可以讀取或寫入的屬性。

  • 它可能具有一些用於屬性的“getter”和“setter”方法。

JavaBeans 屬性

JavaBean 屬性是可以由物件使用者訪問的命名屬性。屬性可以是任何 Java 資料型別,包括您定義的類。

JavaBean 屬性可以是只讀、可寫、只讀只寫。透過 JavaBean 實現類中的兩種方法訪問 JavaBean 屬性:

序號 方法及描述
1

getPropertyName()

例如,如果屬性名稱為firstName,則您的方法名稱將為getFirstName()以讀取該屬性。此方法稱為訪問器。

2

setPropertyName()

例如,如果屬性名稱為firstName,則您的方法名稱將為setFirstName()以寫入該屬性。此方法稱為修改器。

只讀屬性將僅具有getPropertyName()方法,而只寫屬性將僅具有setPropertyName()方法。

JavaBeans 示例

考慮一個具有少量屬性的學生類:

package com.tutorialspoint;

public class StudentsBean implements java.io.Serializable {
   private String firstName = null;
   private String lastName = null;
   private int age = 0;

   public StudentsBean() {
   }
   public String getFirstName(){
      return firstName;
   }
   public String getLastName(){
      return lastName;
   }
   public int getAge(){
      return age;
   }
   public void setFirstName(String firstName){
      this.firstName = firstName;
   }
   public void setLastName(String lastName){
      this.lastName = lastName;
   }
   public void setAge(Integer age){
      this.age = age;
   }
}

訪問 JavaBeans

useBean操作宣告一個 JavaBean 以在 JSP 中使用。聲明後,bean 成為一個指令碼變數,既可以被 JSP 中使用的指令碼元素訪問,也可以被其他自定義標籤訪問。useBean標籤的完整語法如下:

<jsp:useBean id = "bean's name" scope = "bean's scope" typeSpec/>

這裡,scope 屬性的值可以是page、request、sessionapplication,具體取決於您的需求。id屬性的值可以是任何值,只要它在同一 JSP 中的其他useBean 宣告中是唯一的名稱即可。

以下示例顯示瞭如何使用 useBean 操作:

<html>
   <head>
      <title>useBean Example</title>
   </head>
   
   <body>
      <jsp:useBean id = "date" class = "java.util.Date" /> 
      <p>The date/time is <%= date %>
   </body>
</html>

您將收到以下結果:

The date/time is Thu Sep 30 11:18:11 GST 2010 

訪問 JavaBeans 屬性

除了<jsp:useBean...>操作之外,您還可以使用<jsp:getProperty/>操作訪問 get 方法,並使用<jsp:setProperty/>操作訪問 set 方法。以下是完整語法:

<jsp:useBean id = "id" class = "bean's class" scope = "bean's scope">
   <jsp:setProperty name = "bean's id" property = "property name"  
      value = "value"/>
   <jsp:getProperty name = "bean's id" property = "property name"/>
   ...........
</jsp:useBean>

name 屬性引用先前由 useBean 操作引入 JSP 的 JavaBean 的 id。property 屬性是要呼叫的getset方法的名稱。

以下示例顯示瞭如何使用上述語法訪問資料:

<html>
   <head>
      <title>get and set properties Example</title>
   </head>
   
   <body>
      <jsp:useBean id = "students" class = "com.tutorialspoint.StudentsBean"> 
         <jsp:setProperty name = "students" property = "firstName" value = "Zara"/>
         <jsp:setProperty name = "students" property = "lastName" value = "Ali"/>
         <jsp:setProperty name = "students" property = "age" value = "10"/>
      </jsp:useBean>

      <p>Student First Name: 
         <jsp:getProperty name = "students" property = "firstName"/>
      </p>
      
      <p>Student Last Name: 
         <jsp:getProperty name = "students" property = "lastName"/>
      </p>
      
      <p>Student Age: 
         <jsp:getProperty name = "students" property = "age"/>
      </p>

   </body>
</html>

讓我們使StudentsBean.class在 CLASSPATH 中可用。訪問上述 JSP,將顯示以下結果:

Student First Name: Zara 

Student Last Name: Ali 

Student Age: 10 

JSP - 自定義標籤

在本章中,我們將討論 JSP 中的自定義標籤。自定義標籤是使用者定義的 JSP 語言元素。當包含自定義標籤的 JSP 頁面轉換為 servlet 時,該標籤將轉換為對稱為標籤處理器的物件的運算。然後,當執行 JSP 頁面的 servlet 時,Web 容器將呼叫這些操作。

JSP 標籤擴充套件允許您建立新的標籤,您可以將其直接插入 JavaServer 頁面。JSP 2.0 規範引入了用於編寫這些自定義標籤的簡單標籤處理器。

要編寫自定義標籤,您可以簡單地擴充套件SimpleTagSupport類並覆蓋doTag()方法,您可以在其中放置生成標籤內容的程式碼。

建立“Hello”標籤

假設您想定義一個名為<ex:Hello>的自定義標籤,並且您想以以下方式在沒有主體的情況下使用它:

<ex:Hello />

要建立自定義JSP標籤,您必須首先建立一個充當標籤處理程式的Java類。現在讓我們建立如下所示的HelloTag類:

package com.tutorialspoint;

import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.*;

public class HelloTag extends SimpleTagSupport {
   public void doTag() throws JspException, IOException {
      JspWriter out = getJspContext().getOut();
      out.println("Hello Custom Tag!");
   }
}

以上程式碼包含簡單的編碼,其中doTag()方法使用getJspContext()方法獲取當前的JspContext物件,並使用它將"Hello Custom Tag!"傳送到當前的JspWriter物件。

讓我們編譯上述類並將其複製到環境變數CLASSPATH中可用的目錄中。最後,建立以下標籤庫檔案:<Tomcat-Installation-Directory>webapps\ROOT\WEB-INF\custom.tld

<taglib>
   <tlib-version>1.0</tlib-version>
   <jsp-version>2.0</jsp-version>
   <short-name>Example TLD</short-name>
   
   <tag>
      <name>Hello</name>
      <tag-class>com.tutorialspoint.HelloTag</tag-class>
      <body-content>empty</body-content>
   </tag>
</taglib>

現在讓我們在JSP程式中使用上面定義的自定義標籤Hello,如下所示:

<%@ taglib prefix = "ex" uri = "WEB-INF/custom.tld"%>

<html>
   <head>
      <title>A sample custom tag</title>
   </head>
   
   <body>
      <ex:Hello/>
   </body>
</html>

呼叫上述JSP,這應該會產生以下結果:

Hello Custom Tag!

訪問標籤體

您可以像在標準標籤中看到的那樣,在標籤體中包含一條訊息。假設您想定義一個名為<ex:Hello>的自定義標籤,並且您想以以下方式在有主體的情況下使用它:

<ex:Hello>
   This is message body
</ex:Hello>

讓我們對上述標籤程式碼進行以下更改以處理標籤體:

package com.tutorialspoint;

import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.*;

public class HelloTag extends SimpleTagSupport {
   StringWriter sw = new StringWriter();
   public void doTag()
   
   throws JspException, IOException {
      getJspBody().invoke(sw);
      getJspContext().getOut().println(sw.toString());
   }
}

在這裡,呼叫產生的輸出首先被捕獲到StringWriter中,然後再寫入與標籤關聯的JspWriter。我們需要如下更改TLD檔案:

<taglib>
   <tlib-version>1.0</tlib-version>
   <jsp-version>2.0</jsp-version>
   <short-name>Example TLD with Body</short-name>
   
   <tag>
      <name>Hello</name>
      <tag-class>com.tutorialspoint.HelloTag</tag-class>
      <body-content>scriptless</body-content>
   </tag>
</taglib>

現在讓我們以適當的主體呼叫上述標籤,如下所示:

<%@ taglib prefix = "ex" uri = "WEB-INF/custom.tld"%>

<html>
   <head>
      <title>A sample custom tag</title>
   </head>
   
   <body>
      <ex:Hello>
         This is message body
      </ex:Hello>
   </body>
</html>

您將收到以下結果:

This is message body

自定義標籤屬性

您可以與自定義標籤一起使用各種屬性。要接受屬性值,自定義標籤類需要實現setter方法,與JavaBean setter方法相同,如下所示:

package com.tutorialspoint;

import javax.servlet.jsp.tagext.*;
import javax.servlet.jsp.*;
import java.io.*;

public class HelloTag extends SimpleTagSupport {
   private String message;

   public void setMessage(String msg) {
      this.message = msg;
   }
   StringWriter sw = new StringWriter();
   public void doTag()
   
   throws JspException, IOException {
      if (message != null) {
         /* Use message from attribute */
         JspWriter out = getJspContext().getOut();
         out.println( message );
      } else {
         /* use message from the body */
         getJspBody().invoke(sw);
         getJspContext().getOut().println(sw.toString());
      }
   }
}

屬性的名稱是"message",所以setter方法是setMessage()。現在讓我們使用<attribute>元素在TLD檔案中新增此屬性,如下所示:

<taglib>
   <tlib-version>1.0</tlib-version>
   <jsp-version>2.0</jsp-version>
   <short-name>Example TLD with Body</short-name>
   
   <tag>
      <name>Hello</name>
      <tag-class>com.tutorialspoint.HelloTag</tag-class>
      <body-content>scriptless</body-content>
      
      <attribute>
         <name>message</name>
      </attribute>
   
   </tag>
</taglib>

讓我們按照帶有message屬性的JSP操作,如下所示:

<%@ taglib prefix = "ex" uri = "WEB-INF/custom.tld"%>

<html>
   <head>
      <title>A sample custom tag</title>
   </head>
   
   <body>
      <ex:Hello message = "This is custom tag" />
   </body>
</html>

這將產生以下結果:

This is custom tag

考慮為屬性包含以下屬性:

序號 屬性&用途
1

name

name元素定義屬性的名稱。每個屬性名稱對於特定標籤必須唯一。

2

required

這指定此屬性是必需的還是可選的。對於可選屬性,它將為false。

3

rtexprvalue

宣告標籤屬性的執行時表示式值是否有效

4

type

定義此屬性的Java類型別。預設情況下,它被假定為String

5

description

可以提供資訊描述。

6

fragment

宣告此屬性值是否應被視為JspFragment

以下是指定與屬性相關的屬性的示例:

.....
   <attribute>
      <name>attribute_name</name>
      <required>false</required>
      <type>java.util.Date</type>
      <fragment>false</fragment>
   </attribute>
.....

如果您使用兩個屬性,則可以如下修改您的TLD:

.....
   <attribute>
      <name>attribute_name1</name>
      <required>false</required>
      <type>java.util.Boolean</type>
      <fragment>false</fragment>
   </attribute>
   
   <attribute>
      <name>attribute_name2</name>
      <required>true</required>
      <type>java.util.Date</type>
   </attribute>
.....

JSP - 表示式語言 (EL)

JSP表示式語言(EL)使您可以輕鬆訪問儲存在JavaBeans元件中的應用程式資料。JSP EL允許您建立(a)算術和(b)邏輯表示式。在JSP EL表示式中,您可以使用整數、浮點數、字串、內建常量true和false表示布林值,以及null。

簡單語法

通常,當您在JSP標籤中指定屬性值時,只需使用字串。例如:

<jsp:setProperty name = "box" property = "perimeter" value = "100"/>

JSP EL允許您為這些屬性值中的任何一個指定表示式。JSP EL的簡單語法如下所示:

${expr}

這裡expr指定表示式本身。JSP EL中最常見的運算子是.[]。這兩個運算子允許您訪問Java Beans和內建JSP物件的各種屬性。

例如,上述語法<jsp:setProperty>標籤可以用表示式編寫,例如:

<jsp:setProperty name = "box" property = "perimeter" 
   value = "${2*box.width+2*box.height}"/>

當JSP編譯器在屬性中看到${}形式時,它會生成程式碼來計算表示式並替換表示式的值。

您還可以將JSP EL表示式用於標籤的模板文字中。例如,<jsp:text>標籤只是將它的內容插入到JSP的主體中。以下<jsp:text>宣告將<h1>Hello JSP!</h1>插入到JSP輸出中:

<jsp:text>
   <h1>Hello JSP!</h1>
</jsp:text>

您現在可以在<jsp:text>標籤(或任何其他標籤)的主體中包含JSP EL表示式,使用與您用於屬性相同的${}語法。例如:

<jsp:text>
   Box Perimeter is: ${2*box.width + 2*box.height}
</jsp:text>

EL表示式可以使用括號對子表示式進行分組。例如,${(1 + 2) * 3} 等於 9,但 ${1 + (2 * 3)} 等於 7

要停用EL表示式的計算,我們如下指定page指令的isELIgnored屬性:

<%@ page isELIgnored = "true|false" %>

此屬性的有效值為true和false。如果為true,則在靜態文字或標籤屬性中出現EL表示式時,將忽略它們。如果為false,則容器將計算EL表示式。

EL中的基本運算子

JSP表示式語言(EL)支援Java支援的大多數算術和邏輯運算子。下表列出了最常用的運算子:

序號 運算子&描述
1

.

訪問bean屬性或Map條目

2

[]

訪問陣列或List元素

3

( )

對子表示式進行分組以更改計算順序

4

+

加法

5

-

減法或值的否定

6

*

乘法

7

/ 或 div

除法

8

% 或 mod

取模(餘數)

9

== 或 eq

測試相等性

10

!= 或 ne

測試不相等性

11

< 或 lt

測試小於

12

> 或 gt

測試大於

13

<= 或 le

測試小於或等於

14

>= 或 ge

測試大於或等於

15

&& 或 and

測試邏輯AND

16

|| 或 or

測試邏輯OR

17

! 或 not

一元布林補碼

18

empty

測試空變數值

JSP EL中的函式

JSP EL也允許您在表示式中使用函式。這些函式必須在自定義標籤庫中定義。函式用法具有以下語法:

${ns:func(param1, param2, ...)}

其中ns是函式的名稱空間,func是函式的名稱,param1是第一個引數值。例如,函式fn:length是JSTL庫的一部分。此函式可以按如下方式使用以獲取字串的長度。

${fn:length("Get my length")}

要使用任何標籤庫(標準或自定義)中的函式,您必須在伺服器上安裝該庫,並且必須使用<taglib>指令將庫包含在JSP中,如JSTL章節中所述。

JSP EL隱式物件

JSP表示式語言支援以下隱式物件:

序號 隱式物件&描述
1

pageScope

頁面範圍內的作用域變數

2

requestScope

請求範圍內的作用域變數

3

sessionScope

會話範圍內的作用域變數

4

applicationScope

應用程式範圍內的作用域變數

5

param

作為字串的請求引數

6

paramValues

作為字串集合的請求引數

7

header

作為字串的HTTP請求頭

8

headerValues

作為字串集合的HTTP請求頭

9

initParam

上下文初始化引數

10

cookie

Cookie值

11

pageContext

當前頁面的JSP PageContext物件

您可以在表示式中使用這些物件,就像使用變數一樣。以下示例將幫助您理解這些概念:

pageContext物件

pageContext物件允許您訪問pageContext JSP物件。透過pageContext物件,您可以訪問request物件。例如,要訪問請求的傳入查詢字串,您可以使用以下表達式:

${pageContext.request.queryString}

作用域物件

pageScope、requestScope、sessionScopeapplicationScope變數提供對儲存在每個作用域級別的變數的訪問。

例如,如果您需要顯式訪問應用程式作用域中的box變數,則可以透過applicationScope變數訪問它,如applicationScope.box

param和paramValues物件

param和paramValues物件允許您訪問通常透過request.getParameterrequest.getParameterValues方法可用的引數值。

例如,要訪問名為order的引數,請使用表示式${param.order}${param["order"]}

以下是訪問名為username的請求引數的示例:

<%@ page import = "java.io.*,java.util.*" %>
<%String title = "Accessing Request Param";%>

<html>
   <head>
      <title><% out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><% out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>${param["username"]}</p>
      </div>
   </body>
</html>

param物件返回單個字串值,而paramValues物件返回字串陣列。

header和headerValues物件

header和headerValues物件允許您訪問通常透過request.getHeaderrequest.getHeaders方法可用的標頭值。

例如,要訪問名為user-agent的標頭,請使用表示式${header.user-agent}${header["user-agent"]}

以下是訪問名為user-agent的標頭引數的示例:

<%@ page import = "java.io.*,java.util.*" %>
<%String title = "User Agent Example";%>

<html>
   <head>
      <title><% out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><% out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>${header["user-agent"]}</p>
      </div>
   </body>
</html>

輸出將類似於以下內容:

User Agent Example

Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; HPNTDF; .NET4.0C; InfoPath.2)

header物件返回單個字串值,而headerValues物件返回字串陣列。

JSP - 異常處理

在本章中,我們將討論如何在JSP中處理異常。在編寫JSP程式碼時,您可能會犯編碼錯誤,這些錯誤可能發生在程式碼的任何部分。您的JSP程式碼中可能會出現以下型別的錯誤:

已檢查異常

已檢查異常是指通常是使用者錯誤或程式設計師無法預見的錯誤。例如,如果要開啟檔案但找不到檔案,則會發生異常。在編譯時,這些異常不能簡單地被忽略。

執行時異常

執行時異常是指程式設計師可能本可以避免的異常。與已檢查異常相反,執行時異常在編譯時會被忽略。

錯誤

這些根本不是異常,而是超出使用者或程式設計師控制範圍的問題。錯誤通常在您的程式碼中被忽略,因為您很少能對錯誤做些什麼。例如,如果發生堆疊溢位,則會發生錯誤。它們在編譯時也會被忽略。

我們將進一步討論處理JSP程式碼中發生的執行時異常/錯誤的方法。

使用Exception物件

異常物件是Throwable的子類的例項(例如,java.lang.NullPointerException),並且僅在錯誤頁面中可用。下表列出了Throwable類中可用的重要方法。

序號 方法和描述
1

public String getMessage()

返回關於發生的異常的詳細訊息。此訊息在Throwable建構函式中初始化。

2

public Throwable getCause()

返回異常的原因,以Throwable物件表示。

3

public String toString()

返回類的名稱與getMessage()結果的連線。

4

public void printStackTrace()

toString()的結果以及堆疊跟蹤列印到System.err(錯誤輸出流)。

5

public StackTraceElement [] getStackTrace()

返回一個數組,其中包含堆疊跟蹤中的每個元素。索引為0的元素表示呼叫堆疊的頂部,陣列中的最後一個元素表示呼叫堆疊底部的元素。

6

public Throwable fillInStackTrace()

使用當前堆疊跟蹤填充此Throwable物件的堆疊跟蹤,並新增到堆疊跟蹤中的任何先前資訊。

JSP允許您為每個JSP指定錯誤頁面。每當頁面丟擲異常時,JSP容器都會自動呼叫錯誤頁面。

以下是如何為main.jsp指定錯誤頁面的示例。要設定錯誤頁面,請使用<%@ page errorPage = "xxx" %>指令。

<%@ page errorPage = "ShowError.jsp" %>

<html>
   <head>
      <title>Error Handling Example</title>
   </head>
   
   <body>
      <%
         // Throw an exception to invoke the error page
         int x = 1;
         
         if (x == 1) {
            throw new RuntimeException("Error condition!!!");
         }
      %>
   </body>
</html>

我們現在將編寫一個錯誤處理JSP ShowError.jsp,如下所示。請注意,錯誤處理頁面包含指令<%@ page isErrorPage = "true" %>。此指令導致JSP編譯器生成異常例項變數。

<%@ page isErrorPage = "true" %>

<html>
   <head>
      <title>Show Error Page</title>
   </head>
   
   <body>
      <h1>Opps...</h1>
      <p>Sorry, an error occurred.</p>
      <p>Here is the exception stack trace: </p>
      <pre><% exception.printStackTrace(response.getWriter()); %></pre>
   </body>
</html>

訪問main.jsp,您將收到類似於以下內容的輸出:

java.lang.RuntimeException: Error condition!!!
......

Opps...
Sorry, an error occurred.

Here is the exception stack trace:

使用JSTL標籤進行錯誤頁面

您可以使用JSTL標籤編寫錯誤頁面ShowError.jsp。此頁面與上述示例中的邏輯幾乎相同,但結構更好,資訊更多:

<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%@page isErrorPage = "true" %>

<html>
   <head>
      <title>Show Error Page</title>
   </head>
   
   <body>
      <h1>Opps...</h1>
      <table width = "100%" border = "1">
         <tr valign = "top">
            <td width = "40%"><b>Error:</b></td>
            <td>${pageContext.exception}</td>
         </tr>
            
         <tr valign = "top">
            <td><b>URI:</b></td>
            <td>${pageContext.errorData.requestURI}</td>
         </tr>
            
         <tr valign = "top">
            <td><b>Status code:</b></td>
            <td>${pageContext.errorData.statusCode}</td>
         </tr>
            
         <tr valign = "top">
            <td><b>Stack trace:</b></td>
            <td>
               <c:forEach var = "trace" 
                  items = "${pageContext.exception.stackTrace}">
                  <p>${trace}</p>
               </c:forEach>
            </td>
         </tr>
      </table>

   </body>
</html>

訪問main.jsp,將生成以下內容:

Opps...

Error:

java.lang.RuntimeException: Error condition!!!

URI:

/main.jsp

Status code:

500

Stack trace:

org.apache.jsp.main_jsp._jspService(main_jsp.java:65)

org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:68)

javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)

javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

使用Try...Catch塊

如果要在同一頁面中處理錯誤,並希望採取某些操作而不是觸發錯誤頁面,則可以使用try....catch塊。

以下是一個簡單的示例,演示如何使用try...catch塊。讓我們將以下程式碼放入main.jsp中:

<html>
   <head>
      <title>Try...Catch Example</title>
   </head>
   
   <body>
      <%
         try {
            int i = 1;
            i = i / 0;
            out.println("The answer is " + i);
         }
         catch (Exception e) {
            out.println("An exception occurred: " + e.getMessage());
         }
      %>
   </body>
</html>

訪問main.jsp,它應該生成類似於以下內容的輸出:

An exception occurred: / by zero 

JSP - 除錯

在本章中,我們將討論除錯JSP。測試/除錯JSP和servlet始終很困難。JSP和Servlet往往涉及大量客戶端/伺服器互動,這使得錯誤很可能發生,但難以重現。

以下是一些可能有助於您除錯的提示和建議。

使用System.out.println()

System.out.println()易於用作標記,以測試某些程式碼是否正在執行。我們還可以打印出變數值。請考慮以下其他要點:

  • 由於System物件是核心Java物件的一部分,因此可以在任何地方使用它,而無需安裝任何額外的類。這包括Servlet、JSP、RMI、EJB、普通Bean以及獨立應用程式

  • 與在斷點處停止相比,寫入System.out不會過多地干擾應用程式的正常執行流程,這使得在時間至關重要時非常有價值。

以下是使用System.out.println()的語法:

System.out.println("Debugging message");

以下示例演示如何使用System.out.print()

<%@taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>

<html>
   <head><title>System.out.println</title></head>
   <body>
      <c:forEach var = "counter" begin = "1" end = "10" step = "1" >
      
         <c:out value = "${counter-5}"/></br>
         <% System.out.println( "counter = " + pageContext.findAttribute("counter") ); %>
      </c:forEach>
      
   </body>
</html>

訪問上述JSP,瀏覽器將顯示以下結果:

-4
-3
-2
-1
0
1
2
3
4
5

如果您使用的是Tomcat,您還將在日誌目錄中的stdout.log末尾找到這些行。

counter = 1
counter = 2
counter = 3
counter = 4
counter = 5
counter = 6
counter = 7
counter = 8
counter = 9
counter = 10

透過這種方式,您可以將變數和其他資訊引入系統日誌,以分析問題的根本原因或出於各種其他原因。

使用JDB記錄器

J2SE日誌框架旨在為在JVM中執行的任何類提供日誌記錄服務。我們可以利用此框架記錄任何資訊。

讓我們使用JDK記錄器API重寫上述示例:

<%@taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%@page import = "java.util.logging.Logger" %>

<html>
   <head><title>Logger.info</title></head>
   
   <body>
      <% Logger logger = Logger.getLogger(this.getClass().getName());%>

      <c:forEach var = "counter" begin = "1" end = "10" step = "1" >
      <c:set var = "myCount" value = "${counter-5}" />
      <c:out value = "${myCount}"/></br>
         <% String message = "counter = "
            + pageContext.findAttribute("counter") + "myCount = "
            + pageContext.findAttribute("myCount");
            logger.info( message );
         %>
      </c:forEach>
      
   </body>
</html>

上述程式碼將在瀏覽器和stdout.log中生成類似的結果,但您將在stdout.log中獲得其他資訊。我們將使用記錄器的info方法,並且僅出於資訊目的記錄訊息。以下是stdout.log檔案的快照:

24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 1 myCount = -4
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 2 myCount = -3
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 3 myCount = -2
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 4 myCount = -1
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 5 myCount = 0
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 6 myCount = 1
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 7 myCount = 2
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 8 myCount = 3
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 9 myCount = 4
24-Sep-2010 23:31:31 org.apache.jsp.main_jsp _jspService
INFO: counter = 10 myCount = 5

可以使用便捷函式severe()、warning()、info()、config()、fine()、finer()finest()以不同的級別傳送訊息。這裡finest()方法可以用於記錄最精細的資訊,而severe()方法可以用於記錄嚴重的資訊。

您可以使用Log4J框架將訊息記錄到不同的檔案中,具體取決於其嚴重級別和重要性。

除錯工具

NetBeans是一個免費的開源Java整合開發環境,支援開發獨立的Java應用程式和Web應用程式,支援JSP和servlet規範,幷包括一個JSP偵錯程式。

NetBeans支援以下基本除錯功能:

  • 斷點
  • 單步執行程式碼
  • 觀察點

您可以參考NetBeans文件以瞭解上述除錯功能。

使用JDB偵錯程式

您可以使用與除錯小程式或應用程式相同的jdb命令來除錯JSP和servlet。

要除錯JSP或servlet,您可以除錯sun.servlet.http.HttpServer,然後觀察HttpServer如何響應我們從瀏覽器發出的HTTP請求執行JSP/servlet。這與除錯小程式非常相似。不同之處在於,對於小程式,正在除錯的實際程式是sun.applet.AppletViewer

大多數偵錯程式透過自動了解如何除錯小程式來隱藏此細節。在他們對JSP執行相同的操作之前,您必須透過考慮以下事項來幫助您的偵錯程式:

  • 設定偵錯程式的類路徑。這有助於您找到sun.servlet.http.Http-Server和相關類。

  • 設定偵錯程式的類路徑。這有助於您找到您的JSP和支援類,通常是ROOT\WEB-INF\classes

設定好正確的類路徑後,開始除錯sun.servlet.http.HttpServer。您可以在您感興趣的任何JSP中設定斷點,然後使用Web瀏覽器向HttpServer發出對給定JSP的請求(https://:8080/JSPToDebug)。這裡的執行在斷點處停止。

使用註釋

程式碼中的註釋可以以多種方式幫助除錯過程。註釋可以在除錯過程中以多種其他方式使用。

JSP使用Java註釋,單行(// ...)多行(/* ... */)註釋可用於臨時刪除Java程式碼的一部分。如果錯誤消失了,請仔細檢視您剛剛註釋的程式碼並找出問題所在。

客戶端和伺服器標頭

有時,當JSP的行為不符合預期時,檢視原始HTTP請求和響應很有用。如果您熟悉HTTP的結構,您可以讀取請求和響應,並檢視這些標頭中到底發生了什麼。

重要的除錯技巧

以下是有關JSP除錯的一些更多除錯技巧:

  • 要求瀏覽器顯示其正在顯示的頁面的原始內容。這有助於識別格式問題。通常是“檢視”選單下的一個選項。

  • 透過強制重新載入頁面,確保瀏覽器沒有快取先前請求的輸出。使用Netscape Navigator,使用Shift-Reload;使用Internet Explorer使用Shift-Refresh

JSP - 安全性

JavaServer Pages和servlet為Web開發人員提供了多種機制來保護應用程式。透過在應用程式部署描述符中識別資源併為其分配角色,可以宣告性地保護資源。

提供了幾種身份驗證級別,從使用識別符號和密碼的基本身份驗證到使用證書的複雜身份驗證。

基於角色的身份驗證

servlet規範中的身份驗證機制使用一種稱為基於角色的安全的技術。其思想是,您建立角色並按角色限制資源,而不是在使用者級別限制資源。

您可以在檔案tomcat-users.xml中定義不同的角色,該檔案位於Tomcat主目錄下的conf中。此檔案的示例如下所示:

<?xml version = '1.0' encoding = 'utf-8'?>
<tomcat-users>
   <role rolename = "tomcat"/>
   <role rolename = "role1"/>
   <role rolename = "manager"/>
   <role rolename = "admin"/>
   <user username = "tomcat" password = "tomcat" roles = "tomcat"/>
   <user username = "role1" password = "tomcat" roles = "role1"/>
   <user username = "both" password = "tomcat" roles = "tomcat,role1"/>
   <user username = "admin" password = "secret" roles = "admin,manager"/>
</tomcat-users>

此檔案定義了使用者名稱、密碼角色之間簡單的對映。請注意,給定使用者可能具有多個角色;例如,username = "both"位於“tomcat”角色和“role1”角色中。

識別和定義不同的角色後,可以透過使用web.xml檔案中(位於WEB-INF目錄下)的<security-constraint>元素,對不同的Web應用程式資源進行基於角色的安全限制。

以下是web.xml中的一個示例條目:

<web-app>
   ...
   <security-constraint>
      <web-resource-collection>
         <web-resource-name>SecuredBookSite</web-resource-name>
         <url-pattern>/secured/*</url-pattern>
         <http-method>GET</http-method>
         <http-method>POST</http-method>
      </web-resource-collection>
      
      <auth-constraint>
         <description>
            Let only managers use this app
         </description>
         <role-name>manager</role-name>
      </auth-constraint>
   </security-constraint>
   
   <security-role>
      <role-name>manager</role-name>
   </security-role>
   
   <login-config>
      <auth-method>BASIC</auth-method>
   </login-config>
   ...
</web-app>

上述條目將表示:

  • 任何對與/secured/*匹配的URL的HTTP GET或POST請求都將受安全限制。

  • 具有管理者角色的人員可以訪問受保護的資源。

  • login-config元素用於描述BASIC形式的身份驗證。

如果您嘗試瀏覽包含/security目錄的任何URL,將顯示以下對話方塊,要求輸入使用者名稱和密碼。如果您提供使用者“admin”和密碼“secret”,那麼您將可以訪問與/secured/*匹配的URL,因為我們已將使用者admin定義為具有管理者角色的使用者,該使用者被允許訪問此資源。

基於表單的身份驗證

當您使用FORM身份驗證方法時,必須提供一個登入表單以提示使用者輸入使用者名稱和密碼。以下是login.jsp的簡單程式碼。這有助於為相同目的建立表單:

<html>
   <body bgcolor = "#ffffff">
      
      <form method = "POST" action ="j_security_check">
         <table border = "0">
            <tr>
               <td>Login</td>
               <td><input type = "text" name="j_username"></td>
            </tr>
            <tr>
               <td>Password</td>
               <td><input type = "password" name="j_password"></td>
            </tr>
         </table>
         <input type = "submit" value = "Login!">
      </form>
      
   </body>
</html>

這裡您必須確保登入表單必須包含名為j_usernamej_password的表單元素。<form>標籤中的操作必須為j_security_check。必須使用POST作為表單方法。同時,您將需要修改<login-config>標籤以將auth-method指定為FORM:

<web-app>
   ...
   <security-constraint>
      <web-resource-collection>
         <web-resource-name>SecuredBookSite</web-resource-name>
         <url-pattern>/secured/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
      </web-resource-collection>
      
      <auth-constraint>
         <description>Let only managers use this app</description>
         <role-name>manager</role-name>
      </auth-constraint>
   </security-constraint>
   
   <security-role>
      <role-name>manager</role-name>
   </security-role>
   
   <login-config>
      <auth-method>FORM</auth-method>
      <form-login-config>
         <form-login-page>/login.jsp</form-login-page>
         <form-error-page>/error.jsp</form-error-page>
      </form-login-config>
   </login-config>
   ...
</web-app>

現在,當您嘗試訪問任何具有URL /secured/*的資源時,它將顯示上述表單,要求您輸入使用者 ID 和密碼。當容器看到“j_security_check”操作時,它會使用一些內部機制來驗證呼叫方。

如果登入成功並且呼叫方被授權訪問受保護的資源,則容器從那時起使用會話 ID 來識別呼叫方的登入會話。容器使用包含會話 ID 的 cookie 來維護登入會話。伺服器將 cookie 傳送回客戶端,只要呼叫方在後續請求中提供此 cookie,容器就會知道呼叫方是誰。

如果登入失敗,則伺服器會發送回由 form-error-page 設定標識的頁面。

這裡,j_security_check 是使用基於表單登入的應用程式必須為登入表單指定的動作。在同一表單中,您還應該有一個名為j_username 的文字輸入控制元件和一個名為j_password密碼輸入控制元件。當您看到此資訊時,這意味著表單中包含的資訊將提交到伺服器,伺服器將檢查名稱和密碼。如何做到這一點是特定於伺服器的。

檢視標準 Realm 實現以瞭解j_security_check 如何在 Tomcat 容器中工作。

Servlet/JSP 中的程式設計安全

HttpServletRequest 物件提供以下方法,這些方法可用於在執行時挖掘安全資訊:

序號 方法及描述
1

String getAuthType()

getAuthType() 方法返回一個 String 物件,該物件表示用於保護 Servlet 的身份驗證方案的名稱。

2

boolean isUserInRole(java.lang.String role)

isUserInRole() 方法返回一個布林值:如果使用者在給定角色中,則為 true;如果使用者不在給定角色中,則為 false。

3

String getProtocol()

getProtocol() 方法返回一個 String 物件,表示用於傳送請求的協議。可以檢查此值以確定是否使用了安全協議。

4

boolean isSecure()

isSecure() 方法返回一個布林值,表示請求是否使用 HTTPS 發出。值為 true 表示使用了 HTTPS 並且連線是安全的。值為 false 表示請求未使用 HTTPS。

5

Principle getUserPrinciple()

getUserPrinciple() 方法返回一個 java.security.Principle 物件,其中包含當前已認證使用者的名稱。

例如,對於連結到管理人員頁面的 JavaServer 頁面,您可能具有以下程式碼:

<% if (request.isUserInRole("manager")) { %>
   <a href = "managers/mgrreport.jsp">Manager Report</a>
   <a href = "managers/personnel.jsp">Personnel Records</a>
<% } %>

透過檢查 JSP 或 servlet 中使用者的角色,您可以自定義網頁以僅向用戶顯示她可以訪問的專案。如果您需要使用者在身份驗證表單中輸入的使用者名稱,則可以在請求物件中呼叫getRemoteUser 方法。

JSP - 國際化 | i18n | l10n

在本章中,我們將討論 JSP 中國際化的概念。在繼續之前,讓我們瞭解以下三個重要術語:

  • 國際化 (i18n) - 這意味著使網站能夠提供內容的不同版本,這些版本已翻譯成訪問者的語言或國籍。

  • 本地化 (l10n) - 這意味著向網站新增資源以使其適應特定的地理或文化區域,例如將網站翻譯成印地語。

  • 區域設定 (locale) - 這是一個特定的文化或地理區域。它通常被稱為語言符號後跟國家/地區符號,這兩個符號用下劃線分隔。例如,“en_US”表示美國英語區域設定。

在構建全球網站時,需要處理許多事項。本教程不會詳細介紹所有內容,但它將為您提供一個很好的示例,說明您如何透過區分其位置(即區域設定)來為網際網路社群提供不同語言的網頁。

JSP 可以根據請求者的區域設定選擇合適的站點版本,並根據本地語言、文化和要求提供相應的站點版本。以下是請求物件的方法,該方法返回 Locale 物件。

java.util.Locale request.getLocale() 

檢測區域設定

以下是您可以用來檢測請求者的位置、語言以及當然還有區域設定的重要區域設定方法。以下所有方法都顯示在請求者的瀏覽器中設定的國家/地區名稱和語言名稱。

序號 方法及描述
1

String getCountry()

此方法以 ISO 3166 2 個字母格式返回此區域設定的大寫國家/地區程式碼。

2

String getDisplayCountry()

此方法返回適合顯示給使用者的區域設定國家/地區的名稱。

3

String getLanguage()

此方法以 ISO 639 格式返回此區域設定的小寫語言程式碼。

4

String getDisplayLanguage()

此方法返回適合顯示給使用者的區域設定語言的名稱。

5

String getISO3Country()

此方法返回此區域設定國家/地區的三個字母縮寫。

6

String getISO3Language()

此方法返回此區域設定語言的三個字母縮寫。

示例

以下示例顯示如何在 JSP 中顯示請求的語言和關聯的國家/地區:

<%@ page import = "java.io.*,java.util.Locale" %>
<%@ page import = "javax.servlet.*,javax.servlet.http.* "%>
<%
   //Get the client's Locale
   Locale locale = request.getLocale();
   String language = locale.getLanguage();
   String country = locale.getCountry();
%>

<html>
   <head>
      <title>Detecting Locale</title>
   </head>

   <body>
      <center>
         <h1>Detecting Locale</h1>
      </center>
      
      <p align = "center">
         <% 
            out.println("Language : " + language  + "<br />");
            out.println("Country  : " + country   + "<br />");
         %>
      </p>
   </body>
</html>

語言設定

JSP 可以輸出用西歐語言(如英語、西班牙語、德語、法語、義大利語、荷蘭語等)編寫的頁面。這裡重要的是設定 Content-Language 標頭以正確顯示所有字元。

另一個重點是使用 HTML 實體顯示所有特殊字元;例如,"&#241;" 表示"ñ""&#161;" 表示"¡",如下所示:

<%@ page import = "java.io.*,java.util.Locale" %>
<%@ page import = "javax.servlet.*,javax.servlet.http.* "%>

<%
   // Set response content type
   response.setContentType("text/html");
   
   // Set spanish language code.
   response.setHeader("Content-Language", "es");
   String title = "En Español";
%>

<html>
   <head>
      <title><%  out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><%  out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>En Español</p>
         <p>¡Hola Mundo!</p>
      </div>
   </body>
</html>

特定於區域設定的日期

您可以使用java.text.DateFormat 類及其靜態getDateTimeInstance( ) 方法來格式化特定於區域設定的日期和時間。以下是顯示如何格式化特定於給定區域設定的日期的示例:

<%@ page import = "java.io.*,java.util.Locale" %>
<%@ page import = "javax.servlet.*,javax.servlet.http.* "%>
<%@ page import = "java.text.DateFormat,java.util.Date" %>

<%
   String title = "Locale Specific Dates";
   
   //Get the client's Locale
   Locale locale = request.getLocale( );
   
   String date = DateFormat.getDateTimeInstance(
      DateFormat.FULL, 
      DateFormat.SHORT, 
      locale).format(new Date( ));
%>

<html>
   
   <head>
      <title><% out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><% out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>Local Date: <%  out.print(date); %></p>
      </div>
   </body>
</html>

特定於區域設定的貨幣

您可以使用java.txt.NumberFormat 類及其靜態getCurrencyInstance( ) 方法以特定於區域設定的貨幣格式化數字(例如 long 或 double 型別)。以下是顯示如何格式化特定於給定區域設定的貨幣的示例:

<%@ page import = "java.io.*,java.util.Locale" %>
<%@ page import = "javax.servlet.*,javax.servlet.http.* "%>
<%@ page import = "java.text.NumberFormat,java.util.Date" %>

<%
   String title = "Locale Specific Currency";
   
   //Get the client's Locale
   Locale locale = request.getLocale( );
   
   NumberFormat nft = NumberFormat.getCurrencyInstance(locale);
   String formattedCurr = nft.format(1000000);
%>

<html>
   
   <head>
      <title><% out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><% out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>Formatted Currency: <%  out.print(formattedCurr); %></p>
      </div>
   </body>
</html>

特定於區域設定的百分比

您可以使用java.txt.NumberFormat 類及其靜態getPercentInstance( ) 方法獲取特定於區域設定的百分比。以下示例顯示如何格式化特定於給定區域設定的百分比:

<%@ page import = "java.io.*,java.util.Locale" %>
<%@ page import = "javax.servlet.*,javax.servlet.http.* "%>
<%@ page import = "java.text.NumberFormat,java.util.Date" %>

<%
   String title = "Locale Specific Percentage";
   
   //Get the client's Locale
   Locale locale = request.getLocale( );
   
   NumberFormat nft = NumberFormat.getPercentInstance(locale);
   String formattedPerc = nft.format(0.51);
%>

<html>
   
   <head>
      <title><% out.print(title); %></title>
   </head>
   
   <body>
      <center>
         <h1><% out.print(title); %></h1>
      </center>
      
      <div align = "center">
         <p>Formatted Percentage: <%  out.print(formattedPerc); %></p>
      </div>
   </body>
</html>
廣告

© . All rights reserved.