Struts 2 快速指南



基本 MVC 架構

Model View Controller,簡稱MVC,是一種用於開發 Web 應用程式的軟體設計模式。MVC 模式由以下三個部分組成:

  • 模型 (Model) - 最底層,負責維護資料。

  • 檢視 (View) - 負責向用戶顯示全部或部分資料。

  • 控制器 (Controller) - 控制模型和檢視之間互動的軟體程式碼。

MVC 流行的原因在於它將應用程式邏輯與使用者介面層隔離開,並支援關注點分離。控制器接收所有應用程式請求,然後與模型協作準備檢視所需的資料。檢視然後使用控制器準備的資料生成最終的可呈現響應。MVC 抽象可以以圖形方式表示如下。

Struts MVC

模型

模型負責管理應用程式的資料。它響應來自檢視的請求,也響應來自控制器的更新指令。

檢視

這意味著以特定格式呈現資料,由控制器的決定觸發。它們是基於指令碼的模板系統,例如 JSP、ASP、PHP,並且非常易於與 AJAX 技術整合。

控制器

控制器負責響應使用者輸入並對資料模型物件執行互動操作。控制器接收輸入,驗證輸入,然後執行修改資料模型狀態的業務操作。

Struts 2 是一個基於 MVC 的框架。在接下來的章節中,我們將瞭解如何在 Struts 2 中使用 MVC 方法。

Struts 2 - 概述

Struts 2 是一個流行且成熟的 Web 應用程式框架,基於 MVC 設計模式。Struts 2 不僅僅是 Struts 1 的新版本,而是對 Struts 架構的完全重寫。

Webwork 框架最初以 Struts 框架為基礎,其目標是提供一個基於 Struts 的增強和改進的框架,使開發人員更容易進行 Web 開發。

一段時間後,Webwork 框架和 Struts 社群攜手建立了著名的 Struts 2 框架。

Struts 2 框架特性

以下是一些可能促使您考慮使用 Struts 2 的強大特性:

  • POJO 表單和 POJO Action - Struts 2 取消了 Struts 框架中不可或缺的 ActionForm。使用 Struts 2,您可以使用任何 POJO 來接收表單輸入。同樣,您現在也可以將任何 POJO 視為 Action 類。

  • 標籤支援 - Struts 2 改進了表單標籤和新標籤,允許開發人員編寫更少的程式碼。

  • AJAX 支援 - Struts 2 認識到 Web 2.0 技術的興起,並透過建立 AJAX 標籤將 AJAX 支援整合到產品中,此功能與標準 Struts 2 標籤非常相似。

  • 易於整合 - 與 Spring、Tiles 和 SiteMesh 等其他框架的整合現在更容易,Struts 2 提供了各種整合選項。

  • 模板支援 - 支援使用模板生成檢視。

  • 外掛支援 - 可以使用外掛增強和擴充套件核心 Struts 2 行為。Struts 2 提供了許多外掛。

  • 效能分析 - Struts 2 提供整合的效能分析功能來除錯和分析應用程式。此外,Struts 還藉助內建除錯工具提供整合的除錯功能。

  • 易於修改標籤 - 可以使用 Freemarker 模板調整 Struts 2 中的標籤標記。這不需要 JSP 或 Java 知識。基本的 HTML、XML 和 CSS 知識就足以修改標籤。

  • 更少的配置 - Struts 2 透過使用各種設定的預設值來減少配置。除非偏離 Struts 2 設定的預設設定,否則您無需進行配置。

  • 檢視技術 - Struts 2 很好地支援多種檢視選項(JSP、Freemarker、Velocity 和 XSLT)

以上列出了Struts 2 的十大主要特性,使其成為一個企業級框架。

Struts 2 的缺點

儘管 Struts 2 具有許多強大的特性,但當前版本 Struts 2 也有一些需要改進的侷限性。以下是一些主要方面:

  • 較高的學習曲線 - 要將 MVC 與 Struts 一起使用,您必須熟悉標準 JSP、Servlet API 和一個龐大而複雜的框架。

  • 文件不足 - 與標準的 servlet 和 JSP API 相比,Struts 的線上資源較少,許多第一次使用 Struts 的使用者發現 Apache 的線上文件令人困惑且組織混亂。

  • 不夠透明 - 與普通的基於 Java 的 Web 應用程式相比,Struts 應用程式在幕後發生了更多的事情,這使得難以理解該框架。

最後,一個好的框架應該提供通用的行為,以便許多不同型別的應用程式都可以使用它。

Struts 2 是最好的 Web 框架之一,被廣泛用於開發富網際網路應用程式 (RIA)。

Struts 2 - 環境搭建

我們的首要任務是執行一個最小的 Struts 2 應用程式。本章將指導您如何準備開發環境以開始使用 Struts 2。

我假設您已經在計算機上安裝了 JDK(5+)、Tomcat 和 Eclipse。如果您尚未安裝這些元件,請按照以下快速入門步驟操作:

步驟 1 - 安裝 Java 開發工具包 (JDK)

您可以從 Oracle 的 Java 網站下載最新版本的 SDK:Java SE 下載。您將在下載的檔案中找到安裝 JDK 的說明,請按照說明安裝和配置設定。最後,設定 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 檔案中。

在 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 的位置,否則請根據 IDE 的文件進行正確的設定。

步驟 2 - 安裝 Apache Tomcat

您可以從 https://tomcat.apache.org/ 下載最新版本的 Tomcat。下載安裝後,將二進位制分發版解壓縮到方便的位置。

例如,在 Windows 上為 C:\apache-tomcat-6.0.33,或在 Linux/Unix 上為 /usr/local/apachetomcat-6.0.33,並建立指向這些位置的 CATALINA_HOME 環境變數。

您可以透過在 Windows 計算機上執行以下命令來啟動 Tomcat,或者您可以簡單地雙擊 startup.bat。

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

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

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

成功啟動後,Tomcat 包含的預設 Web 應用程式可以透過訪問https://:8080/ 來使用。如果一切正常,則應顯示以下結果:

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

步驟 3 - 安裝 Eclipse (IDE)

本教程中的所有示例均使用 Eclipse IDE 編寫。我建議您在計算機上安裝最新版本的 Eclipse。

要安裝 Eclipse,請從 https://www.eclipse.org/downloads/ 下載最新的 Eclipse 二進位制檔案。下載安裝後,將二進位制分發版解壓縮到方便的位置。

例如,在 Windows 上為 C:\eclipse,或在 Linux/Unix 上為 /usr/local/eclipse,最後適當地設定 PATH 變數。可以透過在 Windows 計算機上執行以下命令來啟動 Eclipse,或者您可以簡單地雙擊 eclipse.exe。

%C:\eclipse\eclipse.exe

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

$/usr/local/eclipse/eclipse

成功啟動後,如果一切正常,則應顯示以下結果:

Eclipse Home page

步驟 4 - 安裝 Struts 2 庫

現在,如果一切正常,則可以繼續安裝 Struts 2 框架。以下是您在計算機上下載和安裝 Struts 2 的簡單步驟。

  • 選擇您是要在 Windows 上還是 Unix 上安裝 Struts 2,然後繼續下一步下載 Windows 的 .zip 檔案和 Unix 的 .tar 檔案。

  • https://struts.apache.org/download.cgi 下載最新版本的 Struts 2 二進位制檔案。

  • 撰寫本教程時,我下載了struts-2.0.14-all.zip,解壓縮下載的檔案後,您將在 C:\struts-2.2.3 中獲得如下所示的目錄結構。

Sturts Directories

第二步是將 zip 檔案解壓縮到任何位置,我在我的 Windows 7 計算機的c:\資料夾中下載並解壓縮了struts-2.2.3-all.zip,以便我將所有 jar 檔案都放在C:\struts-2.2.3\lib中。確保您正確設定了 CLASSPATH 變數,否則執行應用程式時會遇到問題。

Struts 2 - 架構

從高層次來看,Struts2是一個拉取式MVC(或MVC2)框架。Struts2中的模型-檢視-控制器模式由以下五個核心元件實現:

  • Action(動作)
  • 攔截器(Interceptors)
  • 值棧/OGNL
  • 結果/結果型別(Results / Result types)
  • 檢視技術(View technologies)

Struts 2與傳統的MVC框架略有不同,其中Action扮演模型的角色,而不是控制器的角色,儘管兩者之間存在一些重疊。

Struts 2 Architecture

上圖描述了Model(模型)、View(檢視)和Controller(控制器)在Struts2高層次架構中的位置。控制器由Struts2分發器servlet過濾器和攔截器實現,模型由Action實現,檢視是結果型別和結果的組合。值棧和OGNL提供了一個公共執行緒,連線並實現了其他元件之間的整合。

除了上述元件之外,還有許多與配置相關的資訊。包括Web應用程式的配置,以及Action、攔截器、結果等的配置。

這是Struts 2 MVC模式的架構概述。我們將在後續章節中更詳細地介紹每個元件。

請求生命週期(Request Life Cycle)

基於上圖,您可以理解在Struts 2中使用者請求生命週期的工作流程如下:

  • 使用者向伺服器傳送請求,請求某些資源(例如頁面)。

  • 過濾器分發器檢視請求,然後確定相應的Action。

  • 應用已配置的攔截器功能,例如驗證、檔案上傳等。

  • 根據請求的操作執行選定的Action。

  • 如果需要,再次應用已配置的攔截器進行任何後處理。

  • 最後,檢視準備結果並將結果返回給使用者。

Struts 2 - Hello World 示例

正如您已經從Struts 2架構中學到的那樣,當您在Struts 2 Web應用程式中單擊超連結或提交HTML表單時,輸入由控制器收集,然後傳送到稱為Action的Java類。Action執行後,結果會選擇一個資源來呈現響應。該資源通常是JSP,但也可以是PDF檔案、Excel電子表格或Java Applet視窗。

假設您已經構建了開發環境。現在,讓我們繼續構建第一個Hello World Struts2專案。該專案的目的是構建一個Web應用程式,收集使用者的姓名,並顯示“Hello World”以及使用者名稱。

對於任何Struts 2專案,我們都需要建立以下四個元件:

序號 元件和描述
1

Action

建立一個Action類,它將包含完整的業務邏輯並控制使用者、模型和檢視之間的互動。

2

攔截器(Interceptors)

根據需要建立攔截器,或使用現有的攔截器。這是控制器的一部分。

3

檢視(View)

建立JSP來與使用者互動,獲取輸入並呈現最終訊息。

4

配置檔案(Configuration Files)

建立配置檔案來關聯Action、檢視和控制器。這些檔案是struts.xml、web.xml、struts.properties。

我將使用Eclipse IDE,因此所有必需的元件都將在動態Web專案下建立。現在讓我們開始建立動態Web專案。

建立動態Web專案(Create a Dynamic Web Project)

啟動Eclipse,然後選擇檔案 > 新建 > 動態Web專案,輸入專案名稱為HelloWorldStruts2,並按照以下螢幕設定其餘選項:

Hello World Sturts1

在接下來的螢幕中選擇所有預設選項,最後選中生成Web.xml部署描述符選項。這將在Eclipse中為您建立一個動態Web專案。現在選擇視窗 > 顯示檢視 > 專案資源管理器,您將看到如下所示的專案視窗:

Hello World Sturts2

現在將以下檔案從Struts 2 lib資料夾C:\struts-2.2.3\lib複製到我們專案的WEB-INF\lib資料夾。為此,您可以簡單地將所有以下檔案拖放到WEB-INF\lib資料夾中。

  • commons-fileupload-x.y.z.jar
  • commons-io-x.y.z.jar
  • commons-lang-x.y.jar
  • commons-logging-x.y.z.jar
  • commons-logging-api-x.y.jar
  • freemarker-x.y.z.jar
  • javassist-.xy.z.GA
  • ognl-x.y.z.jar
  • struts2-core-x.y.z.jar
  • xwork-core.x.y.z.jar

建立Action類(Create Action Class)

Action類是Struts 2應用程式的關鍵,我們在Action類中實現大部分業務邏輯。因此,讓我們在Java資源 > src下建立一個名為HelloWorldAction.java的java檔案,包名為com.tutorialspoint.struts2,內容如下所示。

當用戶單擊URL時,Action類會響應使用者的操作。執行Action類的一個或多個方法,並返回一個String結果。根據結果的值,將呈現特定的JSP頁面。

package com.tutorialspoint.struts2;

public class HelloWorldAction {
   private String name;

   public String execute() throws Exception {
      return "success";
   }
   
   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

這是一個非常簡單的類,只有一個名為“name”的屬性。我們為“name”屬性提供了標準的getter和setter方法,以及一個返回字串“success”的execute方法。

Struts 2框架將建立HelloWorldAction類的物件,並在響應使用者操作時呼叫execute方法。您可以將業務邏輯放在此方法中,該方法最終返回String常量。換句話說,對於每個URL,您都必須實現一個Action類,您可以直接使用該類名作為您的Action名稱,也可以使用struts.xml檔案將其對映到其他名稱,如下所示。

建立檢視(Create a View)

我們需要一個JSP來呈現最終訊息,當預定義的Action發生時,Struts 2框架將呼叫此頁面,此對映將在struts.xml檔案中定義。因此,讓我們在Eclipse專案中的WebContent資料夾中建立下面的jsp檔案HelloWorld.jsp。為此,右鍵單擊專案資源管理器中的WebContent資料夾,然後選擇新建 > JSP檔案

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>

<html>
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      Hello World, <s:property value = "name"/>
   </body>
</html>

taglib指令告訴Servlet容器,此頁面將使用Struts 2標籤,並且這些標籤將以s開頭。

s:property標籤顯示Action類屬性“name”的值,該值由HelloWorldAction類的getName()方法返回。

建立主頁(Create Main Page)

我們還需要在WebContent資料夾中建立index.jsp。此檔案將作為初始操作URL,使用者可以單擊它來告訴Struts 2框架呼叫HelloWorldAction類的定義方法並呈現HelloWorld.jsp檢視。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      <h1>Hello World From Struts2</h1>
      <form action = "hello">
         <label for = "name">Please enter your name</label><br/>
         <input type = "text" name = "name"/>
         <input type = "submit" value = "Say Hello"/>
      </form>
   </body>
</html>

上面檢視檔案中定義的hello Action將使用struts.xml檔案對映到HelloWorldAction類及其execute方法。當用戶單擊“提交”按鈕時,它將導致Struts 2框架執行HelloWorldAction類中定義的execute方法,並根據方法的返回值選擇和呈現相應的檢視作為響應。

配置檔案(Configuration Files)

我們需要一個對映來將URL、HelloWorldAction類(模型)和HelloWorld.jsp(檢視)繫結在一起。對映告訴Struts 2框架哪個類將響應使用者的操作(URL),將執行該類的哪個方法,以及根據該方法返回的String結果呈現哪個檢視。

因此,讓我們建立一個名為struts.xml的檔案。由於Struts 2要求struts.xml位於classes資料夾中。因此,在WebContent/WEB-INF/classes資料夾下建立struts.xml檔案。Eclipse預設情況下不會建立“classes”資料夾,因此您需要自己建立。為此,右鍵單擊專案資源管理器中的WEB-INF資料夾,然後選擇新建 > 資料夾。您的struts.xml應該如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   
   <package name = "helloworld" extends = "struts-default">
     <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
      </action>
   </package>
</struts>

關於上述配置檔案,需要理解一些內容。在這裡,我們將常量struts.devMode設定為true,因為我們在開發環境中工作,我們需要檢視一些有用的日誌訊息。然後,我們定義一個名為helloworld的包。

當您想要將Action分組在一起時,建立包非常有用。在我們的示例中,我們將Action命名為“hello”,它對應於URL/hello.action,並由HelloWorldAction.class支援。當呼叫URL/hello.action時,將執行HelloWorldAction.classexecute方法。如果execute方法的結果返回“success”,那麼我們將使用者帶到HelloWorld.jsp

下一步是建立一個web.xml檔案,它是任何對Struts 2的請求的入口點。Struts2應用程式的入口點將是在部署描述符(web.xml)中定義的過濾器。因此,我們將在web.xml中定義org.apache.struts2.dispatcher.FilterDispatcher類的條目。web.xml檔案需要在WebContent下的WEB-INF資料夾下建立。當您建立專案時,Eclipse已經為您建立了一個web.xml檔案的框架。因此,讓我們修改它如下:

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee" 
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">
   
   <display-name>Struts 2</display-name>
   
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
   
   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

我們指定index.jsp作為我們的歡迎檔案。然後我們配置Struts2過濾器在所有URL上執行(即,任何與模式/*匹配的URL)。

啟用詳細日誌(To Enable Detailed Log)

透過在WEB-INF/classes資料夾下建立logging.properties檔案,您可以在使用Struts 2時啟用完整的日誌記錄功能。在您的屬性檔案中保留以下兩行:

org.apache.catalina.core.ContainerBase.[Catalina].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].handlers = \
   java.util.logging.ConsoleHandler

預設的logging.properties指定了一個ConsoleHandler用於將日誌記錄路由到stdout,還有一個FileHandler。可以使用SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST或ALL設定處理程式的日誌級別閾值。

就是這樣。我們準備使用Struts 2框架執行我們的Hello World應用程式。

應用程式執行步驟(Procedure for Executing the Application)

右鍵單擊專案名稱,然後單擊匯出 > WAR檔案以建立WAR檔案。

然後將此WAR部署到Tomcat的webapps目錄。

最後,啟動Tomcat伺服器並嘗試訪問URLhttps://:8080/HelloWorldStruts2/index.jsp。這將顯示以下螢幕:

Hello World Struts4

輸入值“Struts2”並提交頁面。您應該看到下一頁

Hello World Struts5

請注意,您可以在struts.xml檔案中將index定義為Action,在這種情況下,您可以將索引頁面稱為https://:8080/HelloWorldStruts2/index.action。請檢視如何在下面將index定義為Action:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">

      <action name = "index">
         <result >/index.jsp</result>
      </action>

      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
      </action>

   </package>
</struts>

Struts 2 - 配置檔案(Struts 2 - Configuration Files)

本章將引導您完成Struts 2應用程式所需的 基本配置。在這裡,我們將瞭解如何在一些重要的配置檔案(如web.xml、struts.xml、strutsconfig.xmlstruts.properties)的幫助下進行配置。

說實話,您只需使用web.xmlstruts.xml配置檔案就可以開始工作(正如您在我們上一章中已經看到的那樣,我們的示例使用了這兩個檔案)。但是,為了您的知識,我們還將解釋其他檔案。

web.xml檔案

web.xml配置檔案是一個J2EE配置檔案,它決定了servlet容器如何處理HTTP請求的元素。它嚴格來說不是Struts2配置檔案,但是它是Struts2工作必需的一個配置檔案。

如前所述,此檔案為任何Web應用程式提供了一個入口點。Struts2應用程式的入口點將是在部署描述符(web.xml)中定義的過濾器。因此,我們將在web.xml中定義一個FilterDispatcher類的入口。web.xml檔案需要建立在WebContent/WEB-INF資料夾下。

如果您在沒有模板或生成它的工具(例如Eclipse或Maven2)的幫助下開始,那麼這是您需要配置的第一個配置檔案。

以下是我們在上一個示例中使用的web.xml檔案的內容。

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee" 
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">
   
   <display-name>Struts 2</display-name>
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
   
   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

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

</web-app>

請注意,我們將Struts 2過濾器對映到/*,而不是/*.action,這意味著所有URL都將由Struts過濾器解析。我們將在講解註解章節時對此進行介紹。

struts.xml檔案

struts.xml檔案包含您在開發操作時將修改的配置資訊。此檔案可用於覆蓋應用程式的預設設定,例如struts.devMode = false以及在屬性檔案中定義的其他設定。此檔案可以在WEB-INF/classes資料夾下建立。

讓我們看一下我們在上一章中解釋的“Hello World”示例中建立的struts.xml檔案。

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
     
      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
      </action>
      
      <-- more actions can be listed here -->

   </package>
   <-- more packages can be listed here -->

</struts>

首先要注意的是DOCTYPE。所有Struts配置檔案都需要具有正確的doctype,如我們的示例所示。是根標籤元素,我們使用標籤在其中宣告不同的包。這裡的允許配置的分離和模組化。當您擁有大型專案並且專案被分成不同的模組時,這非常有用。

例如,如果您的專案有三個領域——business_application、customer_application和staff_application,那麼您可以建立三個包並將相關的操作儲存在相應的包中。

package標籤具有以下屬性:

序號 屬性 & 描述
1

name (必需)

包的唯一識別符號

2

extends

此包擴充套件自哪個包?預設情況下,我們使用struts-default作為基本包。

3

abstract

如果標記為true,則該包不可用於終端使用者使用。

4

namespace

操作的唯一名稱空間

constant標籤以及name和value屬性應用於覆蓋在default.properties中定義的任何以下屬性,就像我們剛剛設定struts.devMode屬性一樣。設定struts.devMode屬性允許我們在日誌檔案中檢視更多除錯訊息。

我們為要訪問的每個URL定義action標籤,並定義一個包含execute()方法的類,每當我們訪問相應的URL時,都會訪問該方法。

結果確定操作執行後返回到瀏覽器的內容。從操作返回的字串應該是結果的名稱。結果如上所述按操作配置,或者作為“全域性”結果配置,可用於包中的每個操作。結果具有可選的nametype屬性。預設名稱值為“success”。

struts.xml檔案可能會隨著時間的推移而變得很大,因此透過包將其分解是一種模組化的方法,但Struts提供了另一種模組化struts.xml檔案的方法。您可以將檔案拆分成多個xml檔案,並以如下方式匯入它們。

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <include file="my-struts1.xml"/>
   <include file="my-struts2.xml"/>
</struts>

我們尚未介紹的另一個配置檔案是struts-default.xml。此檔案包含Struts的標準配置設定,對於您99.99%的專案,您無需更改這些設定。因此,我們不會對此檔案進行詳細介紹。如果您有興趣,請檢視struts2-core-2.2.3.jar檔案中提供的default.properties檔案。

struts-config.xml檔案

struts-config.xml配置檔案是Web客戶端中檢視和模型元件之間的連結,但對於您99.99%的專案,您無需更改這些設定。

配置檔案基本上包含以下主要元素:

序號 攔截器 & 描述
1

struts-config

這是配置檔案的根節點。

2

form-beans

在這裡,您可以將ActionForm子類對映到名稱。您在strutsconfig.xml檔案的其餘部分甚至在JSP頁面上使用此名稱作為ActionForm的別名。

3

global forwards

此部分將Web應用程式上的頁面對映到名稱。您可以使用此名稱來引用實際頁面。這避免了在網頁上硬編碼URL。

4

action-mappings

在這裡,您可以宣告表單處理程式,它們也被稱為操作對映。

5

controller

此部分配置Struts內部結構,在實際情況下很少使用。

6

plug-in

此部分告訴Struts在哪裡可以找到您的屬性檔案,這些檔案包含提示和錯誤訊息

以下是struts-config.xml檔案示例:

<?xml version = "1.0" Encoding = "ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
   "http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">

<struts-config>

   <!-- ========== Form Bean Definitions ============ -->
   <form-beans>
      <form-bean name = "login" type = "test.struts.LoginForm" />
   </form-beans>

   <!-- ========== Global Forward Definitions ========= -->
   <global-forwards>
   </global-forwards>

   <!-- ========== Action Mapping Definitions ======== -->
   <action-mappings>
      <action
         path = "/login"
         type = "test.struts.LoginAction" >

         <forward name = "valid" path = "/jsp/MainMenu.jsp" />
         <forward name = "invalid" path = "/jsp/LoginView.jsp" />
      </action>
   </action-mappings>

   <!-- ========== Controller Definitions ======== -->
   <controller contentType = "text/html;charset = UTF-8"
      debug = "3" maxFileSize = "1.618M" locale = "true" nocache = "true"/>

</struts-config>

有關struts-config.xml檔案的更多詳細資訊,請檢視您的Struts文件。

struts.properties檔案

此配置檔案提供了一種更改框架預設行為的機制。實際上,struts.properties配置檔案中包含的所有屬性也可以使用init-paramweb.xml中配置,也可以使用struts.xml配置檔案中的constant標籤配置。但是,如果您希望將事物分開並使其更特定於Struts,則可以在WEB-INF/classes資料夾下建立此檔案。

在此檔案中配置的值將覆蓋在default.properties中配置的預設值,default.properties包含在struts2-core-x.y.z.jar發行版中。您可以考慮使用struts.properties檔案更改一些屬性:

### When set to true, Struts will act much more friendly for developers
struts.devMode = true

### Enables reloading of internationalization files
struts.i18n.reload = true

### Enables reloading of XML configuration files
struts.configuration.xml.reload = true

### Sets the port that the server is run on
struts.url.http.port = 8080

這裡任何以hash (#)開頭的行都將被視為註釋,並將被Struts 2忽略。

Struts 2 - Action

Action是Struts2框架的核心,就像任何MVC(模型-檢視-控制器)框架一樣。每個URL都對映到一個特定的action,該action提供處理請求所需的處理邏輯。

但是action還在其他兩個重要方面發揮作用。首先,action在將資料從請求傳輸到檢視(無論是JSP還是其他型別的結果)的過程中發揮著重要作用。其次,action必須協助框架確定哪個結果應該呈現將在對請求的響應中返回的檢視。

建立Action

Struts2中action的唯一要求是必須有一個不帶引數的方法返回String或Result物件,並且必須是POJO。如果未指定不帶引數的方法,則預設行為是使用execute()方法。

您可以選擇擴充套件ActionSupport類,該類實現了包括Action介面在內的六個介面。Action介面如下:

public interface Action {
   public static final String SUCCESS = "success";
   public static final String NONE = "none";
   public static final String ERROR = "error";
   public static final String INPUT = "input";
   public static final String LOGIN = "login";
   public String execute() throws Exception;
}

讓我們看一下“Hello World”示例中的action方法:

package com.tutorialspoint.struts2;

public class HelloWorldAction {
   private String name;

   public String execute() throws Exception {
      return "success";
   }
   
   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

為了說明action方法控制檢視這一點,讓我們對execute方法進行以下更改,並擴充套件ActionSupport類,如下所示:

package com.tutorialspoint.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorldAction extends ActionSupport {
   private String name;

   public String execute() throws Exception {
      if ("SECRET".equals(name)) {
         return SUCCESS;
      } else {
         return ERROR;  
      }
   }
   
   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

在這個例子中,我們在execute方法中有一些邏輯來檢視name屬性。如果屬性等於字串"SECRET",我們返回SUCCESS作為結果,否則我們返回ERROR作為結果。因為我們擴充套件了ActionSupport,所以我們可以使用字串常量SUCCESS和ERROR。現在,讓我們修改我們的struts.xml檔案,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction"
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
         <result name = "error">/AccessDenied.jsp</result>
      </action>
   </package>
</struts>

建立檢視(Create a View)

讓我們在eclipse專案的WebContent資料夾中建立下面的jsp檔案HelloWorld.jsp。為此,右鍵單擊專案資源管理器中的WebContent資料夾,然後選擇新建>JSP檔案。如果返回結果為SUCCESS(即Action介面中定義的字串常量“success”),則將呼叫此檔案:

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>

<html>
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      Hello World, <s:property value = "name"/>
   </body>
</html>

以下是在action結果為ERROR(等於字串常量“error”)的情況下框架將呼叫的檔案。以下是AccessDenied.jsp的內容:

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>

<html>  
   <head>
      <title>Access Denied</title>
   </head>
   
   <body>
      You are not authorized to view this page.
   </body>
</html>

我們還需要在WebContent資料夾中建立index.jsp。此檔案將作為初始action URL,使用者可以單擊它來告訴Struts 2框架呼叫HelloWorldAction類的execute方法並呈現HelloWorld.jsp檢視。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>  
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      <h1>Hello World From Struts2</h1>
      <form action = "hello">
         <label for = "name">Please enter your name</label><br/>
         <input type = "text" name = "name"/>
         <input type = "submit" value = "Say Hello"/>
      </form>
   </body>
</html>

就是這樣,web.xml檔案不需要更改,因此讓我們使用我們在“示例”章節中建立的同一個web.xml檔案。現在,我們可以使用Struts 2框架執行我們的Hello World應用程式了。

執行應用程式

右鍵單擊專案名稱,然後單擊匯出>WAR檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URL https://:8080/HelloWorldStruts2/index.jsp。這將顯示以下螢幕:

Hello World Struts4

讓我們輸入一個單詞“SECRET”,您應該會看到以下頁面:

helloworldstruts51

現在輸入除“SECRET”以外的任何單詞,您應該會看到以下頁面:

helloworldstruts6

建立多個Action

您將經常定義多個action來處理不同的請求併為使用者提供不同的URL,因此您將定義如下所示的不同類:

package com.tutorialspoint.struts2;
import com.opensymphony.xwork2.ActionSupport;

class MyAction extends ActionSupport {
   public static String GOOD = SUCCESS;
   public static String BAD = ERROR;
}

public class HelloWorld extends ActionSupport {
   ...
   public String execute() {
      if ("SECRET".equals(name)) return MyAction.GOOD;
      return MyAction.BAD;
   }
   ...
}

public class SomeOtherClass extends ActionSupport {
   ...
   public String execute() {
      return MyAction.GOOD;
   }
   ...
}

您將在struts.xml檔案中配置這些action,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   
   <package name = "helloworld" extends = "struts-default">
      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorld" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
         <result name = "error">/AccessDenied.jsp</result>
      </action>
      
      <action name = "something" 
         class = "com.tutorialspoint.struts2.SomeOtherClass" 
         method = "execute">
         <result name = "success">/Something.jsp</result>
         <result name = "error">/AccessDenied.jsp</result>
      </action>
   </package>
</struts>

正如您在上面的假設示例中看到的,action結果SUCCESSERROR是重複的。

為了解決這個問題,建議您建立一個包含結果結果的類。

Struts 2 - 攔截器

攔截器在概念上與servlet過濾器或JDK的Proxy類相同。攔截器允許在action和框架之外分別實現橫切功能。您可以使用攔截器實現以下功能:

  • 在呼叫action之前提供預處理邏輯。

  • 在呼叫action之後提供後處理邏輯。

  • 捕獲異常,以便可以執行備用處理。

Struts2框架中提供的許多功能都是使用攔截器實現的;

示例包括異常處理、檔案上傳、生命週期回撥等。事實上,由於Struts2將其大部分功能都強調在攔截器上,因此每個action不太可能分配7個或8個攔截器。

Struts2框架攔截器

Struts 2框架提供了一系列開箱即用的攔截器,這些攔截器已預先配置並可以使用。下面列出了一些重要的攔截器:

序號 攔截器 & 描述
1

alias

允許引數在請求之間具有不同的名稱別名。

2

checkbox

透過為未選中複選框新增false引數值來輔助管理複選框。

3

conversionError

將將字串轉換為引數型別時的錯誤資訊放入action的欄位錯誤中。

4

createSession

如果尚不存在HTTP會話,則自動建立一個HTTP會話。

5

debugging

為開發人員提供幾個不同的除錯螢幕。

6

execAndWait

在action在後臺執行時,將使用者傳送到中間等待頁面。

7

exception

將從action丟擲的異常對映到結果,允許透過重定向進行自動異常處理。

8

fileUpload

方便檔案上傳。

9

i18n

在使用者會話期間跟蹤選定的區域設定。

10

logger

透過輸出正在執行的action的名稱來提供簡單的日誌記錄。

11

params

在action上設定請求引數。

12

prepare

這通常用於執行預處理工作,例如設定資料庫連線。

13

profile

允許為action記錄簡單的概要分析資訊。

14

scope

在會話或應用程式範圍內儲存和檢索action的狀態。

15

ServletConfig

為action提供對各種基於servlet的資訊的訪問。

16

timer

以操作執行時間長短的形式提供簡單的效能分析資訊。

17

令牌

檢查操作的有效令牌,以防止重複表單提交。

18

驗證

為操作提供驗證支援。

有關上述攔截器的完整詳細資訊,請參閱 Struts 2 文件。但是,我將向您展示如何在 Struts 應用程式中一般使用攔截器。

如何使用攔截器?

讓我們看看如何將現有的攔截器用於我們的“Hello World”程式。我們將使用**計時器**攔截器,其目的是測量執行操作方法所花費的時間。同時,我使用**引數**攔截器,其目的是將請求引數傳送到操作。您可以嘗試在不使用此攔截器的情況下執行您的示例,您會發現**name**屬性未設定,因為引數無法到達操作。

我們將保留 HelloWorldAction.java、web.xml、HelloWorld.jsp 和 index.jsp 檔案,因為它們已在**示例**章節中建立,但讓我們修改**struts.xml**檔案以新增攔截器,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name = "struts.devMode" value = "true" />
   
   <package name = "helloworld" extends = "struts-default">
      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction"
         method = "execute">
         <interceptor-ref name = "params"/>
         <interceptor-ref name = "timer" />
         <result name = "success">/HelloWorld.jsp</result>
      </action>
   </package>
</struts>

右鍵單擊專案名稱,然後單擊**匯出 > WAR 檔案**以建立 WAR 檔案。然後將此 WAR 部署到 Tomcat 的 webapps 目錄中。最後,啟動 Tomcat 伺服器並嘗試訪問 URL **https://:8080/HelloWorldStruts2/index.jsp**。這將生成以下螢幕:

Hello World Struts 4

現在在給定的文字框中輸入任何單詞,然後單擊“Say Hello”按鈕以執行已定義的操作。現在,如果您檢查生成的日誌,您會發現以下文字:

INFO: Server startup in 3539 ms
27/08/2011 8:40:53 PM 
com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
INFO: Executed action [//hello!execute] took 109 ms.

底部的行是由於**計時器**攔截器生成的,它表明操作總共花費了 109 毫秒。

建立自定義攔截器

在您的應用程式中使用自定義攔截器是提供橫切應用程式功能的一種優雅方式。建立自定義攔截器很容易;需要擴充套件的介面是以下**Interceptor**介面:

public interface Interceptor extends Serializable {
   void destroy();
   void init();
   String intercept(ActionInvocation invocation)
   throws Exception;
}

顧名思義,init() 方法提供了一種初始化攔截器的方法,而 destroy() 方法提供了一種攔截器清理工具。與操作不同,攔截器在請求之間被重用,並且需要是執行緒安全的,特別是 intercept() 方法。

**ActionInvocation**物件提供對執行時環境的訪問。它允許訪問操作本身以及呼叫操作和確定操作是否已被呼叫的方法。

如果您不需要初始化或清理程式碼,則可以擴充套件**AbstractInterceptor**類。這提供了 init() 和 destroy() 方法的預設無操作實現。

建立攔截器類

讓我們在**Java 資源 > src**資料夾中建立以下 MyInterceptor.java 檔案:

package com.tutorialspoint.struts2;

import java.util.*;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class MyInterceptor extends AbstractInterceptor {

   public String intercept(ActionInvocation invocation)throws Exception {

      /* let us do some pre-processing */
      String output = "Pre-Processing"; 
      System.out.println(output);

      /* let us call action or next interceptor */
      String result = invocation.invoke();

      /* let us do some post-processing */
      output = "Post-Processing"; 
      System.out.println(output);

      return result;
   }
}

正如您所注意到的,實際操作將透過**invocation.invoke()**呼叫使用攔截器執行。因此,您可以根據您的要求進行一些預處理和一些後處理。

框架本身透過首次呼叫 ActionInvocation 物件的 invoke() 來啟動該過程。每次呼叫**invoke()**時,ActionInvocation都會查詢其狀態並執行接下來出現的攔截器。當所有已配置的攔截器都已呼叫後,invoke() 方法將導致執行操作本身。

下圖透過請求流程顯示了相同的概念:

ActionInvocation

建立Action類(Create Action Class)

讓我們在**Java 資源 > src**下建立一個名為**com.tutorialspoint.struts2**包的java檔案HelloWorldAction.java,內容如下所示。

package com.tutorialspoint.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorldAction extends ActionSupport {
   private String name;

   public String execute() throws Exception {
      System.out.println("Inside action....");
      return "success";
   }  

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

這是我們在前面示例中看到的同一個類。我們具有“name”屬性的標準 getter 和 setter 方法,以及返回字串“success”的 execute 方法。

建立檢視(Create a View)

讓我們在 Eclipse 專案的 WebContent 資料夾中建立下面的 jsp 檔案**HelloWorld.jsp**。

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>

<html>
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      Hello World, <s:property value = "name"/>
   </body>
</html>

建立主頁(Create Main Page)

我們還需要在 WebContent 資料夾中建立**index.jsp**。此檔案將用作初始操作 URL,使用者可以單擊該 URL 以告訴 Struts 2 框架呼叫 HelloWorldAction 類的已定義方法並呈現 HelloWorld.jsp 檢視。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      <h1>Hello World From Struts2</h1>
      <form action = "hello">
         <label for = "name">Please enter your name</label><br/>
         <input type = "text" name = "name"/>
         <input type = "submit" value = "Say Hello"/>
      </form>
   </body>
</html>

上面檢視檔案中定義的**hello**操作將使用 struts.xml 檔案對映到 HelloWorldAction 類及其 execute 方法。

配置檔案(Configuration Files)

現在,我們需要註冊我們的攔截器,然後像在前面的示例中呼叫預設攔截器一樣呼叫它。要註冊新定義的攔截器,將<interceptors>...</interceptors>標籤直接放在**struts.xml**檔案的<package>標籤下。對於預設攔截器,您可以跳過此步驟,就像我們在前面的示例中所做的那樣。但是在這裡,讓我們註冊並使用它,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">

      <interceptors>
         <interceptor name = "myinterceptor"
            class = "com.tutorialspoint.struts2.MyInterceptor" />
      </interceptors>

      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction" 
         method = "execute">
         <interceptor-ref name = "params"/>
         <interceptor-ref name = "myinterceptor" />
         <result name = "success">/HelloWorld.jsp</result>
      </action>

   </package>
</struts>

需要注意的是,您可以在<package>標籤內註冊多個攔截器,同時您可以在<action>標籤內呼叫多個攔截器。您可以使用不同的操作呼叫相同的攔截器。

web.xml 檔案需要在 WebContent 下的 WEB-INF 資料夾中建立,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee" 
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">
   
   <display-name>Struts 2</display-name>
   
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
   
   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

右鍵單擊專案名稱,然後單擊**匯出 > WAR 檔案**以建立 WAR 檔案。然後將此 WAR 部署到 Tomcat 的 webapps 目錄中。最後,啟動 Tomcat 伺服器並嘗試訪問 URL **https://:8080/HelloWorldStruts2/index.jsp**。這將生成以下螢幕:

Hello World Struts 4

現在在給定的文字框中輸入任何單詞,然後單擊“Say Hello”按鈕以執行已定義的操作。現在,如果您檢查生成的日誌,您會在底部找到以下文字:

Pre-Processing
Inside action....
Post-Processing

堆疊多個攔截器

正如您可以想象的那樣,必須為每個操作配置多個攔截器很快就會變得極其難以管理。因此,攔截器使用攔截器堆疊進行管理。這是一個示例,直接來自 strutsdefault.xml 檔案:

<interceptor-stack name = "basicStack">
   <interceptor-ref name = "exception"/>
   <interceptor-ref name = "servlet-config"/>
   <interceptor-ref name = "prepare"/>
   <interceptor-ref name = "checkbox"/>
   <interceptor-ref name = "params"/>
   <interceptor-ref name = "conversionError"/>
</interceptor-stack>

上述堆疊稱為**basicStack**,可在您的配置中使用,如下所示。此配置節點位於<package .../>節點下。每個<interceptor-ref .../>標籤都引用在當前攔截器堆疊之前已配置的攔截器或攔截器堆疊。因此,在配置初始攔截器和攔截器堆疊時,確保所有攔截器和攔截器堆疊配置的名稱唯一非常重要。

我們已經看到如何將攔截器應用於操作,應用攔截器堆疊沒有什麼不同。事實上,我們使用完全相同的標籤:

<action name = "hello" class = "com.tutorialspoint.struts2.MyAction">
   <interceptor-ref name = "basicStack"/>
   <result>view.jsp</result>
</action

註冊“basicStack”將使用 hello 操作註冊所有六個攔截器的完整堆疊。需要注意的是,攔截器的執行順序與它們的配置順序相同。例如,在上述情況下,異常將首先執行,第二個將是 servlet-config,依此類推。

Struts 2 - 結果和結果型別

如前所述,**<results>**標籤在 Struts2 MVC 框架中扮演**檢視**的角色。操作負責執行業務邏輯。執行業務邏輯後的下一步是使用**<results>**標籤顯示檢視。

通常,結果會附加一些導航規則。例如,如果操作方法是驗證使用者身份,則有三種可能的結果。

  • 登入成功
  • 登入失敗 - 使用者名稱或密碼不正確
  • 帳戶已鎖定

在這種情況下,操作方法將配置三種可能的結果字串和三個不同的檢視以呈現結果。我們已經在前面的示例中看到了這一點。

但是,Struts2 不會將您與使用 JSP 作為檢視技術捆綁在一起。畢竟,MVC 範例的全部目的是保持各層獨立且高度可配置。例如,對於 Web2.0 客戶端,您可能希望返回 XML 或 JSON 作為輸出。在這種情況下,您可以為 XML 或 JSON 建立一個新的結果型別來實現此目的。

Struts 附帶許多預定義的**結果型別**,以及我們已經看到的預設結果型別**dispatcher**,它用於排程到 JSP 頁面。Struts 允許您使用其他標記語言作為檢視技術來呈現結果,流行的選擇包括**Velocity、Freemaker、XSLT**和**Tiles**。

排程程式結果型別

**dispatcher**結果型別是預設型別,如果未指定其他結果型別,則使用它。它用於轉發到伺服器上的 servlet、JSP、HTML 頁面等。它使用_RequestDispatcher.forward()_方法。

我們在之前的示例中看到了“簡寫”版本,我們提供了 JSP 路徑作為結果標籤的主體。

<result name = "success">
   /HelloWorld.jsp
</result>

我們也可以使用<result...>元素內的<param name = "location">標籤指定 JSP 檔案,如下所示:

<result name = "success" type = "dispatcher">
   <param name = "location">
      /HelloWorld.jsp
   </param >
</result>

我們還可以提供一個**parse**引數,預設為 true。parse 引數確定是否解析 location 引數以獲取 OGNL 表示式。

FreeMaker 結果型別

在此示例中,我們將瞭解如何使用**FreeMaker**作為檢視技術。Freemaker 是一個流行的模板引擎,用於使用預定義的模板生成輸出。現在讓我們建立一個名為**hello.fm**的 Freemaker 模板檔案,內容如下:

Hello World ${name}

上面的檔案是一個模板,其中**name**是一個引數,將使用定義的操作從外部傳遞。您將此檔案儲存在您的 CLASSPATH 中。

接下來,讓我們修改**struts.xml**以指定結果,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">

      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction"
         method = "execute">
         <result name = "success" type = "freemarker">
            <param name = "location">/hello.fm</param>
         </result>
      </action>
      
   </package>

</struts>

讓我們保留 HelloWorldAction.java、HelloWorldAction.jsp 和 index.jsp 檔案,就像我們在示例章節中建立它們一樣。

現在右鍵單擊專案名稱,然後單擊**匯出 > WAR 檔案**以建立 WAR 檔案。

然後將此 WAR 部署到 Tomcat 的 webapps 目錄中。最後,啟動 Tomcat 伺服器並嘗試訪問 URL **https://:8080/HelloWorldStruts2/index.jsp**。這將生成以下螢幕。

Hello World Struts 4

輸入值“Struts2”並提交頁面。您應該會看到下一頁。

Hello World Struts 5

如您所見,這與 JSP 檢視完全相同,只是我們沒有使用 JSP 作為檢視技術。在此示例中,我們使用了 Freemaker。

重定向結果型別

**redirect**結果型別呼叫標準_response.sendRedirect()_方法,導致瀏覽器向給定位置建立新請求。

我們可以在<result...>元素的主體中或作為<param name = "location">元素提供位置。Redirect 也支援**parse**引數。這是一個使用 XML 配置的示例:

<action name = "hello" 
   class = "com.tutorialspoint.struts2.HelloWorldAction"
   method = "execute">
   <result name = "success" type = "redirect">
      <param name = "location">
         /NewWorld.jsp
      </param >
   </result>
</action>

只需修改您的 struts.xml 檔案以定義上面提到的重定向型別,並建立一個新檔案 NewWorld.jpg,每當 hello 操作返回成功時,您將被重定向到該檔案。您可以檢視Struts 2 重定向操作示例以更好地理解。

Struts 2 - 值棧/OGNL

值棧

值棧是一組多個物件,它們按以下順序儲存以下物件:

序號 物件和說明
1

臨時物件

在頁面執行期間會建立各種臨時物件。例如,在 JSP 標籤中迴圈遍歷的集合的當前迭代值。

2

模型物件

如果您在 Struts 應用程式中使用模型物件,則當前模型物件將位於值棧上的操作之前。

3

操作物件

這將是正在執行的當前操作物件。

4

命名物件

這些物件包括 #application、#session、#request、#attr 和 #parameters,並引用相應的 servlet 作用域。

可以透過為 JSP、Velocity 或 Freemarker 提供的標籤訪問值棧。我們將在單獨的章節中學習各種標籤,這些標籤用於獲取和設定 struts 2.0 值棧。您可以在操作中獲取 valueStack 物件,如下所示:

ActionContext.getContext().getValueStack()

獲得 ValueStack 物件後,可以使用以下方法操作該物件:

序號 ValueStack 方法及描述
1

Object findValue(String expr)

根據預設搜尋順序,透過對棧中表達式求值來查詢值。

2

CompoundRoot getRoot()

獲取儲存推送到棧中物件的 CompoundRoot。

3

Object peek()

獲取棧頂物件,但不改變棧。

4

Object pop()

獲取棧頂物件並將其從棧中移除。

5void push(Object o)

將此物件放入棧頂。

6

void set(String key, Object o)

使用給定的鍵設定棧上的物件,以便可以透過 findValue(key,...) 檢索。

7

void setDefaultType(Class defaultType)

設定預設型別,如果獲取值時未提供型別,則轉換為該型別。

8

void setValue(String expr, Object value)

嘗試使用預設搜尋順序,使用給定的表示式設定棧中bean上的屬性。

9

int size()

獲取棧中物件的個數。

OGNL

**物件圖導航語言**(OGNL) 是一種強大的表示式語言,用於引用和操作 ValueStack 上的資料。OGNL 還幫助進行資料傳輸和型別轉換。

OGNL 非常類似於 JSP 表示式語言。OGNL 基於在上下文中擁有根物件或預設物件的概念。可以使用井號符號 (#) 表示法引用預設物件或根物件的屬性。

如前所述,OGNL 基於上下文,Struts 構建了一個 ActionContext 對映以與 OGNL 一起使用。ActionContext 對映包含以下內容:

  • **Application** - 應用範圍的變數

  • **Session** - 會話範圍的變數

  • **Root / value stack** - 所有操作變數都儲存在此處

  • **Request** - 請求範圍的變數

  • **Parameters** - 請求引數

  • **Attributes** - 儲存在頁面、請求、會話和應用程式範圍中的屬性

重要的是要理解,Action 物件始終在 ValueStack 中可用。因此,如果您的 Action 物件具有屬性 **“x”** 和 **“y”**,則您可以直接使用它們。

ActionContext 中的物件使用井號符號 (#) 引用,但是 ValueStack 中的物件可以直接引用。

例如,如果 **employee** 是 action 類的一個屬性,則可以按如下方式引用:

<s:property value = "name"/>

而不是

<s:property value = "#name"/>

如果會話中有一個名為“login”的屬性,則可以按如下方式檢索它:

<s:property value = "#session.login"/>

OGNL 還支援處理集合——即 Map、List 和 Set。例如,要顯示顏色下拉列表,您可以執行以下操作:

<s:select name = "color" list = "{'red','yellow','green'}" />

OGNL 表示式能夠巧妙地將“red”、“yellow”、“green”解釋為顏色,並基於此構建列表。

在接下來的章節中學習不同的標籤時,將廣泛使用 OGNL 表示式。因此,與其單獨檢視它們,不如在表單標籤/控制元件標籤/資料標籤和 Ajax 標籤部分中使用一些示例來檢視它們。

ValueStack/OGNL 示例

建立Action

讓我們考慮以下 action 類,我們訪問 ValueStack,然後設定一些鍵,我們將在檢視(即 JSP 頁面)中使用 OGNL 訪問這些鍵。

package com.tutorialspoint.struts2;

import java.util.*; 

import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class HelloWorldAction extends ActionSupport {
   private String name;

   public String execute() throws Exception {
      ValueStack stack = ActionContext.getContext().getValueStack();
      Map<String, Object> context = new HashMap<String, Object>();

      context.put("key1", new String("This is key1")); 
      context.put("key2", new String("This is key2"));
      stack.push(context);

      System.out.println("Size of the valueStack: " + stack.size());
      return "success";
   }  

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

實際上,Struts 2 在執行時將您的 action 新增到 ValueStack 的頂部。因此,將內容放入 ValueStack 的常用方法是為 Action 類中的值新增 getter/setter,然後使用 <s:property> 標籤訪問這些值。但我向您展示了 ActionContext 和 ValueStack 在 struts 中的工作原理。

建立檢視

讓我們在 Eclipse 專案的 WebContent 資料夾中建立以下 jsp 檔案 **HelloWorld.jsp**。如果 action 返回成功,則將顯示此檢視:

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>

<html>
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      Entered value : <s:property value = "name"/><br/>
      Value of key 1 : <s:property value = "key1" /><br/>
      Value of key 2 : <s:property value = "key2" /> <br/>
   </body>
</html>

我們還需要在 WebContent 資料夾中建立 **index.jsp**,其內容如下:

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      <h1>Hello World From Struts2</h1>
      <form action = "hello">
         <label for = "name">Please enter your name</label><br/>
         <input type = "text" name = "name"/>
         <input type = "submit" value = "Say Hello"/>
      </form>
   </body>
</html>

配置檔案(Configuration Files)

以下是 **struts.xml** 檔案的內容:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">

      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
      </action>

   </package>
</struts>

以下是 **web.xml** 檔案的內容:

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee" 
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">
   
   <display-name>Struts 2</display-name>
   
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
   
   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

右鍵單擊專案名稱,然後單擊 **匯出 > WAR 檔案** 以建立 WAR 檔案。然後將此 WAR 部署到 Tomcat 的 webapps 目錄中。

最後,啟動 Tomcat 伺服器並嘗試訪問 URL **https://:8080/HelloWorldStruts2/index.jsp**。這將產生以下螢幕

Hello World Struts 4

現在在給定的文字框中輸入任何單詞,然後單擊“Say Hello”按鈕以執行已定義的操作。現在,如果您檢查生成的日誌,您將在底部找到以下文字:

Size of the valueStack: 3

這將顯示以下螢幕,該螢幕將顯示您輸入的任何值以及我們在 ValueStack 上設定的 key1 和 key2 的值。

Struts 2 - 檔案上傳

Struts 2 框架提供對使用“基於表單的 HTML 檔案上傳”處理檔案上傳的內建支援。上傳檔案時,它通常會儲存在臨時目錄中,並且您的 Action 類應該處理或將它們移動到永久目錄,以確保資料不會丟失。

**注意** - 伺服器可能已實施安全策略,禁止您寫入臨時目錄和屬於您的 Web 應用程式的目錄以外的目錄。

Struts 中的檔案上傳可以透過預定義的攔截器(稱為 **FileUpload** 攔截器)實現,該攔截器透過 org.apache.struts2.interceptor.FileUploadInterceptor 類提供,並作為 **defaultStack** 的一部分包含在內。您仍然可以在 struts.xml 中使用它來設定各種引數,如下所示。

建立檢視檔案

讓我們從建立檢視開始,這將需要瀏覽和上傳選定的檔案。因此,讓我們建立一個使用普通 HTML 上傳表單的 **index.jsp**,允許使用者上傳檔案:

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>File Upload</title>
   </head>
   
   <body>
      <form action = "upload" method = "post" enctype = "multipart/form-data">
         <label for = "myFile">Upload your file</label>
         <input type = "file" name = "myFile" />
         <input type = "submit" value = "Upload"/>
      </form>
   </body>
</html>

上面的例子需要注意幾點。首先,表單的 enctype 設定為 **multipart/form-data**。應該設定此項,以便檔案上傳攔截器能夠成功處理檔案上傳。下一個需要注意的是表單的操作方法 **upload** 和檔案上傳欄位的名稱 - 即 **myFile**。我們需要此資訊來建立操作方法和 struts 配置。

接下來,讓我們建立一個簡單的 jsp 檔案 **success.jsp** 來顯示檔案上傳結果(如果成功)。

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>

<html>
   <head>
      <title>File Upload Success</title>
   </head>
   
   <body>
      You have successfully uploaded <s:property value = "myFileFileName"/>
   </body>
</html>

如果檔案上傳出現錯誤,則結果檔案 **error.jsp** 如下所示:

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>

<html>
   <head>
      <title>File Upload Error</title>
   </head>
   
   <body>
      There has been an error in uploading the file.
   </body>
</html>

建立Action類(Create Action Class)

接下來,讓我們建立一個名為 **uploadFile.java** 的 Java 類,該類將負責上傳檔案並將該檔案儲存在安全位置:

package com.tutorialspoint.struts2;

import java.io.File;
import org.apache.commons.io.FileUtils;
import java.io.IOException; 

import com.opensymphony.xwork2.ActionSupport;

public class uploadFile extends ActionSupport {
   private File myFile;
   private String myFileContentType;
   private String myFileFileName;
   private String destPath;

   public String execute() {
      /* Copy file to a safe location */
      destPath = "C:/apache-tomcat-6.0.33/work/";

      try {
         System.out.println("Src File name: " + myFile);
         System.out.println("Dst File name: " + myFileFileName);
     	    	 
         File destFile  = new File(destPath, myFileFileName);
         FileUtils.copyFile(myFile, destFile);
  
      } catch(IOException e) {
         e.printStackTrace();
         return ERROR;
      }

      return SUCCESS;
   }
   
   public File getMyFile() {
      return myFile;
   }
   
   public void setMyFile(File myFile) {
      this.myFile = myFile;
   }
   
   public String getMyFileContentType() {
      return myFileContentType;
   }
   
   public void setMyFileContentType(String myFileContentType) {
      this.myFileContentType = myFileContentType;
   }
   
   public String getMyFileFileName() {
      return myFileFileName;
   }
   
   public void setMyFileFileName(String myFileFileName) {
      this.myFileFileName = myFileFileName;
   }
}

**uploadFile.java** 是一個非常簡單的類。需要注意的是,FileUpload 攔截器與 Parameters 攔截器一起為我們完成了所有繁重的工作。

FileUpload 攔截器預設情況下為我們提供了三個引數。它們使用以下模式命名:

  • **[您的檔名引數]** - 這是使用者上傳的實際檔案。在此示例中,它將是“myFile”

  • **[您的檔名引數]ContentType** - 這是上傳檔案的型別。在此示例中,它將是“myFileContentType”

  • **[您的檔名引數]FileName** - 這是上傳的檔名。在此示例中,它將是“myFileFileName”

感謝 Struts 攔截器,這三個引數對我們可用。我們所要做的就是在我們的 Action 類中建立三個名稱正確的引數,這些變數將自動為我們自動連線。因此,在上面的示例中,我們有三個引數和一個操作方法,如果一切順利,它只返回“success”,否則返回“error”。

配置檔案(Configuration Files)

以下是控制檔案上傳過程的 Struts2 配置屬性:

序號 屬性及描述
1

struts.multipart.maxSize

作為檔案上傳接受的檔案的最大大小(以位元組為單位)。預設為 250M。

2

struts.multipart.parser

用於上傳多部分表單的庫。預設為 **jakarta**

3

struts.multipart.saveDir

儲存臨時檔案的位置。預設為 javax.servlet.context.tempdir。

為了更改任何這些設定,您可以在應用程式的 struts.xml 檔案中使用 **constant** 標籤,就像我更改要上傳檔案的最大大小一樣。

讓我們將 **struts.xml** 設定如下:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <constant name = "struts.multipart.maxSize" value = "1000000" />
   <package name = "helloworld" extends = "struts-default">
      <action name = "upload" class = "com.tutorialspoint.struts2.uploadFile">
         <result name = "success">/success.jsp</result>
         <result name = "error">/error.jsp</result>
      </action>
   </package>
</struts>

由於 **FileUpload** 攔截器是攔截器預設堆疊的一部分,因此我們不需要顯式配置它。但是,您可以在 <action> 內新增 <interceptor-ref> 標籤。fileUpload 攔截器接受兩個引數 **(a) maximumSize** 和 **(b) allowedTypes**。

maximumSize 引數設定允許的最大檔案大小(預設為大約 2MB)。allowedTypes 引數是一個逗號分隔的已接受內容 (MIME) 型別列表,如下所示:

<action name = "upload" class = "com.tutorialspoint.struts2.uploadFile">
   <interceptor-ref name = "basicStack">
   <interceptor-ref name = "fileUpload">
      <param name = "allowedTypes">image/jpeg,image/gif</param>
   </interceptor-ref>
   <result name = "success">/success.jsp</result>
   <result name = "error">/error.jsp</result>
</action>

以下是 **web.xml** 檔案的內容:

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee" 
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">
   
   <display-name>Struts 2</display-name>
   
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
   
   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

現在右鍵單擊專案名稱,然後單擊 **匯出 > WAR 檔案** 以建立 WAR 檔案。然後將此 WAR 部署到 Tomcat 的 webapps 目錄中。最後,啟動 Tomcat 伺服器並嘗試訪問 URL **https://:8080/HelloWorldStruts2/upload.jsp**。這將產生以下螢幕:

Hello World Struts 7

現在使用“瀏覽”按鈕選擇檔案“Contacts.txt”,然後單擊上傳按鈕,該按鈕將檔案上傳到您的伺服器,您應該會看到下一頁。您可以檢查上傳的檔案是否已儲存在 C:\apache-tomcat-6.0.33\work 中。

Hello World Struts 8

請注意,FileUpload 攔截器會自動刪除上傳的檔案,因此您必須在刪除上傳的檔案之前以程式設計方式將其儲存在某個位置。

錯誤訊息

fileUplaod 攔截器使用多個預設錯誤訊息鍵:

序號 錯誤訊息鍵及描述
1

struts.messages.error.uploading

無法上傳檔案時發生的常規錯誤。

2

struts.messages.error.file.too.large

上傳的檔案大小超過 maximumSize 指定的大小時發生。

3

struts.messages.error.content.type.not.allowed

上傳的檔案與指定的預期內容型別不匹配時發生。

您可以在 **WebContent/WEB-INF/classes/messages.properties** 資原始檔中覆蓋這些訊息的文字。

Struts 2 - 資料庫訪問

本章將透過簡單的步驟教你如何使用Struts 2訪問資料庫。Struts是一個MVC框架,而不是資料庫框架,但它提供了對JPA/Hibernate整合的優秀支援。我們將在後面的章節中討論Hibernate整合,但在本章中,我們將使用普通的JDBC來訪問資料庫。

本章的第一步是設定和準備我們的資料庫。我使用MySQL作為本例的資料庫。我的機器上已安裝MySQL,並且我建立了一個名為“struts_tutorial”的新資料庫。我建立了一個名為login的表並用一些值填充它。以下是建立和填充表的指令碼。

我的MySQL資料庫使用預設使用者名稱“root”和密碼“root123”。

CREATE TABLE `struts_tutorial`.`login` (
   `user` VARCHAR( 10 ) NOT NULL ,
   `password` VARCHAR( 10 ) NOT NULL ,
   `name` VARCHAR( 20 ) NOT NULL ,
   PRIMARY KEY ( `user` )
) ENGINE = InnoDB;

INSERT INTO `struts_tutorial`.`login` (`user`, `password`, `name`)
VALUES ('scott', 'navy', 'Scott Burgemott');

下一步是下載MySQL Connector jar檔案,並將此檔案放入專案的WEB-INF\lib資料夾中。完成此操作後,我們就可以建立Action類了。

建立Action

Action類具有與資料庫表中的列相對應的屬性。我們有user、passwordname作為String屬性。在action方法中,我們使用user和password引數來檢查使用者是否存在,如果存在,我們就在下一個螢幕中顯示使用者名稱。

如果使用者輸入了錯誤的資訊,我們將再次將其傳送到登入螢幕。

以下是LoginAction.java檔案的內容:

package com.tutorialspoint.struts2;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {

   private String user;
   private String password;
   private String name;

   public String execute() {
      String ret = ERROR;
      Connection conn = null;

      try {
         String URL = "jdbc:mysql:///struts_tutorial";
         Class.forName("com.mysql.jdbc.Driver");
         conn = DriverManager.getConnection(URL, "root", "root123");
         String sql = "SELECT name FROM login WHERE";
         sql+=" user = ? AND password = ?";
         PreparedStatement ps = conn.prepareStatement(sql);
         ps.setString(1, user);
         ps.setString(2, password);
         ResultSet rs = ps.executeQuery();

         while (rs.next()) {
            name = rs.getString(1);
            ret = SUCCESS;
         }
      } catch (Exception e) {
         ret = ERROR;
      } finally {
         if (conn != null) {
            try {
               conn.close();
            } catch (Exception e) {
            }
         }
      }
      return ret;
   }

   public String getUser() {
      return user;
   }

   public void setUser(String user) {
      this.user = user;
   }

   public String getPassword() {
      return password;
   }

   public void setPassword(String password) {
      this.password = password;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

建立主頁(Create Main Page)

現在,讓我們建立一個JSP檔案index.jsp來收集使用者名稱和密碼。我們將根據資料庫檢查使用者名稱和密碼。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Login</title>
   </head>
   
   <body>
      <form action = "loginaction" method = "post">
         User:<br/><input type = "text" name = "user"/><br/>
         Password:<br/><input type = "password" name = "password"/><br/>
         <input type = "submit" value = "Login"/>		
      </form>
   </body>
</html>

建立檢視

現在讓我們建立success.jsp檔案,如果action返回SUCCESS,則將呼叫此檔案,但是如果action返回ERROR,我們將有另一個檢視檔案。

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>

<html>
   <head>
      <title>Successful Login</title>
   </head>
   
   <body>
      Hello World, <s:property value = "name"/>
   </body>
</html>

如果action返回ERROR,則以下是檢視檔案error.jsp

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>

<html>
   <head>
      <title>Invalid User Name or Password</title>
   </head>
   
   <body>
      Wrong user name or password provided.
   </body>
</html>

配置檔案(Configuration Files)

最後,讓我們使用struts.xml配置檔案將所有內容組合在一起,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
   
      <action name = "loginaction" 
         class = "com.tutorialspoint.struts2.LoginAction"
         method = "execute">
         <result name = "success">/success.jsp</result>
         <result name = "error">/error.jsp</result>
      </action>
   
   </package>
</struts>

以下是 **web.xml** 檔案的內容:

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee" 
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">
   
   <display-name>Struts 2</display-name>
   
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
   
   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

現在,右鍵單擊專案名稱,然後單擊匯出> WAR檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URL https://:8080/HelloWorldStruts2/index.jsp。這將生成以下螢幕:

Hello World Struts 9

輸入錯誤的使用者名稱和密碼。你應該看到下一頁。

Hello World Struts 10

現在輸入scott作為使用者名稱,navy作為密碼。你應該看到下一頁。

Hello World Struts 11

Struts 2 - 傳送電子郵件

本章解釋如何使用Struts 2應用程式傳送電子郵件。

對於此練習,你需要從JavaMail API 1.4.4下載並安裝mail.jar,並將mail.jar檔案放入你的WEB-INF\lib資料夾中,然後按照建立action、檢視和配置檔案的標準步驟進行操作。

建立Action

下一步是建立一個負責傳送電子郵件的Action方法。讓我們建立一個名為Emailer.java的新類,其內容如下。

package com.tutorialspoint.struts2;

import java.util.Properties;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import com.opensymphony.xwork2.ActionSupport;

public class Emailer extends ActionSupport {

   private String from;
   private String password;
   private String to;
   private String subject;
   private String body;

   static Properties properties = new Properties();
   static {
      properties.put("mail.smtp.host", "smtp.gmail.com");
      properties.put("mail.smtp.socketFactory.port", "465");
      properties.put("mail.smtp.socketFactory.class",
         "javax.net.ssl.SSLSocketFactory");
      properties.put("mail.smtp.auth", "true");
      properties.put("mail.smtp.port", "465");
   }

   public String execute() {
      String ret = SUCCESS;
      try {
         Session session = Session.getDefaultInstance(properties,  
            new javax.mail.Authenticator() {
               protected PasswordAuthentication 
               getPasswordAuthentication() {
                  return new 
                  PasswordAuthentication(from, password);
               }
            }
         );

         Message message = new MimeMessage(session);
         message.setFrom(new InternetAddress(from));
         message.setRecipients(Message.RecipientType.TO, 
            InternetAddress.parse(to));
         message.setSubject(subject);
         message.setText(body);
         Transport.send(message);
      } catch(Exception e) {
         ret = ERROR;
         e.printStackTrace();
      }
      return ret;
   }

   public String getFrom() {
      return from;
   }

   public void setFrom(String from) {
      this.from = from;
   }

   public String getPassword() {
      return password;
   }

   public void setPassword(String password) {
      this.password = password;
   }

   public String getTo() {
      return to;
   }

   public void setTo(String to) {
      this.to = to;
   }

   public String getSubject() {
      return subject;
   }

   public void setSubject(String subject) {
      this.subject = subject;
   }

   public String getBody() {
      return body;
   }

   public void setBody(String body) {
      this.body = body;
   }

   public static Properties getProperties() {
      return properties;
   }

   public static void setProperties(Properties properties) {
      Emailer.properties = properties;
   }
}

如上面的原始碼所示,Emailer.java具有與下面給出的email.jsp頁面中的表單屬性相對應的屬性。這些屬性是:

  • From - 發件人的電子郵件地址。由於我們使用的是Google的SMTP,因此我們需要一個有效的gtalk ID。

  • Password - 上述帳戶的密碼。

  • To - 傳送電子郵件給誰?

  • Subject - 電子郵件的主題。

  • Body - 實際的電子郵件正文。

我們沒有考慮對上述欄位進行任何驗證,驗證將在下一章中新增。現在讓我們看看execute()方法。execute()方法使用javax Mail庫使用提供的引數傳送電子郵件。如果郵件傳送成功,則action返回SUCCESS,否則返回ERROR。

建立主頁(Create Main Page)

讓我們編寫主頁面JSP檔案index.jsp,它將用於收集上面提到的與電子郵件相關的資訊:

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
   <title>Email Form</title>
   </head>
   
   <body>
      <em>The form below uses Google's SMTP server. 
         So you need to enter a gmail username and password
      </em>
      
      <form action = "emailer" method = "post">
         <label for = "from">From</label><br/>
         <input type = "text" name = "from"/><br/>
         <label for = "password">Password</label><br/>
         <input type = "password" name = "password"/><br/>
         <label for = "to">To</label><br/>
         <input type = "text" name = "to"/><br/>
         <label for = "subject">Subject</label><br/>
         <input type = "text" name = "subject"/><br/>
         <label for = "body">Body</label><br/>
         <input type = "text" name = "body"/><br/>
         <input type = "submit" value = "Send Email"/>
      </form>
   </body>
</html>

建立檢視

我們將使用JSP檔案success.jsp,如果action返回SUCCESS,則將呼叫此檔案,但是如果action返回ERROR,我們將有另一個檢視檔案。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Email Success</title>
   </head>
   
   <body>
      Your email to <s:property value = "to"/> was sent successfully.
   </body>
</html>

如果action返回ERROR,則以下是檢視檔案error.jsp

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Email Error</title>
   </head>
   
   <body>
      There is a problem sending your email to <s:property value = "to"/>.
   </body>
</html>

配置檔案(Configuration Files)

現在讓我們使用struts.xml配置檔案將所有內容組合在一起,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">

      <action name = "emailer" 
         class = "com.tutorialspoint.struts2.Emailer"
         method = "execute">
         <result name = "success">/success.jsp</result>
         <result name = "error">/error.jsp</result>
      </action>

   </package>
</struts>

以下是 **web.xml** 檔案的內容:

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee" 
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">
   
   <display-name>Struts 2</display-name>
   
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>

   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

現在,右鍵單擊專案名稱,然後單擊匯出> WAR檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URL https://:8080/HelloWorldStruts2/index.jsp。這將生成以下螢幕:

Email User Input

輸入所需的資訊並單擊傳送電子郵件按鈕。如果一切順利,你應該看到以下頁面。

Email Successful

Struts 2 - 驗證框架

在本章中,我們將深入探討Struts驗證框架。在Struts核心,我們有驗證框架,它幫助應用程式在執行action方法之前執行規則以執行驗證。

客戶端驗證通常使用Javascript實現。但是,不應該僅僅依賴於客戶端驗證。最佳實踐建議應在應用程式框架的所有級別引入驗證。現在讓我們看看在Struts專案中新增驗證的兩種方法。

在這裡,我們將以一個Employee為例,其姓名和年齡應使用一個簡單的頁面捕獲,我們將進行這兩個驗證以確保使用者始終輸入姓名和年齡,年齡應在28到65之間。

讓我們從示例的主JSP頁面開始。

建立主頁(Create Main Page)

讓我們編寫主頁面JSP檔案index.jsp,它將用於收集上面提到的與Employee相關的資訊。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Employee Form</title>
   </head>

   <body>
      <s:form action = "empinfo" method = "post">
         <s:textfield name = "name" label = "Name" size = "20" />
         <s:textfield name = "age" label = "Age" size = "20" />
         <s:submit name = "submit" label = "Submit" align="center" />
      </s:form>
   </body>
</html>

index.jsp使用Struts標籤,我們還沒有介紹,但我們將在與標籤相關的章節中學習它們。但現在,假設s:textfield標籤列印一個輸入欄位,s:submit列印一個提交按鈕。我們為每個標籤使用了label屬性,它為每個標籤建立標籤。

建立檢視

如果定義的action返回SUCCESS,我們將使用JSP檔案success.jsp。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Success</title>
   </head>
   
   <body>
      Employee Information is captured successfully.
   </body>
</html>

建立Action

因此,讓我們定義一個小的action類Employee,然後新增一個名為validate()的方法,如下所示Employee.java檔案。確保你的action類擴充套件了ActionSupport類,否則你的validate方法將不會執行。

package com.tutorialspoint.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class Employee extends ActionSupport {
   private String name;
   private int age;
   
   public String execute() {
       return SUCCESS;
   }
   
   public String getName() {
       return name;
   }
   
   public void setName(String name) {
       this.name = name;
   }
   
   public int getAge() {
       return age;
   }
   
   public void setAge(int age) {
       this.age = age;
   }

   public void validate() {
      if (name == null || name.trim().equals("")) {
         addFieldError("name","The name is required");
      }
      
      if (age < 28 || age > 65) {
         addFieldError("age","Age must be in between 28 and 65");
      }
   }
}

如上例所示,驗證方法檢查“Name”欄位是否有值。如果沒有提供值,我們將為“Name”欄位新增一個欄位錯誤,並顯示自定義錯誤訊息。其次,我們檢查“Age”欄位的輸入值是否在28到65之間,如果不滿足此條件,我們將在驗證欄位上方新增一個錯誤。

配置檔案(Configuration Files)

最後,讓我們使用struts.xml配置檔案將所有內容組合在一起,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">

      <action name = "empinfo" 
         class = "com.tutorialspoint.struts2.Employee"
         method = "execute">
         <result name = "input">/index.jsp</result>
         <result name = "success">/success.jsp</result>
      </action>

   </package>
</struts>

以下是 **web.xml** 檔案的內容:

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee"
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">

   <display-name>Struts 2</display-name>
   
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>

   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

現在,右鍵單擊專案名稱,然後單擊匯出> WAR檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URL https://:8080/HelloWorldStruts2/index.jsp。這將生成以下螢幕:

Email User Input

現在不要輸入任何必需的資訊,只需單擊提交按鈕。你將看到以下結果:

Error

輸入所需的資訊,但輸入錯誤的“From”欄位,例如將姓名設定為“test”,年齡設定為30,最後單擊提交按鈕。你將看到以下結果:

Success

此驗證如何工作?

當用戶按下提交按鈕時,Struts 2將自動執行validate方法,如果方法內列出的任何“if”語句為真,Struts 2將呼叫其addFieldError方法。如果添加了任何錯誤,則Struts 2將不會繼續呼叫execute方法。相反,Struts 2框架將返回input作為呼叫action的結果。

因此,當驗證失敗且Struts 2返回input時,Struts 2框架將重新顯示index.jsp檔案。由於我們使用了Struts 2表單標籤,Struts 2將自動在表單欄位上方新增錯誤訊息。

這些錯誤訊息是我們指定的,在addFieldError方法呼叫中。addFieldError方法需要兩個引數。第一個是表單欄位名稱,錯誤適用於該名稱,第二個是在該表單欄位上方顯示的錯誤訊息。

addFieldError("name","The name is required");

為了處理input的返回值,我們需要在struts.xml中的action節點中新增以下結果。

<result name = "input">/index.jsp</result>

基於XML的驗證

進行驗證的第二種方法是將xml檔案放在action類旁邊。Struts2基於XML的驗證提供了更多驗證選項,例如電子郵件驗證、整數範圍驗證、表單驗證欄位、表示式驗證、正則表示式驗證、必需驗證、必需字串驗證、字串長度驗證等。

xml檔案需要命名為'[action-class]'-validation.xml'。因此,在本例中,我們建立一個名為Employee-validation.xml的檔案,其內容如下:

<!DOCTYPE validators PUBLIC 
   "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
   "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

<validators>
   <field name = "name">
      <field-validator type = "required">
         <message>
            The name is required.
         </message>
      </field-validator>
   </field>

   <field name = "age">
     <field-validator type = "int">
         <param name = "min">29</param>
         <param name = "max">64</param>
         <message>
            Age must be in between 28 and 65
         </message>
      </field-validator>
   </field>
</validators>

上述XML檔案應理想情況下與類檔案一起儲存在你的CLASSPATH中。讓我們使用以下Employee action類,而沒有validate()方法:

package com.tutorialspoint.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class Employee extends ActionSupport{
   private String name;
   private int age;
   
   public String execute() {
       return SUCCESS;
   }
   
   public String getName() {
       return name;
   }
   
   public void setName(String name) {
       this.name = name;
   }
   
   public int getAge() {
       return age;
   }
   
   public void setAge(int age) {
       this.age = age;
   }
}

其餘設定將與上一個示例相同,現在如果你執行應用程式,它將產生與我們在上一個示例中獲得的結果相同的結果。

使用xml檔案儲存配置的優點是可以將驗證與應用程式程式碼分離。你可以讓開發人員編寫程式碼,讓業務分析師建立驗證xml檔案。需要注意的另一點是預設情況下可用的驗證器型別。

Struts預設情況下還有很多驗證器。常見的驗證器包括日期驗證器、正則表示式驗證器和字串長度驗證器。檢視以下連結瞭解更多詳情Struts - 基於XML的驗證器

Struts2 - 本地化,國際化 (i18n)

國際化 (i18n) 是規劃和實施產品和服務的流程,以便它們可以輕鬆適應特定地區的語言和文化,這個過程稱為本地化。國際化過程稱為翻譯或本地化啟用。

國際化縮寫為i18n,因為該詞以字母“i”開頭,以“n”結尾,第一個i和最後一個n之間有18個字元。

Struts2透過資源包、攔截器和標籤庫在以下位置提供本地化,即國際化 (i18n) 支援:

  • UI標籤

  • 訊息和錯誤。

  • 在action類中。

資源包

Struts2使用資源包為Web應用程式的使用者提供多種語言和區域設定選項。你不必擔心用不同的語言編寫頁面。你只需要為每種你想要的語言建立一個資源包。資源包將包含使用者語言的標題、訊息和其他文字。資源包是包含應用程式預設語言的鍵/值對的檔案。

資原始檔的簡單命名格式為:

bundlename_language_country.properties

這裡,bundlename可以是ActionClass、Interface、SuperClass、Model、Package、全域性資源屬性。下一部分language_country表示國家/地區區域設定,例如,西班牙語(西班牙)區域設定由es_ES表示,英語(美國)區域設定由en_US表示等,其中你可以省略國家/地區部分(可選)。

當你按其鍵引用訊息元素時,Struts框架將按照以下順序搜尋相應的message bundle:

  • ActionClass.properties
  • Interface.properties
  • SuperClass.properties
  • model.properties
  • package.properties
  • struts.properties
  • global.properties

要開發多種語言的應用程式,你應該維護與這些語言/區域設定相對應的多個屬性檔案,並根據鍵/值對定義所有內容。

例如,如果你要為美式英語(預設)、西班牙語和法語開發應用程式,則必須建立三個屬性檔案。在這裡,我將只使用global.properties檔案,你也可以使用不同的屬性檔案來分離不同型別的訊息。

  • global.properties - 預設情況下將應用英語(美國)。

  • global_fr.properties - 這將用於法語區域設定。

  • global_es.properties - 這將用於西班牙語區域設定。

訪問訊息

有幾種方法可以訪問訊息資源,包括getText、text標籤、UI標籤的key屬性以及i18n標籤。讓我們簡要了解一下:

要顯示i18n文字,請在屬性標籤或任何其他標籤(例如UI標籤)中使用對getText的呼叫,如下所示:

<s:property value = "getText('some.key')" />

text標籤從預設資源包(即struts.properties)檢索訊息。

<s:text name = "some.key" />

i18n標籤將任意資源包推入值棧。i18n標籤作用域內的其他標籤可以顯示來自該資源包的訊息。

<s:i18n name = "some.package.bundle">
   <s:text name = "some.key" />
</s:i18n>

大多數UI標籤的key屬性可用於從資源包生成訊息。

<s:textfield key = "some.key" name = "textfieldName"/>

本地化示例

讓我們目標是建立上一章中提到的index.jsp的多語言版本。相同的檔案將按如下方式編寫:

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Employee Form with Multilingual Support</title>
   </head>

   <body>
      <h1><s:text name = "global.heading"/></h1>

      <s:url id = "indexEN" namespace="/" action = "locale" >
         <s:param name = "request_locale" >en</s:param>
      </s:url>
      
      <s:url id = "indexES" namespace="/" action = "locale" >
         <s:param name = "request_locale" >es</s:param>
      </s:url>
      
      <s:url id = "indexFR" namespace="/" action = "locale" >
         <s:param name = "request_locale" >fr</s:param>
      </s:url>

      <s:a href="%{indexEN}" >English</s:a>
      <s:a href="%{indexES}" >Spanish</s:a>
      <s:a href="%{indexFR}" >France</s:a>

      <s:form action = "empinfo" method = "post" namespace = "/">
         <s:textfield name = "name" key = "global.name" size = "20" />
         <s:textfield name = "age" key = "global.age" size = "20" />
         <s:submit name = "submit" key = "global.submit" />
      </s:form>

   </body>
</html>

我們將建立success.jsp檔案,該檔案將在定義的操作返回SUCCESS時呼叫。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
	pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Success</title>
   </head>
   
   <body>
      <s:property value = "getText('global.success')" />
   </body>
</html>

這裡我們需要建立以下兩個操作:(a)第一個操作負責處理Locale並以不同的語言顯示相同的index.jsp檔案;(b)另一個操作負責提交表單本身。這兩個操作都將返回SUCCESS,但我們將根據返回值採取不同的操作,因為這兩個操作的目的不同。

負責處理Locale的操作

package com.tutorialspoint.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class Locale extends ActionSupport {
   public String execute() {
       return SUCCESS;
   }
}

提交表單的操作

package com.tutorialspoint.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class Employee extends ActionSupport{
   private String name;
   private int age;
   
   public String execute() {
      return SUCCESS;
   }
   
   public String getName() {
      return name;
   }
   
   public void setName(String name) {
      this.name = name;
   }
   
   public int getAge() {
      return age;
   }
   
   public void setAge(int age) {
      this.age = age;
   }
}

現在讓我們建立以下三個global.properties檔案並將它們放在CLASSPATH中:

global.properties

global.name = Name
global.age = Age
global.submit = Submit
global.heading = Select Locale
global.success = Successfully authenticated

global_fr.properties

global.name = Nom d'utilisateur 
global.age = l'âge
global.submit = Soumettre des
global.heading = Sé lectionnez Local
global.success = Authentifi	é  avec succès

global_es.properties

global.name = Nombre de usuario
global.age = Edad
global.submit = Presentar
global.heading = seleccionar la configuracion regional
global.success = Autenticado correctamente

我們將建立包含兩個操作的struts.xml,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <constant name = "struts.custom.i18n.resources" value = "global" />
   <package name = "helloworld" extends = "struts-default" namespace="/">
      <action name = "empinfo" 
         class = "com.tutorialspoint.struts2.Employee"
         method = "execute">
         <result name = "input">/index.jsp</result>
         <result name = "success">/success.jsp</result>
      </action>
      
      <action name = "locale" 
         class = "com.tutorialspoint.struts2.Locale"
         method = "execute">
         <result name = "success">/index.jsp</result>
      </action>
   </package>

</struts>

以下是 **web.xml** 檔案的內容:

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee"
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">

   <display-name>Struts 2</display-name>
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>

   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

現在,右鍵單擊專案名稱,然後單擊匯出> WAR檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URL https://:8080/HelloWorldStruts2/index.jsp。這將生成以下螢幕:

English Output

現在選擇任何一種語言,例如我們選擇西班牙語,它將顯示以下結果:

Spanish Output

您也可以嘗試使用法語。最後,讓我們嘗試在西班牙語Locale下單擊提交按鈕,它將顯示以下螢幕:

Spanish Success

恭喜,現在您擁有了一個多語言網頁,您可以將其網站推廣到全球。

Struts 2 - 型別轉換

HTTP請求中的所有內容都由協議視為字串。這包括數字、布林值、整數、日期、小數等等。但是,在Struts類中,您可以擁有任何資料型別的屬性。

Struts 如何為您自動裝配屬性?

Struts在後臺使用各種型別轉換器來完成繁重的工作。

例如,如果您的Action類中有一個整數屬性,Struts會自動將請求引數轉換為整數屬性,而無需您執行任何操作。預設情況下,Struts附帶許多型別轉換器。

如果您使用的是以下列出的任何轉換器,則無需擔心:

  • 整數、浮點數、雙精度數、十進位制數
  • 日期和日期時間
  • 陣列和集合
  • 列舉
  • 布林值
  • BigDecimal

有時,當您使用自己的資料型別時,需要新增自己的轉換器以使Struts瞭解如何在顯示之前轉換這些值。考慮以下POJO類Environment.java

package com.tutorialspoint.struts2;

public class Environment {
   private String name;
   
   public  Environment(String name) {
      this.name = name;
   }
   
   public String getName() {
      return name;
   }
   
   public void setName(String name) {
      this.name = name;
   }
}

這是一個非常簡單的類,它有一個名為name的屬性,因此這個類沒有什麼特別的。讓我們建立另一個包含系統資訊的類-SystemDetails.java

為了這個練習的目的,我將Environment硬編碼為“Development”,並將作業系統硬編碼為“Windows XP SP3”。

在一個即時專案中,您將從系統配置中獲取此資訊。

讓我們使用以下Action類:

package com.tutorialspoint.struts2;
import com.opensymphony.xwork2.ActionSupport;

public class SystemDetails extends ActionSupport {
   private Environment environment = new Environment("Development");
   private String operatingSystem = "Windows XP SP3";

   public String execute() {
      return SUCCESS;
   }
   
   public Environment getEnvironment() {
      return environment;
   }
   
   public void setEnvironment(Environment environment) {
      this.environment = environment;
   }
   
   public String getOperatingSystem() {
      return operatingSystem;
   }
   
   public void setOperatingSystem(String operatingSystem) {
      this.operatingSystem = operatingSystem;
   }
}

接下來,讓我們建立一個簡單的JSP檔案System.jsp來顯示環境和作業系統資訊。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>System Details</title>
   </head>
   
   <body>
      Environment: <s:property value = "environment"/><br/>
      Operating System:<s:property value = "operatingSystem"/>
   </body>
</html>

讓我們使用struts.xmlsystem.jspSystemDetails.java類連線在一起。

SystemDetails類有一個簡單的execute()方法,它返回字串“SUCCESS”。

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
      
      <action name = "system" 
            class = "com.tutorialspoint.struts2.SystemDetails" 
            method = "execute">
         <result name = "success">/System.jsp</result>
      </action>
   </package>
</struts>
  • 右鍵單擊專案名稱,然後單擊匯出 > WAR檔案以建立WAR檔案。

  • 然後將此WAR部署到Tomcat的webapps目錄。

  • 最後,啟動Tomcat伺服器並嘗試訪問URL https://:8080/HelloWorldStruts2/system.action。這將產生以下螢幕:

System Info

上面輸出有什麼問題?Struts知道如何顯示和轉換字串“Windows XP SP3”和其他內建資料型別,但它不知道如何處理Environment型別的屬性。它只是簡單地呼叫了類的toString()方法。

為了解決這個問題,讓我們現在為Environment類建立一個並註冊一個簡單的TypeConverter

建立一個名為EnvironmentConverter.java的類,內容如下:

package com.tutorialspoint.struts2;

import java.util.Map;
import org.apache.struts2.util.StrutsTypeConverter;

public class EnvironmentConverter extends StrutsTypeConverter {
   @Override
   public Object convertFromString(Map context, String[] values, Class clazz) {
      Environment env = new Environment(values[0]);
      return env;
   }

   @Override
   public String convertToString(Map context, Object value) {
      Environment env  = (Environment) value;
      return env == null ? null : env.getName();
   }	
}

EnvironmentConverter擴充套件了StrutsTypeConverter類,並透過覆蓋兩個方法convertFromString()convertToString()來告訴Struts如何將Environment轉換為字串,反之亦然。

現在讓我們在應用程式中使用它之前註冊此轉換器。註冊轉換器有兩種方法。

如果轉換器只在一個特定的Action中使用,那麼您需要建立一個屬性檔案,其名稱必須為'[action-class]'converstion.properties

在我們的例子中,我們建立一個名為SystemDetails-converstion.properties的檔案,其中包含以下注冊條目:

environment = com.tutorialspoint.struts2.EnvironmentConverter

在上面的例子中,“environment”是SystemDetails.java類中屬性的名稱,我們告訴Struts使用EnvironmentConverter來轉換此屬性。

但是,我們不會這樣做,而是將此轉換器全域性註冊,以便可以在整個應用程式中使用它。為此,在WEBINF/classes資料夾中建立一個名為xwork-conversion.properties的屬性檔案,其中包含以下行:

com.tutorialspoint.struts2.Environment = \
   com.tutorialspoint.struts2.EnvironmentConverter

這只是全域性註冊轉換器,以便Struts在每次遇到Environment型別物件時都可以自動進行轉換。現在,如果您重新編譯並重新執行程式,那麼您將得到更好的輸出,如下所示:

System Info

顯然,現在結果會更好,這意味著我們的Struts轉換器工作正常。

這就是您可以建立多個轉換器並根據您的需求註冊它們的方式。

Struts 2 - 主題和模板

在開始本章的實際教程之前,讓我們看一下https://struts.apache.org給出的幾個定義:

序號 術語和描述
1

標籤 (TAG)

一小段從JSP、FreeMarker或Velocity內部執行的程式碼。

2

模板 (TEMPLATE)

一段程式碼,通常用FreeMarker編寫,可以由某些標籤(HTML標籤)渲染。

3

主題 (THEME)

打包在一起以提供通用功能的模板集合。

我還建議閱讀Struts2本地化章節,因為我們將再次使用相同的示例來執行我們的練習。

當您在網頁中使用Struts 2標籤(例如<s:submit...>,<s:textfield...>等)時,Struts 2框架將生成具有預配置樣式和佈局的HTML程式碼。Struts 2帶有三個內建主題:

序號 主題和描述
1

SIMPLE主題

一個最小的主題,沒有“花裡胡哨”的功能。例如,textfield標籤渲染HTML <input/>標籤,沒有標籤、驗證、錯誤報告或任何其他格式或功能。

2

XHTML主題

這是Struts 2使用的預設主題,它提供SIMPLE主題提供的所有基礎功能,並添加了一些功能,例如HTML的標準兩列表格佈局、每個HTML的標籤、驗證和錯誤報告等。

3

CSS_XHTML主題

此主題提供SIMPLE主題提供的所有基礎功能,並添加了一些功能,例如基於CSS的標準兩列布局,使用<div>表示HTML Struts標籤、每個HTML Struts標籤的標籤,並根據CSS樣式表放置。

如上所述,如果您沒有指定主題,則Struts 2將預設使用xhtml主題。例如,此Struts 2 select標籤:

<s:textfield name = "name" label = "Name" />

生成以下HTML標記:

<tr>

   <td class="tdLabel">
      <label for = "empinfo_name" class="label">Name:</label>
   </td>
   <td>
      <input type = "text" name = "name" value = "" id = "empinfo_name"/>
   </td>

</tr>

這裡empinfo是在struts.xml檔案中定義的操作名稱。

選擇主題

您可以根據Struts 2在標籤的基礎上指定主題,或者您可以使用以下方法之一來指定Struts 2應該使用哪個主題:

  • 特定標籤上的theme屬性

  • 標籤周圍的form標籤上的theme屬性

  • 名為“theme”的頁面範圍屬性

  • 名為“theme”的請求範圍屬性

  • 名為“theme”的會話範圍屬性

  • 名為“theme”的應用程式範圍屬性

  • struts.properties中的struts.ui.theme屬性(預設為xhtml)

以下是如果您想為不同的標籤使用不同的主題,在標籤級別指定它們的語法:

<s:textfield name = "name" label = "Name" theme="xhtml"/>

因為在每個標籤的基礎上使用主題並不十分實用,所以我們可以簡單地在struts.properties檔案中使用以下標籤指定規則:

# Standard UI theme
struts.ui.theme = xhtml
# Directory where theme template resides
struts.ui.templateDir = template
# Sets the default template type. Either ftl, vm, or jsp
struts.ui.templateSuffix = ftl

以下是我們在本地化章節中獲取的結果,我們使用預設主題,並在struts-default.properties檔案中設定了struts.ui.theme = xhtml,該檔案預設包含在struts2-core.xy.z.jar檔案中。

English Output

主題是如何工作的?

對於給定的主題,每個struts標籤都有一個關聯的模板,例如s:textfield → text.ftls:password → password.ftl等。

這些模板檔案壓縮在struts2-core.xy.z.jar檔案中。這些模板檔案為每個標籤保留預定義的HTML佈局。

透過這種方式,Struts 2框架使用Sturts標籤和關聯的模板生成最終的HTML標記程式碼。

Struts 2 tags + Associated template file = Final HTML markup code.

預設模板是用FreeMarker編寫的,它們副檔名為.ftl

您也可以使用Velocity或JSP設計您的模板,並相應地在struts.properties中使用struts.ui.templateSuffixstruts.ui.templateDir設定配置。

建立新的主題

建立新主題最簡單的方法是複製任何現有的主題/模板檔案並進行必要的修改。

讓我們從在WebContent/WEBINF/classes中建立一個名為template的資料夾和一個與我們的新主題同名的子資料夾開始。例如,WebContent/WEB-INF/classes/template/mytheme

從這裡,您可以從頭開始構建模板,也可以從Struts2發行版複製模板,以便將來可以根據需要修改它們。

我們將修改現有的預設模板xhtml,用於學習目的。現在,讓我們將內容從struts2-core-x.y.z.jar/template/xhtml複製到我們的主題目錄,並且只修改WebContent/WEBINF/classes/template/mytheme/control.ftl檔案。開啟control.ftl檔案後,將看到以下幾行:

<table class="${parameters.cssClass?default('wwFormTable')?html}"<#rt/>
<#if parameters.cssStyle??> style="${parameters.cssStyle?html}"<#rt/>
</#if>
>

讓我們將上面的control.ftl檔案更改為以下內容:

<table style = "border:1px solid black;">

如果您檢視form.ftl,您會發現此檔案中使用了control.ftl,但form.ftl是從xhtml主題引用此檔案的。因此,讓我們將其更改如下:

<#include "/${parameters.templateDir}/xhtml/form-validate.ftl" />
<#include "/${parameters.templateDir}/simple/form-common.ftl" />
<#if (parameters.validate?default(false))>
   onreset = "${parameters.onreset?default('clearErrorMessages(this);\
   clearErrorLabels(this);')}"
   
<#else>
   <#if parameters.onreset??>
      onreset="${parameters.onreset?html}"
   </#if>
</#if>
#include "/${parameters.templateDir}/mytheme/control.ftl" />

我假設您可能不太瞭解FreeMarker模板語言,但您仍然可以透過檢視.ftl檔案獲得一個很好的瞭解。

但是,讓我們儲存上述更改,然後返回我們的本地化示例,並建立包含以下內容的WebContent/WEB-INF/classes/struts.properties檔案

# Customized them
struts.ui.theme = mytheme
# Directory where theme template resides
struts.ui.templateDir = template
# Sets the template type to ftl.
struts.ui.templateSuffix = ftl

現在更改之後,右鍵單擊專案名稱,然後單擊匯出 > WAR 檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URL https://:8080/HelloWorldStruts2。這將生成以下螢幕:

Theme and Template

您可以看到表單元件周圍有一個邊框,這是我們在從xhtml主題複製後修改主題的結果。如果您在學習FreeMarker方面付出一點努力,那麼您將能夠非常輕鬆地建立或修改您的主題。

我希望您現在對Struts 2主題和模板有了基本的瞭解,對嗎?

Struts 2 - 異常處理

Struts提供了一種更簡單的方法來處理未捕獲的異常並將使用者重定向到專用的錯誤頁面。您可以輕鬆地配置Struts以針對不同的異常使用不同的錯誤頁面。

Struts 透過使用“exception”攔截器簡化了異常處理。“exception”攔截器包含在預設堆疊中,因此您無需執行任何額外操作即可配置它。它開箱即用,隨時可以使用。

讓我們來看一個簡單的HelloWorld示例,其中對HelloWorldAction.java檔案進行了一些修改。在這裡,我們故意在我們的HelloWorldAction操作程式碼中引入了一個空指標異常。

package com.tutorialspoint.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorldAction extends ActionSupport{
   private String name;

   public String execute(){
      String x = null;
      x = x.substring(0);
      return SUCCESS;
   }
   
   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}

讓我們保留HelloWorld.jsp的內容如下:

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>

<html>
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      Hello World, <s:property value = "name"/>
   </body>
</html>

以下是index.jsp的內容:

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      <h1>Hello World From Struts2</h1>
      <form action = "hello">
         <label for = "name">Please enter your name</label><br/>
         <input type = "text" name = "name"/>
         <input type = "submit" value = "Say Hello"/>
      </form>
   </body>
</html>

您的struts.xml應如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
     
      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
      </action>

   </package>
</struts>

現在右鍵單擊專案名稱,然後單擊匯出 > WAR 檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URL https://:8080/HelloWorldStruts2/index.jsp。這將生成以下螢幕:

Hello World Input

輸入值“Struts2”並提交頁面。您應該看到以下頁面:

Exception Output

如上例所示,預設異常攔截器在處理異常方面做得很好。

現在讓我們為異常建立一個專用的錯誤頁面。建立一個名為Error.jsp的檔案,其內容如下:

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
	pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title></title>
   </head>
   
   <body>
      This is my custom error page
   </body>
</html>

現在讓我們配置Struts在發生異常時使用此錯誤頁面。讓我們修改struts.xml如下:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
   
      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction" 
         method = "execute">
         <exception-mapping exception = "java.lang.NullPointerException"
         result = "error" />
         <result name = "success">/HelloWorld.jsp</result>
         <result name = "error">/Error.jsp</result>
      </action>

   </package>
</struts>

如上例所示,現在我們已將Struts配置為對NullPointerException使用專用的Error.jsp。如果您現在重新執行程式,您現在將看到以下輸出:

Hello World Output

除此之外,Struts2框架還帶有一個“logging”攔截器來記錄異常。透過啟用記錄器來記錄未捕獲的異常,我們可以輕鬆檢視堆疊跟蹤並找出出錯的原因。

全域性異常對映

我們已經瞭解瞭如何處理特定於操作的異常。我們可以全域性設定一個異常,該異常將應用於所有操作。例如,要捕獲相同的NullPointerException異常,我們可以在<package...>標記內新增<global-exception-mappings...>標記,並且其<result...>標記應新增到struts.xml檔案中的<action...>標記內,如下所示:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
      <global-exception-mappings>
         <exception-mapping exception = "java.lang.NullPointerException"
         result = "error" />
      </global-exception-mappings>

      <action name = "hello" 
         class = "com.tutorialspoint.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
         <result name = "error">/Error.jsp</result>
      </action>

   </package>
</struts>

Struts 2 - 註解

如前所述,Struts提供兩種配置形式。傳統方式是使用struts.xml檔案進行所有配置。到目前為止,我們在教程中已經看到了很多這樣的例子。另一種配置Struts的方法是使用Java 5註解功能。使用Struts註解,我們可以實現零配置

要在您的專案中開始使用註解,請確保您已將以下jar檔案包含在WebContent/WEB-INF/lib資料夾中:

  • struts2-convention-plugin-x.y.z.jar
  • asm-x.y.jar
  • antlr-x.y.z.jar
  • commons-fileupload-x.y.z.jar
  • commons-io-x.y.z.jar
  • commons-lang-x.y.jar
  • commons-logging-x.y.z.jar
  • commons-logging-api-x.y.jar
  • freemarker-x.y.z.jar
  • javassist-.xy.z.GA
  • ognl-x.y.z.jar
  • struts2-core-x.y.z.jar
  • xwork-core.x.y.z.jar

現在,讓我們看看如何取消struts.xml檔案中可用的配置,並將其替換為註解。

為了解釋Struts2中註解的概念,我們必須重新考慮在Struts2驗證章節中解釋的驗證示例。

在這裡,我們將以一個員工為例,員工的姓名、年齡將使用一個簡單的頁面捕獲,我們將進行兩次驗證以確保使用者始終輸入姓名,並且年齡應在28到65之間。

讓我們從示例的主JSP頁面開始。

建立主頁(Create Main Page)

讓我們編寫主頁面JSP檔案index.jsp,用於收集上面提到的與員工相關的資訊。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Employee Form</title>
   </head>

   <body>
      
      <s:form action = "empinfo" method = "post">
         <s:textfield name = "name" label = "Name" size = "20" />
         <s:textfield name = "age" label = "Age" size = "20" />
         <s:submit name = "submit" label = "Submit" align="center" />
      </s:form>

   </body>
</html>

index.jsp使用Struts標籤,我們還沒有介紹,但我們將在與標籤相關的章節中學習它們。但就目前而言,只需假設s:textfield標籤列印一個輸入欄位,s:submit列印一個提交按鈕。我們為每個標籤使用了label屬性,它為每個標籤建立標籤。

建立檢視

我們將使用JSP檔案success.jsp,該檔案將在定義的操作返回SUCCESS的情況下被呼叫。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
	pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Success</title>
   </head>
   
   <body>
      Employee Information is captured successfully.
   </body>
</html>

建立Action

這是使用註解的地方。讓我們使用註解重新定義操作類Employee,然後新增一個名為validate()的方法,如下所示Employee.java檔案。確保您的操作類擴充套件了ActionSupport類,否則您的validate方法將不會執行。

package com.tutorialspoint.struts2;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import com.opensymphony.xwork2.validator.annotations.*;

@Results({
   @Result(name = "success", Location = "/success.jsp"),
   @Result(name = "input", Location = "/index.jsp")
})
public class Employee extends ActionSupport {
   private String name;
   private int age;

   @Action(value = "/empinfo")
   
   public String execute() {
      return SUCCESS;
   }

   @RequiredFieldValidator( message = "The name is required" )
   
   public String getName() {
      return name;
   }
   
   public void setName(String name) {
      this.name = name;
   }

   @IntRangeFieldValidator(message = "Age must be in between 28 and 65", min = "29", max = "65")
   
   public int getAge() {
      return age;
   }
   
   public void setAge(int age) {
      this.age = age;
   }
}

在這個例子中,我們使用了幾個註解。讓我逐一介紹一下:

  • 首先,我們包含了Results註解。Results註解是結果的集合。

  • 在results註解下,我們有兩個result註解。result註解具有與execute方法的結果相對應的name。它們還包含一個位置,說明應提供與execute()的返回值相對應的哪個檢視。

  • 下一個註解是Action註解。它用於修飾execute()方法。Action方法還接收一個值,該值是呼叫該操作的URL。

  • 最後,我使用了兩個validation註解。我在name欄位上配置了required欄位驗證器,在age欄位上配置了整數範圍驗證器。我還為驗證指定了自定義訊息。

配置檔案(Configuration Files)

我們真的不需要struts.xml配置檔案,所以讓我們刪除此檔案,讓我們檢查web.xml檔案的內容:

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee"
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">

   <display-name>Struts 2</display-name>
   
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>

   <filter>
      <filter-name>struts2</filter-name>
      
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
      
      <init-param>
         <param-name>struts.devMode</param-name>
         <param-value>true</param-value>
      </init-param>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

現在,右鍵單擊專案名稱,然後單擊匯出> WAR檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URL https://:8080/HelloWorldStruts2/index.jsp。這將生成以下螢幕:

Email User Input

現在不要輸入任何必需的資訊,只需單擊提交按鈕。你將看到以下結果:

Error

輸入所需的資訊,但輸入錯誤的“From”欄位,例如將姓名設定為“test”,年齡設定為30,最後單擊提交按鈕。你將看到以下結果:

Success

Struts 2 註解型別

Struts 2應用程式可以使用Java 5註解作為XML和Java屬性配置的替代方案。您可以檢視與不同類別相關的最重要註解的列表:

Struts 2 註解型別.

Struts 2 - 控制標籤

Struts 2標籤有一組標籤,使控制頁面執行流程變得容易。

以下是重要的Struts 2控制標籤列表:

If和Else標籤

這些標籤執行每種語言中都存在的基本條件流。

'If'標籤本身使用,或與'Else If'標籤和/或單個/多個'Else'標籤一起使用,如下所示:

<s:if test = "%{false}">
   <div>Will Not Be Executed</div>
</s:if>

<s:elseif test = "%{true}">
   <div>Will Be Executed</div>
</s:elseif>

<s:else>
   <div>Will Not Be Executed</div>
</s:else>

檢視詳細示例

迭代器標籤

迭代器將迭代一個值。可迭代值可以是java.util.Collection或java.util.Iterator檔案。在迭代迭代器時,您可以使用Sort標籤對結果進行排序,或使用SubSet標籤獲取列表或陣列的子集。

以下示例檢索值堆疊上當前物件的getDays()方法的值,並使用它進行迭代。

<s:property/>標籤打印出迭代器的當前值。

<s:iterator value = "days">
   <p>day is: <s:property/></p>
</s:iterator>

檢視詳細示例

合併標籤

這些merge標籤將兩個或多個列表作為引數,並將它們全部合併在一起,如下所示:

<s:merge var = "myMergedIterator">
   <s:param value = "%{myList1}" />
   <s:param value = "%{myList2}" />
   <s:param value = "%{myList3}" />
</s:merge>

<s:iterator value = "%{#myMergedIterator}">
   <s:property />
</s:iterator>

檢視詳細示例

追加標籤

這些append標籤將兩個或多個列表作為引數,並將它們全部追加在一起,如下所示:

<s:append var = "myAppendIterator">
   <s:param value = "%{myList1}" />
   <s:param value = "%{myList2}" />
   <s:param value = "%{myList3}" />
</s:append>

<s:iterator value = "%{#myAppendIterator}">
   <s:property />
</s:iterator>

檢視詳細示例

生成器標籤

這些generator標籤根據提供的val屬性生成迭代器。以下生成器標籤生成迭代器並使用迭代器標籤列印它。

<s:generator val = "%{'aaa,bbb,ccc,ddd,eee'}">
   <s:iterator>
      <s:property /><br/>
   </s:iterator>
</s:generator>

檢視詳細示例

Struts 2 - 資料標籤

Struts 2資料標籤主要用於操作頁面上顯示的資料。以下是重要的資料標籤:<從這裡開始>

Action標籤

此標籤允許開發人員透過指定操作名稱和可選名稱空間直接從JSP頁面呼叫操作。標籤的主體內容用於呈現來自Action的結果。除非指定了executeResult引數,否則將忽略在struts.xml中為此操作定義的任何結果處理器。

<div>Tag to execute the action</div>
<br />
<s:action name = "actionTagAction" executeresult = "true" />
<br />
<div>To invokes special method  in action class</div>
<br />
<s:action name = "actionTagAction!specialMethod" executeresult = "true" />

檢視詳細示例

Include標籤

這些include將用於在另一個JSP頁面中包含JSP檔案。

<-- First Syntax -->
<s:include value = "myJsp.jsp" />

<-- Second Syntax -->
<s:include value = "myJsp.jsp">
   <s:param name = "param1" value = "value2" />
   <s:param name = "param2" value = "value2" />
</s:include>

<-- Third Syntax -->
<s:include value = "myJsp.jsp">
   <s:param name = "param1">value1</s:param>
   <s:param name = "param2">value2</s:param>
</s:include>

檢視詳細示例

Bean標籤

這些bean標籤例項化符合JavaBeans規範的類。此標籤有一個主體,其中可以包含許多Param元素來設定該類上的任何mutator方法。如果在BeanTag上設定了var屬性,它會將例項化的bean放入堆疊的上下文。

<s:bean name = "org.apache.struts2.util.Counter" var = "counter">
   <s:param name = "first" value = "20"/>
   <s:param name = "last" value = "25" />
</s:bean>

檢視詳細示例

Date標籤

這些date標籤允許您快速輕鬆地格式化日期。您可以指定自定義格式(例如,“dd/MM/yyyy hh:mm”),您可以生成易於閱讀的符號(例如“2小時14分鐘內”),或者您可以只回退到屬性檔案中鍵為'struts.date.format'的預定義格式。

<s:date name = "person.birthday" format = "dd/MM/yyyy" />
<s:date name = "person.birthday" format = "%{getText('some.i18n.key')}" />
<s:date name = "person.birthday" nice="true" />
<s:date name = "person.birthday" />

檢視詳細示例

Param標籤

這些param標籤可用於引數化其他標籤。此標籤具有以下兩個引數。

  • name(字串)- 引數的名稱

  • value(物件)- 引數的值

<pre>
   <ui:component>
      <ui:param name = "key"     value = "[0]"/>
      <ui:param name = "value"   value = "[1]"/>
      <ui:param name = "context" value = "[2]"/>
   </ui:component>
</pre>

檢視詳細示例

Property標籤

這些property標籤用於獲取值的屬性,如果沒有指定,則預設為堆疊頂部。

<s:push value = "myBean">
   <!-- Example 1: -->
   <s:property value = "myBeanProperty" />

   <!-- Example 2: -->TextUtils
   <s:property value = "myBeanProperty" default = "a default value" />
</s:push>

檢視詳細示例

Push標籤

這些push標籤用於將值推入堆疊以簡化使用。

<s:push value = "user">
   <s:propery value = "firstName" />
   <s:propery value = "lastName" />
</s:push>

檢視詳細示例

Set標籤

這些set標籤將值賦給指定範圍內的變數。當您希望將變數賦給複雜表示式,然後每次簡單地引用該變數而不是複雜表示式時,這很有用。可用的範圍是application、session、request、pageaction

<s:set name = "myenv" value = "environment.name"/>
<s:property value = "myenv"/>

檢視詳細示例

Text標籤

這些text標籤用於呈現I18n文字訊息。

<!-- First Example -->
<s:i18n name = "struts.action.test.i18n.Shop">
   <s:text name = "main.title"/>
</s:i18n>

<!-- Second Example -->
<s:text name = "main.title" />

<!-- Third Examlpe -->
<s:text name = "i18n.label.greetings">
   <s:param >Mr Smith</s:param>
</s:text>

檢視詳細示例

URL標籤

這些url標籤用於建立URL。

<-- Example 1 -->
<s:url value = "editGadget.action">
   <s:param name = "id" value = "%{selected}" />
</s:url>

<-- Example 2 -->
<s:url action = "editGadget">
   <s:param name = "id" value = "%{selected}" />
</s:url>

<-- Example 3-->
<s:url includeParams="get">
   <s:param name = "id" value = "%{'22'}" />
</s:url>

檢視詳細示例

Struts 2 - 表單標籤

表單標籤列表是Struts UI標籤的一個子集。這些標籤有助於渲染Struts Web應用程式所需的介面,可分為三類。本章將帶您瞭解所有三種類型的UI標籤:

簡單UI標籤

我們在示例中已經使用了這些標籤,本章將回顧它們。讓我們來看一個包含幾個簡單UI標籤的簡單檢視頁面email.jsp

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <s:head/>
      <title>Hello World</title>
   </head>
   
   <body>
      <s:div>Email Form</s:div>
      <s:text name = "Please fill in the form below:" />
      
      <s:form action = "hello" method = "post" enctype = "multipart/form-data">
         <s:hidden name = "secret" value = "abracadabra"/>
         <s:textfield key = "email.from" name = "from" />
         <s:password key = "email.password" name = "password" />
         <s:textfield key = "email.to" name = "to" />
         <s:textfield key = "email.subject" name = "subject" />
         <s:textarea key = "email.body" name = "email.body" />
         <s:label for = "attachment" value = "Attachment"/>
         <s:file name = "attachment" accept = "text/html,text/plain" />
         <s:token />
         <s:submit key = "submit" />
      </s:form>
      
   </body>
</html>

如果您瞭解HTML,那麼所有使用的標籤都是非常常見的HTML標籤,每個標籤前面都加上了s:字首以及不同的屬性。當我們執行上述程式時,如果已為所有使用的鍵設定了正確的對映,則會得到以下使用者介面。

Struts Simple UI tags

如所示,s:head生成Struts 2應用程式所需的javascript和樣式表元素。

接下來,我們有s:div和s:text元素。s:div用於渲染HTML Div元素。這對於不喜歡混合HTML和Struts標籤的人很有用。對於這些人,他們可以選擇使用s:div來渲染div。

如所示,s:text用於在螢幕上渲染文字。

接下來是我們熟悉的s:form標籤。s:form標籤具有一個action屬性,用於確定表單提交的位置。因為表單中有一個檔案上傳元素,所以必須將enctype設定為multipart。否則,可以將其留空。

在表單標籤的末尾,我們有s:submit標籤。這用於提交表單。提交表單時,所有表單值都將提交到s:form標籤中指定的action。

在s:form內部,我們有一個名為secret的隱藏屬性。這會在HTML中渲染一個隱藏元素。在本例中,“secret”元素的值為“abracadabra”。此元素對終端使用者不可見,用於在不同的檢視之間傳遞狀態。

接下來,我們有s:label、s:textfield、s:password和s:textarea標籤。這些分別用於渲染標籤、輸入欄位、密碼和文字區域。我們在“Struts - 傳送電子郵件”示例中已經看到這些標籤的實際應用。

這裡需要注意的是“key”屬性的使用。“key”屬性用於從屬性檔案獲取這些控制元件的標籤。我們在Struts 2本地化和國際化章節中已經介紹了此功能。

然後,我們有s:file標籤,它渲染一個輸入檔案上傳元件。此元件允許使用者上傳檔案。在此示例中,我們使用了s:file標籤的“accept”引數來指定允許上傳的檔案型別。

最後,我們有s:token標籤。token標籤生成一個唯一令牌,用於確定表單是否被重複提交。

渲染表單時,會將一個隱藏變數作為令牌值放置。例如,假設令牌為“ABC”。提交此表單時,Struts過濾器會將令牌與儲存在會話中的令牌進行比較。如果匹配,則從會話中刪除令牌。現在,如果意外地重新提交表單(透過重新整理或點選瀏覽器後退按鈕),表單將使用“ABC”作為令牌重新提交。在這種情況下,過濾器會再次將令牌與儲存在會話中的令牌進行比較。但由於令牌“ABC”已從會話中刪除,因此它將不匹配,Struts過濾器將拒絕請求。

分組UI標籤

分組UI標籤用於建立單選按鈕和複選框。讓我們來看一個包含複選框和單選按鈕標籤的簡單檢視頁面HelloWorld.jsp

<%@ page contentType = "text/html; charset = UTF-8"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>

<html>
   <head>
      <title>Hello World</title>
      <s:head />
   </head>
   
   <body>
      <s:form action = "hello.action">
         <s:radio label = "Gender" name = "gender" list="{'male','female'}" />
         <s:checkboxlist label = "Hobbies" name = "hobbies"
         list = "{'sports','tv','shopping'}" />
      </s:form>
      
   </body>
</html>

當我們執行上述程式時,我們的輸出將類似於以下內容:

Struts group UI tags

現在讓我們來看一下這個例子。在第一個例子中,我們建立了一個簡單的單選按鈕,標籤為“性別”。name屬性對於單選按鈕標籤是必須的,因此我們指定一個名為“gender”的名稱。然後我們將一個列表提供給gender。該列表填充了“male”和“female”值。因此,在輸出中,我們得到一個包含兩個值的單選按鈕。

在第二個例子中,我們建立了一個複選框列表。這是為了收集使用者的愛好。使用者可以有多個愛好,因此我們使用複選框而不是單選按鈕。複選框填充了“sports”、“TV”和“Shopping”列表。這將愛好顯示為複選框列表。

選擇UI標籤

讓我們探索Struts提供的Select標籤的不同變體。讓我們來看一個包含select標籤的簡單檢視頁面HelloWorld.jsp

<%@ page contentType = "text/html; charset = UTF-8"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>

<html>
   <head>
      <title>Hello World</title>
      <s:head />
   </head>
   
   <body>
      <s:form action = "login.action">
         <s:select name = "username" label = "Username"
            list = "{'Mike','John','Smith'}" />

         <s:select label = "Company Office" name = "mySelection"
            value = "%{'America'}" list="%{#{'America':'America'}}">
            <s:optgroup label = "Asia" 
               list = "%{#{'India':'India','China':'China'}}" />
            <s:optgroup label = "Europe"
               list="%{#{'UK':'UK','Sweden':'Sweden','Italy':'Italy'}}" />
         </s:select>

         <s:combobox label = "My Sign" name = "mySign"
            list = "#{'aries':'aries','capricorn':'capricorn'}" headerkey = "-1" 
            headervalue = "--- Please Select ---" emptyOption = "true" value = "capricorn" />
         <s:doubleselect label = "Occupation" name = "occupation"
            list = "{'Technical','Other'}" doublename = "occupations2"
            doubleList="top == 'Technical' ? 
            {'I.T', 'Hardware'} : {'Accounting', 'H.R'}" />
      </s:form>
   </body>
</html>

當我們執行上述程式時,我們的輸出將類似於以下內容:

Struts select UI tags

現在讓我們逐一講解各個案例。

  • 首先,select標籤渲染HTML select框。在第一個示例中,我們建立一個簡單的select框,名稱為“username”,標籤為“username”。select框將填充一個包含Mike、John和Smith名稱的列表。

  • 在第二個示例中,我們的公司在美國設有總部。它還在亞洲和歐洲設有全球辦事處。我們希望在一個select框中顯示辦事處,但我們希望按大洲名稱對全球辦事處進行分組。這就是optgroup派上用場的地方。我們使用s:optgroup標籤建立一個新組。我們為該組指定一個標籤和一個單獨的列表。

  • 在第三個示例中,使用了組合框。組合框是輸入欄位和select框的組合。使用者可以從select框中選擇一個值,在這種情況下,輸入欄位將自動填充使用者已選擇的值。如果使用者直接輸入值,則不會選擇select框中的任何值。

  • 在我們的示例中,我們列出了星座。select框只列出了四個條目,允許使用者輸入他的星座,如果它不在列表中。我們還在select框中添加了一個標題條目。headerentry是顯示在select框頂部的條目。在我們的例子中,我們想顯示“請選擇”。如果使用者沒有選擇任何內容,則我們假設值為-1。在某些情況下,我們不希望使用者選擇空值。在這些情況下,可以將“emptyOption”屬性設定為false。最後,在我們的示例中,我們為組合框提供“capricorn”作為預設值。

  • 在第四個示例中,我們有一個雙重選擇。當您想要顯示兩個select框時,可以使用雙重選擇。在第一個select框中選擇的值決定了第二個select框中顯示的內容。在我們的示例中,第一個select框顯示“技術”和“其他”。如果使用者選擇“技術”,我們將在第二個select框中顯示“IT”和“硬體”。否則,我們將顯示“會計”和“人力資源”。這可以透過使用示例中所示的“list”和“doubleList”屬性來實現。

在上例中,我們進行了比較,以檢視頂部select框是否等於“技術”。如果是,則顯示“IT”和“硬體”。

我們還需要為頂部框(“name = 'Occupations'”)和底部框(“doubleName = 'occupations2'”)指定名稱。

Struts 2 - Ajax標籤

Struts使用DOJO框架來實現AJAX標籤。首先,要繼續此示例,需要將struts2-dojo-plugin-2.2.3.jar新增到類路徑。

您可以從Struts 2下載的lib資料夾中獲取此檔案(C:\struts-2.2.3all\struts-2.2.3\lib\struts2-dojo-plugin-2.2.3.jar)

對於此練習,讓我們修改HelloWorld.jsp如下:

<%@ page contentType = "text/html; charset = UTF-8"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<%@ taglib prefix = "sx" uri = "/struts-dojo-tags"%>

<html>
   <head>
      <title>Hello World</title>
      <s:head />
      <sx:head />
   </head>
   
   <body>
      <s:form>
         <sx:autocompleter label = "Favourite Colour"
            list = "{'red','green','blue'}" />
         <br />
         <sx:datetimepicker name = "deliverydate" label = "Delivery Date"
            displayformat = "dd/MM/yyyy" />
         <br />
         <s:url id = "url" value = "/hello.action" />
         <sx:div href="%{#url}" delay="2000">
            Initial Content
         </sx:div>
         <br/>
         <sx:tabbedpanel id = "tabContainer">
            <sx:div label = "Tab 1">Tab 1</sx:div>
            <sx:div label = "Tab 2">Tab 2</sx:div>
         </sx:tabbedpanel>
      </s:form>
   </body>
</html>

執行上述示例時,我們將得到以下輸出:

Struts Ajax tags

現在讓我們一步一步地講解這個例子。

首先要注意的是添加了一個新的標籤庫,字首為sx。這是(struts-dojo-tags)專門為ajax整合建立的標籤庫。

然後在HTML頭部,我們呼叫sx:head。這初始化了dojo框架,並使其準備好頁面內所有AJAX呼叫。這一步很重要——如果沒有初始化sx:head,您的ajax呼叫將無法工作。

首先,我們有autocompleter標籤。autocompleter標籤看起來非常像一個select框。它填充了紅色、綠色和藍色值。但是select框和這個框的區別在於它會自動完成。也就是說,如果您開始輸入gr,它將用“green”填充它。除此之外,這個標籤與我們之前介紹的s:select標籤非常相似。

接下來,我們有一個日期時間選擇器。此標籤建立一個輸入欄位,旁邊有一個按鈕。按下按鈕時,將顯示一個彈出式日期時間選擇器。當用戶選擇日期時,日期將按照標籤屬性中指定的格式填充到輸入文字中。在我們的示例中,我們指定了dd/MM/yyyy作為日期格式。

接下來,我們建立一個指向system.action檔案的url標籤,我們在之前的練習中建立了這個檔案。它不必是system.action——它可以是您之前建立的任何action檔案。然後我們有一個div,其超連結設定為url,延遲設定為2秒。執行時會發生的情況是,“初始內容”將顯示2秒,然後div的內容將替換為hello.action執行的內容。

最後,我們有一個簡單的選項卡面板,有兩個選項卡。選項卡本身就是div,標籤為“選項卡1”和“選項卡2”。

值得注意的是,Struts中的AJAX標籤整合仍在進行中,並且此整合的成熟度隨著每個版本的釋出而逐漸提高。

Struts 2和Spring整合

Spring是一個流行的Web框架,它可以輕鬆地與許多常見的Web任務整合。那麼問題是,當我們有Struts 2時,為什麼還需要Spring呢?Spring不僅僅是一個MVC框架——它提供了許多Struts中沒有的其他功能。

例如:依賴注入,這對於任何框架都非常有用。在本章中,我們將透過一個簡單的示例來了解如何將Spring和Struts 2整合在一起。

首先,您需要從Spring安裝中將以下檔案新增到專案的構建路徑。您可以從https://www.springsource.org/download下載並安裝最新版本的Spring框架。

  • org.springframework.asm-x.y.z.M(a).jar
  • org.springframework.beans-x.y.z.M(a).jar
  • org.springframework.context-x.y.z.M(a).jar
  • org.springframework.core-x.y.z.M(a).jar
  • org.springframework.expression-x.y.z.M(a).jar
  • org.springframework.web-x.y.z.M(a).jar
  • org.springframework.web.servlet-x.y.z.M(a).jar

最後,將struts2-spring-plugin-x.y.z.jar新增到您的Struts lib目錄中的WEB-INF/lib中。如果您使用的是Eclipse,則可能會遇到異常java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener

要解決這個問題,您需要進入標記選項卡,然後依次右鍵單擊類依賴項,並進行快速修復以釋出/匯出所有依賴項。最後,確保標記選項卡下沒有依賴衝突。

Struts and Sprint Integration

現在讓我們按照如下方式設定Struts-Spring整合的web.xml

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee" 
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id = "WebApp_ID" version = "3.0">
	
   <display-name>Struts 2</display-name>
   
   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>

   <listener>
      <listener-class>
         org.springframework.web.context.ContextLoaderListener
      </listener-class>
   </listener>

   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.FilterDispatcher
      </filter-class>
   </filter>

   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

這裡需要注意的重要一點是我們配置的監聽器。ContextLoaderListener是載入spring上下文檔案所必需的。Spring的配置檔案稱為applicationContext.xml檔案,它必須與web.xml檔案放在同一級別。

讓我們建立一個名為User.java的簡單action類,它有兩個屬性:firstName和lastName。

package com.tutorialspoint.struts2;

public class User {
   private String firstName;
   private String lastName;

   public String execute() {
      return "success";
   }

   public String getFirstName() {
      return firstName;
   }

   public void setFirstName(String firstName) {
      this.firstName = firstName;
   }

   public String getLastName() {
      return lastName;
   }

   public void setLastName(String lastName) {
      this.lastName = lastName;
   }
}

現在讓我們建立applicationContext.xml spring配置檔案並例項化User.java類。如前所述,此檔案應位於WEB-INF資料夾下:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
   <bean id = "userClass" class = "com.tutorialspoint.struts2.User">
      <property name = "firstName" value = "Michael" />
      <property name = "lastName" value = "Jackson" />
   </bean>
</beans>

如上所示,我們已配置user bean,並將值MichaelJackson注入到bean中。我們還為此bean命名為“userClass”,以便我們可以在其他地方重用它。接下來,讓我們在WebContent資料夾中建立User.jsp

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <title>Hello World</title>
   </head>
   
   <body>
      <h1>Hello World From Struts2 - Spring integration</h1>

      <s:form>
         <s:textfield name = "firstName" label = "First Name"/><br/>
         <s:textfield name = "lastName" label = "Last Name"/><br/>
      </s:form>
      
   </body>
</html>

User.jsp檔案非常簡單。它只有一個目的——顯示使用者物件的firstName和lastName的值。最後,讓我們使用struts.xml檔案將所有實體放在一起。

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
      <action name = "user" class="userClass" 
         method = "execute">
         <result name = "success">/User.jsp</result>
      </action>
   </package>
</struts>

需要注意的重要一點是,我們使用iduserClass來引用類。這意味著我們正在使用spring為User類進行依賴注入。

現在右鍵單擊專案名稱,然後單擊匯出 > WAR檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URLhttps://:8080/HelloWorldStruts2/User.jsp。這將產生以下螢幕:

Struts and Spring Integration

我們現在已經看到了如何將兩個優秀的框架結合在一起。Struts - Spring整合章節到此結束。

Struts 2 & Tiles整合

在本章中,讓我們一起學習將Tiles框架與Struts2整合的步驟。Apache Tiles是一個模板框架,旨在簡化Web應用程式使用者介面的開發。

首先,我們需要從Apache Tiles網站下載tiles jar檔案。您需要將以下jar檔案新增到專案的類路徑。

  • tiles-api-x.y.z.jar
  • tiles-compat-x.y.z.jar
  • tiles-core-x.y.z.jar
  • tiles-jsp-x.y.z.jar
  • tiles-servlet-x.y.z.jar

除此之外,我們還必須將以下jar檔案從struts2下載複製到您的WEB-INF/lib目錄。

  • commons-beanutils-x.y.zjar
  • commons-digester-x.y.jar
  • struts2-tiles-plugin-x.y.z.jar

現在讓我們按照如下所示設定Struts-Tiles整合的web.xml。這裡需要注意兩點。首先,我們需要告訴tiles在哪裡可以找到tiles配置檔案tiles.xml。在本例中,它位於/WEB-INF資料夾下。接下來,我們需要初始化Struts2下載附帶的Tiles監聽器。

<?xml version = "1.0" Encoding = "UTF-8"?>
<web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xmlns = "http://java.sun.com/xml/ns/javaee" 
   xmlns:web = "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   id = "WebApp_ID" version = "2.5">
   <display-name>Struts2Example15</display-name>
	
   <context-param>
      <param-name>
         org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG
      </param-name>
      
      <param-value>
         /WEB-INF/tiles.xml
      </param-value>
   </context-param>

   <listener>
      <listener-class>
         org.apache.struts2.tiles.StrutsTilesListener
      </listener-class>
   </listener>

   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
         org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
      </filter-class>
   </filter>

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

   <welcome-file-list>
      <welcome-file>index.jsp</welcome-file>
   </welcome-file-list>
</web-app>

接下來,讓我們在/WEB-INF資料夾下建立tiles.xml,內容如下:

<?xml version = "1.0" Encoding = "UTF-8" ?>

<!DOCTYPE tiles-definitions PUBLIC
   "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
   "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">

<tiles-definitions>

   <definition name = "baseLayout" template="/baseLayout.jsp">
      <put-attribute name = "title"  value = "Template"/>
      <put-attribute name = "banner" value = "/banner.jsp"/>
      <put-attribute name = "menu"   value = "/menu.jsp"/>
      <put-attribute name = "body"   value = "/body.jsp"/>
      <put-attribute name = "footer"   value = "/footer.jsp"/>
   </definition>

   <definition name = "tiger" extends = "baseLayout">
      <put-attribute name = "title"  value = "Tiger"/>
      <put-attribute name = "body"   value = "/tiger.jsp"/>      
   </definition>

   <definition name = "lion" extends = "baseLayout">
      <put-attribute name = "title"  value = "Lion"/>
      <put-attribute name = "body"   value = "/lion.jsp"/>      
   </definition>
  
</tiles-definitions>

接下來,我們在baseLayout.jsp中定義一個基本的骨架佈局。它有五個可重用/可覆蓋的區域。即標題、橫幅、選單、主體頁尾。我們為baseLayout提供預設值,然後建立兩個從預設佈局擴充套件的自定義項。tiger佈局類似於基本佈局,只是它使用tiger.jsp作為其主體,並將文字“Tiger”作為標題。同樣,lion佈局類似於基本佈局,只是它使用lion.jsp作為其主體,並將文字“Lion”作為標題。

讓我們看一下各個jsp檔案。以下是baseLayout.jsp檔案的內容:

<%@ taglib uri = "http://tiles.apache.org/tags-tiles" prefix = "tiles"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset = UTF-8">
      <title>
         <tiles:insertAttribute name = "title" ignore="true" />
      </title>
   </head>

   <body>
      <tiles:insertAttribute name = "banner" /><br/>
      <hr/>
      <tiles:insertAttribute name = "menu" /><br/>
      <hr/>
      <tiles:insertAttribute name = "body" /><br/>
      <hr/>
      <tiles:insertAttribute name = "footer" /><br/>
   </body>
</html>

在這裡,我們只構建了一個包含tiles屬性的基本HTML頁面。我們在需要的地方插入tiles屬性。接下來,讓我們建立一個banner.jsp檔案,內容如下:

<img src="https://tutorialspoint.tw/images/tp-logo.gif"/>

menu.jsp檔案將包含以下幾行,它們是連結——到TigerMenu.action和LionMenu.action struts actions。

<%@taglib uri = "/struts-tags" prefix = "s"%>

<a href = "<s:url action = "tigerMenu"/>" Tiger</a><br>
<a href = "<s:url action = "lionMenu"/>" Lion</a><br>

lion.jsp檔案將包含以下內容:

<img src="http://upload.wikimedia.org/wikipedia/commons/d/d2/Lion.jpg"/>
The lion

tiger.jsp檔案將包含以下內容:

<img src="http://www.freewebs.com/tigerofdarts/tiger.jpg"/>
The tiger

接下來,讓我們建立action類檔案MenuAction.java,其中包含以下內容:

package com.tutorialspoint.struts2;

import com.opensymphony.xwork2.ActionSupport;

public class MenuAction extends ActionSupport {
   public String tiger() { return "tiger"; }
   public String lion() { return "lion"; }
}

這是一個非常簡單的類。我們聲明瞭兩個方法tiger()和lion(),它們分別返回tiger和lion作為結果。讓我們在struts.xml檔案中將其放在一起:

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <package name = "default" extends = "struts-default">
      <result-types>
         <result-type name = "tiles" 
         class="org.apache.struts2.views.tiles.TilesResult" />
      </result-types>

      <action name = "*Menu" method = "{1}" 
         class = "com.tutorialspoint.struts2.MenuAction">
         <result name = "tiger" type = "tiles">tiger</result>
         <result name = "lion" type = "tiles">lion</result>
      </action>

   </package>
</struts>

讓我們檢查一下我們在上述檔案中做了什麼。首先,我們聲明瞭一種名為“tiles”的新結果型別,因為我們現在使用tiles而不是普通的jsp作為檢視技術。Struts2支援Tiles檢視結果型別,因此我們建立結果型別“tiles”為“org.apache.struts2.view.tiles.TilesResult”類。

接下來,我們想說,如果請求是/tigerMenu.action,則將使用者帶到tiger tiles頁面;如果請求是/lionMenu.action,則將使用者帶到lion tiles頁面。

我們使用一些正則表示式來實現這一點。在我們的action定義中,我們說任何匹配模式“*Menu”的內容都將由此action處理。匹配的方法將在MenuAction類中呼叫。也就是說,tigerMenu.action將呼叫tiger(),lionMenu.action將呼叫lion()。然後我們需要將結果的結果對映到相應的tiles頁面。

現在右鍵單擊專案名稱,然後單擊匯出 > WAR檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URLhttps://:8080/HelloWorldStruts2/tigerMenu.jsp。這將產生以下螢幕:

Struts and Tiles Integration

同樣,如果您轉到lionMenu.action頁面,您將看到使用相同tiles佈局的lion頁面。

Struts 2和Hibernate整合

Hibernate是一個高效能的物件/關係永續性和查詢服務,它在開源GNU Lesser General Public License (LGPL)下獲得許可,可以免費下載。在本章中,我們將學習如何實現Struts 2與Hibernate的整合。如果您不熟悉Hibernate,則可以檢視我們的Hibernate教程

資料庫設定

在本教程中,我將使用“struts2_tutorial”MySQL資料庫。我使用使用者名稱“root”和無密碼連線到我的機器上的此資料庫。首先,您需要執行以下指令碼。此指令碼建立一個名為student的新表,並在該表中建立一些記錄:

CREATE TABLE IF NOT EXISTS `student` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `first_name` varchar(40) NOT NULL,
   `last_name` varchar(40) NOT NULL,
   `marks` int(11) NOT NULL,
   PRIMARY KEY (`id`)
);

--
-- Dumping data for table `student`
--

INSERT INTO `student` (`id`, `first_name`, `last_name`, `marks`)
   VALUES(1, 'George', 'Kane', 20);
INSERT INTO `student` (`id`, `first_name`, `last_name`, `marks`)
   VALUES(2, 'Melissa', 'Michael', 91);
INSERT INTO `student` (`id`, `first_name`, `last_name`, `marks`)
   VALUES(3, 'Jessica', 'Drake', 21);

Hibernate配置

接下來,讓我們建立hibernate.cfg.xml,它是Hibernate的配置檔案。

<?xml version = '1.0' encoding = 'utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
   "-//Hibernate/Hibernate Configuration DTD//EN"
   "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
      <property name = "hibernate.connection.driver_class">c
         om.mysql.jdbc.Driver
      </property>
      
      <property name = "hibernate.connection.url">
         jdbc:mysql://tutorialspoint.tw/struts_tutorial
      </property>
      
      <property name = "hibernate.connection.username">root</property>
      
      <property name = "hibernate.connection.password"></property>
      
      <property name = "hibernate.connection.pool_size">10</property>
      
      <property name = "show_sql">true</property>
      
      <property name = "dialect">
         org.hibernate.dialect.MySQLDialect
      </property>
      
      <property name = "hibernate.hbm2ddl.auto">update</property>
      
      <mapping class = "com.tutorialspoint.hibernate.Student" />
   </session-factory>
</hibernate-configuration> 

讓我們一起了解hibernate配置檔案。首先,我們宣告我們正在使用MySQL驅動程式。然後我們宣告用於連線到資料庫的jdbc url。然後我們宣告連線的使用者名稱、密碼和池大小。我們還指示我們希望在日誌檔案中看到SQL,方法是將“show_sql”設定為true。請閱讀Hibernate教程以瞭解這些屬性的含義。

最後,我們將對映類設定為com.tutorialspoint.hibernate.Student,我們將在本章中建立它。

環境設定

接下來,此專案需要大量jar檔案。附上所需JAR檔案的完整列表的螢幕截圖:

Struts and Hibernate Jars

大多數JAR檔案都可以作為Struts發行版的一部分獲得。如果您安裝了諸如glassfish、websphere或jboss之類的應用程式伺服器,那麼您可以從應用程式伺服器的lib資料夾中獲取大部分其餘jar檔案。如果不是,您可以單獨下載檔案:

其餘檔案,您應該能夠從您的Struts2發行版中獲得。

Hibernate類

現在讓我們建立Hibernate整合所需的Java類。以下是Student.java的內容:

package com.tutorialspoint.hibernate;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "student")
public class Student {
	
   @Id
   @GeneratedValue
   private int id;
   @Column(name = "last_name")
   private String lastName;
   @Column(name = "first_name")
   private String firstName;
   private int marks;
   
   public int getId() {
    return id;
   }
   
   public void setId(int id) {
    this.id = id;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName(String lastName) {
      this.lastName = lastName;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName(String firstName) {
      this.firstName = firstName;
   }
   
   public int getMarks() {
      return marks;
   }
   
   public void setMarks(int marks) {
      this.marks = marks;
   }
}

這是一個POJO類,根據Hibernate規範表示student表。它具有屬性id、firstName和lastName,它們對應於student表的列名。接下來,讓我們按如下方式建立StudentDAO.java檔案:

package com.tutorialspoint.hibernate;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.googlecode.s2hibernate.struts2.plugin.\
   annotations.SessionTarget;
import com.googlecode.s2hibernate.struts2.plugin.\
   annotations.TransactionTarget;

public class StudentDAO {
	
   @SessionTarget
   Session session;

   @TransactionTarget
   Transaction transaction;

   @SuppressWarnings("unchecked")
   public List<Student> getStudents() {
      List<Student> students = new ArrayList<Student>();
      
      try {
         students = session.createQuery("from Student").list();
      } catch(Exception e) {
         e.printStackTrace();
      }
      return students;
   }

   public void addStudent(Student student) {
      session.save(student);
   }
}

StudentDAO類是Student類的資料庫訪問層。它具有列出所有學生以及儲存新學生記錄的方法。

Action類

以下檔案AddStudentAction.java定義了我們的action類。這裡有兩個action方法:execute()和listStudents()。execute()方法用於新增新的學生記錄。我們使用dao的save()方法來實現這一點。

另一個方法listStudents()用於列出學生。我們使用dao的list方法獲取所有學生列表。

package com.tutorialspoint.struts2;

import java.util.ArrayList;
import java.util.List;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.tutorialspoint.hibernate.Student;
import com.tutorialspoint.hibernate.StudentDAO;

public class AddStudentAction extends ActionSupport implements ModelDriven<Student> {

   Student student  = new Student();
   List<Student> students = new ArrayList<Student>();
   StudentDAO dao = new StudentDAO();
   @Override
  
  public Student getModel() {
      return student;
   }

   public String execute() {
      dao.addStudent(student);
      return "success";
   }

   public String listStudents() {
      students = dao.getStudents();
      return "success";
   }

   public Student getStudent() {
      return student;
   }

   public void setStudent(Student student) {
      this.student = student;
   }

   public List<Student> getStudents() {
      return students;
   }

   public void setStudents(List<Student> students) {
      this.students = students;
   }
	
}

您會注意到我們正在實現ModelDriven介面。當您的action類處理具體的模型類(例如Student)而不是單個屬性(例如firstName、lastName)時,可以使用此方法。ModelAware介面要求您實現一個方法來返回模型。在我們的例子中,我們返回“student”物件。

建立檢視檔案

現在讓我們建立student.jsp檢視檔案,內容如下:

<%@ page contentType = "text/html; charset = UTF-8"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>

<html>
   <head>
      <title>Hello World</title>
      <s:head />
   </head>
   
   <body>
      <s:form action = "addStudent">
         <s:textfield name = "firstName" label = "First Name"/>
         <s:textfield name = "lastName" label = "Last Name"/>
         <s:textfield name = "marks" label = "Marks"/>
         <s:submit/>
         <hr/>
         
         <table>
            <tr>
               <td>First Name</td>
               <td>Last Name</td>
               <td>Marks</td>
            </tr>
            
            <s:iterator value = "students">	
               <tr>
                  <td><s:property value = "firstName"/></td>
                  <td><s:property value = "lastName"/></td>
                  <td><s:property value = "marks"/></td>
                 </tr>
            </s:iterator>	
         </table>
      </s:form>
   </body>
</html>

student.jsp非常簡單。在頂部部分,我們有一個提交到“addStudent.action”的表單。它接收firstName、lastName和marks。因為addStudent action與ModelAware“AddSudentAction”繫結,所以會自動建立一個student bean,並自動填充firstName、lastName和marks的值。

在底部部分,我們遍歷學生列表(參見AddStudentAction.java)。我們遍歷列表,並在表中顯示名字、姓氏和分數的值。

Struts配置

讓我們使用struts.xml將其放在一起:

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "myhibernate" extends = "hibernate-default">

      <action name = "addStudent" method = "execute"
         class = "com.tutorialspoint.struts2.AddStudentAction">
         <result name = "success" type = "redirect">
            listStudents
         </result>
      </action>

      <action name = "listStudents" method = "listStudents"
         class = "com.tutorialspoint.struts2.AddStudentAction">
         <result name = "success">/students.jsp</result>
      </action>

   </package>
</struts>

這裡需要注意的重要一點是,我們的包“myhibernate”擴充套件了名為“hibernate-default”的struts2預設包。然後我們宣告兩個actions:addStudent和listStudents。addStudent在AddStudentAction類上呼叫execute(),然後成功後,呼叫listStudents action方法。

listStudent action方法在AddStudentAction類上呼叫listStudents(),並使用student.jsp作為檢視。

現在,右鍵單擊專案名稱,然後單擊匯出 > WAR檔案以建立WAR檔案。然後將此WAR部署到Tomcat的webapps目錄中。最後,啟動Tomcat伺服器並嘗試訪問URLhttps://:8080/HelloWorldStruts2/student.jsp。這將產生以下螢幕:

Struts and Hibernate Result

在頂部部分,我們得到一個表單來輸入新學生記錄的值,底部部分列出資料庫中的學生。繼續新增新學生記錄並按提交。每次單擊提交時,螢幕都會重新整理並顯示更新的列表。

廣告