Struts 2 - 快速指南
基本 MVC 架构
模型视图控制器 (MVC) 或俗称的 MVC 是一种用于开发 Web 应用程序的软件设计模式。模型视图控制器模式由以下三个部分组成 −
模型 − 负责维护数据的模式的最低级别。
视图 − 负责向用户显示全部或部分数据。
控制器 − 控制模型和视图之间交互的软件代码。
MVC 很受欢迎,因为它将应用程序逻辑与用户界面层隔离开来,并支持关注点分离。在这里,控制器接收应用程序的所有请求,然后与模型一起准备视图所需的任何数据。然后,视图使用控制器准备的数据生成最终可呈现的响应。MVC 抽象可以用图形表示如下。

模型
模型负责管理应用程序的数据。它响应来自视图的请求,也响应来自控制器的指令来更新自身。
视图
它意味着以特定格式呈现数据,由控制器决定呈现数据来触发。它们是基于脚本的模板系统,如 JSP、ASP、PHP,并且非常容易与 AJAX 技术集成。
控制器
控制器负责响应用户输入并对数据模型对象执行交互。控制器接收输入,验证输入,然后执行修改数据模型状态的业务操作。
Struts2 是一个基于 MVC 的框架。在接下来的章节中,让我们看看如何在 Struts2 中使用 MVC 方法。
Struts 2 - 概述
Struts2 是一种基于 MVC 设计模式的流行且成熟的 Web 应用程序框架。Struts2 不仅是 Struts 1 的新版本,而且是对 Struts 架构的完全重写。
Webwork 框架最初以 Struts 框架为基础,其目标是提供基于 Struts 的增强和改进框架,使开发人员更轻松地进行 Web 开发。
一段时间后,Webwork 框架和 Struts 社区携手创建了著名的 Struts2 框架。
Struts 2 框架功能
以下是一些可能迫使您考虑使用 Struts2 的出色功能 −
POJO 表单和 POJO 操作 − Struts2 已经废除了 Action Forms,而 Action Forms 是 Struts 框架不可或缺的一部分。使用 Struts2,您可以使用任何 POJO 来接收表单输入。同样,您现在可以将任何 POJO 视为 Action 类。
标签支持 − Struts2 改进了表单标签和新标签,使开发人员可以编写更少的代码。
AJAX 支持 − Struts2 已经认识到 Web2.0 技术的接管,并通过创建 AJAX 标签将 AJAX 支持集成到产品中,此功能与标准 Struts2 标签非常相似。
轻松集成 −现在,由于 Struts2 提供了多种集成功能,因此与其他框架(如 Spring、Tiles 和 SiteMesh)的集成变得更加容易。
模板支持 − 支持使用模板生成视图。
插件支持 − 通过使用插件,可以增强和扩充核心 Struts2 行为。Struts2 有许多可用的插件。
分析 − Struts2 提供集成分析功能来调试和分析应用程序。除此之外,Struts 还借助内置调试工具提供集成调试。
易于修改的标签 − 可以使用 Freemarker 模板调整 Struts2 中的标签标记。这不需要 JSP 或 Java 知识。基本的 HTML、XML 和 CSS 知识足以修改标签。
减少配置 − Struts2 通过使用各种设置的默认值来减少配置。除非偏离 Struts2 设置的默认设置,否则您无需配置任何东西。
视图技术 − Struts2 对多种视图选项(JSP、Freemarker、Velocity 和 XSLT)提供了很好的支持。
上面列出了 Struts 2 的十大功能,这些功能使其成为企业级框架。
Struts 2 的缺点
尽管 Struts 2 具有一系列出色的功能,但当前版本 Struts 2 仍存在一些限制,需要进一步改进。列出的是一些要点 −
更大的学习曲线 − 要将 MVC 与 Struts 结合使用,您必须熟悉标准 JSP、Servlet API 以及庞大而复杂的框架。
文档不全 − 与标准 servlet 和 JSP API 相比,Struts 的在线资源较少,许多初次使用者发现在线 Apache 文档令人困惑且组织混乱。
透明度较低 −与普通的基于 Java 的 Web 应用程序相比,Struts 应用程序的幕后工作要多得多,这使得理解该框架变得困难。
最后要注意的是,一个好的框架应该提供通用行为,以便许多不同类型的应用程序可以利用它。
Struts 2 是最好的 Web 框架之一,被广泛用于开发富互联网应用程序 (RIA)。
Struts 2 - 环境设置
我们的首要任务是运行一个最小的 Struts 2 应用程序。本章将指导您如何准备开发环境以开始使用 Struts 2。
我假设您的机器上已经安装了 JDK (5+)、Tomcat 和 Eclipse。如果您没有安装这些组件,请按照快速通道上给出的步骤操作 −
步骤 1 - 设置 Java 开发工具包 (JDK)
您可以从 Oracle 的 Java 站点 − Java SE 下载下载最新版本的 SDK。您将在下载的文件中找到安装 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 值并按下 OK 按钮。
在 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 或 C:\apache-tomcat-6.0.33\bin\startup.bat
在 Unix(Solaris、Linux 等)机器上执行以下命令即可启动 Tomcat −
$CATALINA_HOME/bin/startup.sh 或 /usr/local/apache-tomcat-6.0.33/bin/startup.sh
成功启动后,访问 http://localhost:8080/ 即可使用 Tomcat 附带的默认 Web 应用程序。如果一切正常,则应显示以下结果 −

有关配置和运行 Tomcat 的更多信息,请参阅此处包含的文档以及 Tomcat 网站:https://tomcat.apache.org/
可以在 Windows 机器上执行以下命令来停止 Tomcat −
%CATALINA_HOME%\bin\shutdown 或 C:\apache-tomcat-5.5.29\bin\shutdown
可以在 Unix(Solaris、Linux 等)机器上执行以下命令来停止 Tomcat −
$CATALINA_HOME/bin/shutdown.sh 或 /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 变量。 Eclipse 可以通过在 Windows 机器上执行以下命令来启动,或者您可以直接双击 eclipse.exe
%C:\eclipse\eclipse.exe
Eclipse 可以通过在 Unix(Solaris、Linux 等)机器上执行以下命令来启动 −
$/usr/local/eclipse/eclipse
启动成功后,如果一切正常,它应该显示以下结果 −

第 4 步 - 设置 Struts2 库
现在,如果一切正常,您可以继续设置 Struts2 框架。以下是在您的机器上下载和安装 Struts2 的简单步骤。
选择是否要在 Windows 或 Unix 上安装 Struts2,然后继续下一步,为 Windows 下载 .zip 文件,为 Unix 下载 .tz 文件。
从 https://struts.apache.org/download.cgi 下载最新版本的 Struts2 二进制文件。
在撰写本教程时,我下载了 struts-2.0.14-all.zip,当您解压下载的文件时,它将为您提供 C:\struts-2.2.3 内的目录结构,如下所示。

第二步是将 zip 文件解压到任意位置,我在我的 Windows 7 机器上的 c:\ 文件夹中下载并解压了 struts-2.2.3-all.zip,这样我就将所有 jar 文件都放入了 C:\struts-2.2.3\lib。请确保正确设置 CLASSPATH 变量,否则在运行应用程序时会遇到问题。
Struts 2 - 架构
从高层次来看,Struts2 是一个拉式 MVC(或 MVC2)框架。 Struts2 中的模型-视图控制器模式由以下五个核心组件实现 −
- 操作
- 拦截器
- 值堆栈 / OGNL
- 结果 / 结果类型
- 视图技术
Struts 2 与传统的 MVC 框架略有不同,其中操作充当模型而不是控制器的角色,尽管存在一些重叠。

上图描绘了 Struts2 高层的 模型、视图 和 控制器架构。控制器使用 Struts2 调度 servlet 过滤器以及拦截器实现,该模型使用操作实现,视图是结果类型和结果的组合。值堆栈和 OGNL 提供公共线程,链接并实现其他组件之间的集成。
除了上述组件外,还会有很多与配置相关的信息。Web 应用程序的配置,以及操作、拦截器、结果等的配置。
这是 Struts 2 MVC 模式的架构概述。我们将在后续章节中更详细地介绍每个组件。
请求生命周期
根据上图,您可以了解 Struts 2 中用户请求生命周期的工作流程,如下所示 −
用户向服务器发送请求以请求某些资源(即页面)。
过滤器调度程序查看请求,然后确定适当的操作。
配置的拦截器功能适用,例如验证、文件上传等。
根据请求的操作执行选定的操作。
同样,如果需要,配置的拦截器将用于执行任何后处理。
最后,视图准备结果并将结果返回给用户。
Struts 2 - Hello World 示例
正如您从 Struts 2 架构中学到的,当您在 Struts 2 Web 应用程序中单击超链接或提交 HTML 表单时,控制器会收集输入,并将其发送到名为 Actions 的 Java 类。执行 Action 后,结果会选择一个资源来呈现响应。资源通常是 JSP,但也可以是 PDF 文件、Excel 电子表格或 Java 小程序窗口。
假设您已经构建了开发环境。现在,让我们继续构建我们的第一个 Hello World Struts2 项目。该项目的目的是构建一个 Web 应用程序,用于收集用户姓名并显示"Hello World"和用户名。
对于任何 Struts 2 项目,我们都必须创建以下四个组件 −
Sr.No | 组件 &描述 |
---|---|
1 | 操作 创建一个操作类,该类将包含完整的业务逻辑并控制用户、模型和视图之间的交互。 |
2 | 拦截器 如果需要,创建拦截器,或使用现有的拦截器。这是控制器的一部分。 |
3 | 视图 创建一个 JSP 来与用户交互,获取输入并显示最终消息。 |
4 | 配置文件 创建配置文件以耦合操作、视图和控制器。这些文件是 struts.xml、web.xml、struts.properties。 |
我将使用 Eclipse IDE,这样所有必需的组件都将在动态 Web 项目下创建。现在让我们开始创建动态 Web 项目。
创建动态 Web 项目
启动 Eclipse,然后选择 文件 > 新建 > 动态 Web 项目,输入项目名称 HelloWorldStruts2,并设置其余选项,如以下屏幕所示 −

在接下来的屏幕中选择所有默认选项,最后选中 生成 Web.xml 部署描述符 选项。这将在 Eclipse 中为您创建一个动态 Web 项目。现在选择 Windows > 显示视图 > Project Explorer,您将在项目窗口中看到如下所示的内容 −

现在将以下文件从 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 类是 Struts 2 应用程序的关键,我们在动作类中实现大部分业务逻辑。因此,让我们在 Java Resources > src 下创建一个 Java 文件 HelloWorldAction.java,包名为 com.tutorialspoint.struts2,内容如下。
当用户单击 URL 时,Action 类会响应用户操作。将执行一个或多个 Action 类的方法并返回一个字符串结果。根据结果的值,呈现特定的 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"的执行方法。
Struts 2 框架将创建一个 HelloWorldAction 类的对象,并调用执行的方法来响应用户的操作。您将业务逻辑放在这个最终返回字符串常量的方法中。换句话说,对于每个 URL,您必须实现一个操作类,并且您可以直接使用该类名作为操作名称,也可以使用 struts.xml 文件映射到其他名称,如下所示。
创建视图
我们需要一个 JSP 来呈现最终消息,当预定义操作发生时,Struts 2 框架将调用此页面,并且此映射将在 struts.xml 文件中定义。因此,让我们在 eclipse 项目的 WebContent 文件夹中创建以下 jsp 文件 HelloWorld.jsp。为此,右键单击项目资源管理器中的 WebContent 文件夹,然后选择 New >JSP File。
<%@ 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 标记显示操作类属性"name>"的值,该值由 HelloWorldAction 类的方法 getName() 返回。
创建主页
我们还需要在 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 操作将使用 struts.xml 文件映射到 HelloWorldAction 类及其执行方法。当用户单击"提交"按钮时,它将导致 Struts 2 框架运行 HelloWorldAction 类中定义的执行方法,并根据该方法的返回值选择适当的视图并将其呈现为响应。
配置文件
我们需要一个映射来将 URL、HelloWorldAction 类(模型)和 HelloWorld.jsp(视图)绑定在一起。映射告诉 Struts 2 框架哪个类将响应用户的操作(URL),将执行该类的哪个方法,以及根据该方法返回的字符串结果呈现哪个视图。
因此,让我们创建一个名为 struts.xml 的文件。因为 Struts 2 要求 struts.xml 存在于 classes 文件夹中。因此,在 WebContent/WEB-INF/classes 文件夹下创建 struts.xml 文件。Eclipse 默认不创建"classes"文件夹,因此您需要自己创建。为此,请在项目资源管理器中右键单击 WEB-INF 文件夹,然后选择 New > Folder。您的 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 的包。
当您想要将操作分组在一起时,创建包很有用。在我们的示例中,我们将操作命名为"hello",它对应于 URL /hello.action 并由 HelloWorldAction.class 支持。HelloWorldAction.class 的 execute 方法是在调用 URL /hello.action 时运行的方法。如果执行方法的结果返回"成功",则我们将用户带到 HelloWorld.jsp。
下一步是创建一个 web.xml 文件,它是对 Struts 2 的任何请求的入口点。Struts2 应用程序的入口点将是部署描述符 (web.xml) 中定义的过滤器。因此,我们将在 web.xml 中定义 org.apache.struts2.dispatcher.FilterDispatcher 类的条目。需要在 WebContent 下的 WEB-INF 文件夹下创建 web.xml 文件。当您创建项目时,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)
启用详细日志
您可以在使用 Struts 2 时通过在 WEB-INF/classes 文件夹下创建 logging.properties 文件来启用完整的日志记录功能。将以下两行保留在您的属性文件中 −
org.apache.catalina.core.ContainerBase.[Catalina].level = INFO org.apache.catalina.core.ContainerBase.[Catalina].handlers = \ java.util.logging.ConsoleHandler
默认的 logs.properties 指定用于将日志记录路由到 stdout 的 ConsoleHandler 以及 FileHandler。可以使用 SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST 或 ALL 设置处理程序的日志级别阈值。
就是这样。我们已准备好使用 Struts 2 框架运行我们的 Hello World 应用程序。
执行应用程序的步骤
右键单击项目名称,然后单击 Export > WAR File 以创建 War 文件。
然后将此 WAR 部署到 Tomcat 的 webapps 目录中。
最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2/index.jsp。这将为您提供以下屏幕 −

输入值"Struts2"并提交页面。您应该看到下一页

请注意,您可以在 struts.xml 文件中将 index 定义为操作,在这种情况下,您可以将索引页面调用为 http://localhost:8080/HelloWorldStruts2/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 应用程序所需的基本配置。在这里,我们将看到可以借助几个重要的配置文件(如 web.xml、struts.xml、strutsconfig.xml 和 struts.properties
)进行配置。老实说,您只需使用 web.xml 和 struts.xml 配置文件即可开始工作(正如您在上一章中已经看到的那样,我们的示例使用这两个文件工作)。但是,为了让您了解,我们还将解释其他文件。
web.xml 文件
web.xml 配置文件是一个 J2EE 配置文件,它确定 servlet 容器如何处理 HTTP 请求的元素。它严格来说不是 Struts2 配置文件,但它是需要配置才能使 Struts2 工作的文件。
如前所述,此文件为任何 Web 应用程序提供入口点。Struts2 应用程序的入口点将是部署描述符 (web.xml) 中定义的过滤器。因此,我们将在 web.xml 中定义 FilterDispatcher 类的条目。需要在文件夹 WebContent/WEB-INF 下创建 web.xml 文件。
如果您在没有模板或生成它的工具(如 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 配置文件都需要具有正确的文档类型,如我们的小示例所示。<struts> 是根标记元素,我们在该元素下使用 <package> 标记声明不同的包。此处 <package> 允许分离和模块化配置。当您有一个大型项目并且项目分为不同的模块时,这非常有用。
例如,如果您的项目有三个域 - business_application、customer_application 和 staff_application,那么您可以创建三个包并将相关操作存储在相应的包中。
package 标记具有以下属性 −
Sr.No | 属性 &描述 |
---|---|
1 | name (required) 包的唯一标识符 |
2 | extends 此包从哪个包扩展而来?默认情况下,我们使用 struts-default 作为基础包。 |
3 | abstract 如果标记为 true,则该包不可供最终用户使用。 |
4 | namespace 操作的唯一命名空间 |
应使用 constant 标记以及 name 和 value 属性来覆盖 default.properties 中定义的以下任何属性,就像我们刚刚设置 struts.devMode 属性一样。设置 struts.devMode 属性允许我们在日志文件中看到更多调试消息。
我们定义 action 标签对应于我们想要访问的每个 URL,并且我们定义一个带有 execute() 方法的类,每当我们访问相应的 URL 时,都会访问该方法。
结果确定执行操作后返回到浏览器的内容。从操作返回的字符串应该是结果的名称。结果按上述操作配置,或作为"全局"结果,可用于包中的每个操作。结果具有可选的 name 和 type 属性。默认名称值为"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% 的项目,您不必触及这些设置。
配置文件基本上包含以下主要元素 −
Sr.No | 拦截器 &描述 |
---|---|
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 配置文件中包含的所有属性也可以在 web.xml 中使用 init-param 进行配置,也可以使用 struts.xml 配置文件中的常量标记进行配置。但是,如果您希望将所有内容分开并使其更具体,则可以在文件夹 WEB-INF/classes 下创建此文件。
此文件中配置的值将覆盖 struts2-core-x.y.z.jar 发行版中包含的 default.properties 中配置的默认值。您可能考虑使用 struts.properties 文件更改几个属性 −
### 设置为 true 时,Struts 对开发人员来说会更加友好 struts.devMode = true ### 启用国际化文件的重新加载 struts.i18n.reload = true ### 启用 XML 配置文件的重新加载 struts.configuration.xml.reload = true ### 设置服务器运行的端口 struts.url.http.port = 8080
此处以 hash (#) 开头的任何行都将被视为注解,并且将被 Struts 2 忽略。
Struts 2 - Action 动作
Action(动作)是 Struts2 框架的核心,就像任何 MVC(模型视图控制器)框架一样。每个 URL 都映射到特定动作,该动作提供处理逻辑,而处理逻辑对于处理来自用户的请求必不可少。
但动作还具有另外两个重要功能。首先,动作在将数据从请求传输到视图(无论是 JSP 还是其他类型的结果)中起着重要作用。其次,动作必须协助框架确定哪个结果应呈现将在请求响应中返回的视图。
创建动作
Struts2 中对动作的唯一要求是必须有一个无参数方法,该方法返回 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 示例中的操作方法 −
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; } }
为了说明操作方法控制视图这一点,让我们对 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>
创建视图
让我们在 eclipse 项目的 WebContent 文件夹中创建以下 jsp 文件 HelloWorld.jsp。为此,右键单击项目资源管理器中的 WebContent 文件夹并选择 New >JSP File。如果返回结果为 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>
以下是当操作结果为 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。此文件将用作初始操作 URL,用户可以单击此 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 http://localhost:8080/HelloWorldStruts2/index.jsp。这将为您提供以下屏幕 −

让我们输入一个单词"SECRET",您应该会看到以下页面 −

现在输入除"SECRET"之外的任何单词,您应该会看到以下页面 −

创建多个操作
您经常会定义多个操作来处理不同的请求并向用户提供不同的 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 文件中配置这些操作,如下所示 −
<?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>
如您在上面的假设示例中所见,操作结果 SUCCESS 和 ERROR 是重复的。
为了解决这个问题,建议您创建一个包含结果的类。
Struts 2 - 拦截器
拦截器在概念上与 servlet 过滤器或 JDK 代理类相同。拦截器允许独立于操作和框架实现横切功能。您可以使用拦截器 − 实现以下功能
在调用操作之前提供预处理逻辑。
在调用操作之后提供后处理逻辑。
捕获异常以便执行替代处理。
Struts2 框架中提供的许多功能都是使用拦截器实现的;
示例包括异常处理、文件上传、生命周期回调等。事实上,由于 Struts2 强调其大部分功能都依赖于拦截器,因此不太可能为每个操作分配 7 或 8 个拦截器。
Struts2 框架拦截器
Struts 2 框架提供了一个很好的开箱即用拦截器列表,这些拦截器已预先配置并可立即使用。下面列出了一些重要的拦截器 −
Sr.No | 拦截器 &描述 |
---|---|
1 | alias 允许参数在不同的请求中使用不同的名称别名。 |
2 | checkbox 通过为未选中的复选框添加参数值 false 来协助管理复选框。 |
3 | conversionError 将字符串转换为参数类型的错误信息放入操作的字段错误中。 |
4 | createSession 如果不存在 HTTP 会话,则自动创建该会话。 |
5 | debugging 为开发人员提供几个不同的调试屏幕。 |
6 | execAndWait 在后台执行操作时,将用户发送到中间等待页面。 |
7 | exception 将操作引发的异常映射到结果,允许通过重定向自动处理异常。 |
8 | fileUpload 方便轻松上传文件。 |
9 | i18n 在用户会话期间跟踪所选语言环境。 |
10 | logger 通过输出正在执行的操作的名称提供简单的日志记录。 |
11 | params 设置操作的请求参数。 |
12 | prepare 这通常用于执行预处理工作,例如设置数据库连接。 |
13 | profile 允许记录操作的简单分析信息。 |
14 | scope 在会话或应用程序范围内存储和检索操作的状态。 |
15 | ServletConfig 为操作提供对各种基于 servlet 的信息的访问。 |
16 | timer 以操作执行时间的形式提供简单的分析信息。 |
17 | token 检查操作是否具有有效令牌以防止重复提交表单。 |
18 | validation 为以下操作提供验证支持动作 |
请参阅 Struts 2 文档,了解上述拦截器的完整详细信息。但我将向您展示如何在 Struts 应用程序中使用拦截器。
如何使用拦截器?
让我们看看如何在"Hello World"程序中使用现有的拦截器。我们将使用 timer 拦截器,其目的是测量执行操作方法所需的时间。同时,我使用 params 拦截器,其目的是将请求参数发送到操作。您可以尝试不使用这个拦截器的示例,您会发现 name 属性未设置,因为参数无法到达操作。
我们将保留 HelloWorldAction.java、web.xml、HelloWorld.jsp 和 index.jsp 文件,因为它们已在 Examples 一章中创建,但让我们修改 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>
右键单击项目名称,然后单击 Export > WAR File 以创建 War 文件。然后将此 WAR 部署到 Tomcat 的 webapps 目录中。最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2/index.jsp。这将产生以下屏幕 −

现在在给定的文本框中输入任何单词,然后单击 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.
此处的底线是由于 timer 拦截器生成的,它表明该操作总共花费了 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 Resources > 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() 方法将导致操作本身被执行。
下图通过请求流显示了相同的概念 −

创建操作类
让我们在 Java Resources > 下创建一个 java 文件 HelloWorldAction.java src 的包名为 com.tutorialspoint.struts2,其内容如下所示。
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 方法。
创建视图
让我们在 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>
创建主页
我们还需要在 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 类及其执行方法。
配置文件
现在,我们需要注册我们的拦截器,然后像在上一个示例中调用默认拦截器一样调用它。要注册新定义的拦截器,<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>标签内调用多个拦截器。您可以使用不同的操作调用同一个拦截器。
需要在WebContent下的WEB-INF文件夹下创建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>
右键单击项目名称,然后单击 Export > WAR File 以创建 War 文件。然后将此 WAR 部署到 Tomcat 的 webapps 目录中。最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2/index.jsp。这将产生以下屏幕 −

现在在给定的文本框中输入任何单词,然后单击 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 操作的拦截器的完整堆栈。需要注意的是,拦截器是按照配置的顺序执行的。例如,在上述情况下,exception 将首先执行,其次是 servlet-config,依此类推。
Struts 2 - Results & Result 类型
如前所述,<results> 标签在 Struts2 MVC 框架中扮演 view 的角色。操作负责执行业务逻辑。执行业务逻辑后的下一步是使用 <results> 标签显示视图。
结果通常会附带一些导航规则。例如,如果操作方法是对用户进行身份验证,则可能出现三种结果。
- 登录成功
- 登录失败 - 用户名或密码不正确
- 帐户已锁定
在这种情况下,操作方法将配置三个可能的结果字符串和三个不同的视图来呈现结果。我们已经在前面的例子中看到了这一点。
但是,Struts2 不会将您限制于使用 JSP 作为视图技术。毕竟,MVC 范式的整个目的是保持各层分离且高度可配置。例如,对于 Web2.0 客户端,您可能希望返回 XML 或 JSON 作为输出。在这种情况下,您可以为 XML 或 JSON 创建新的结果类型并实现这一点。
Struts 附带了许多预定义的结果类型,以及我们已经看到的默认结果类型dispatcher,用于分派到 JSP 页面。 Struts 允许您使用其他标记语言作为视图技术来呈现结果,常见的选择包括 Velocity、Freemaker、XSLT 和 Tiles。
Dispatcher 结果类型
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 参数确定是否将为 OGNL 表达式解析 location 参数。
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 文件。
现在右键单击项目名称,然后单击 Export > WAR File 以创建 War 文件。
然后将此 WAR 部署到 Tomcat 的 webapps 目录中。最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2/index.jsp。这将产生以下屏幕。

输入值"Struts2"并提交页面。您应该会看到下一页。

如您所见,这与 JSP 视图完全相同,只是我们不必使用 JSP 作为视图技术。我们在此示例中使用了 Freemaker。
重定向结果类型
redirect 结果类型调用标准 response.sendRedirect() 方法,导致浏览器创建指向给定位置的新请求。
我们可以在 <result...> 元素的主体中或作为 <param name = "location"> 元素提供位置。重定向还支持 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 - Value Stack/OGNL
Value Stack(值堆栈)
值堆栈是一组多个对象,它们按提供的顺序保存以下对象 −
Sr.No | 对象和说明 |
---|---|
1 | 临时对象 在页面执行期间会创建各种临时对象。例如,在 JSP 标记中循环遍历集合的当前迭代值。 |
2 | 模型对象 如果您在 struts 应用程序中使用模型对象,则当前模型对象将放置在值堆栈上的操作之前。 |
3 | 操作对象 这将是正在执行的当前操作对象。 |
4 | 命名对象 这些对象包括 #application、#session、#request、#attr 和 #parameters,并引用相应的servlet 范围。 |
可以通过为 JSP、Velocity 或 Freemarker 提供的标签访问值堆栈。我们将在单独的章节中研究各种标签,用于获取和设置 struts 2.0 值堆栈。您可以在操作中获取 valueStack 对象,如下所示 −
ActionContext.getContext().getValueStack()
一旦您拥有 ValueStack 对象,您就可以使用以下方法来操作该对象 −
Sr.No | ValueStack 方法 &描述 |
---|---|
1 | Object findValue(String expr) 通过按照默认搜索顺序对堆栈评估给定的表达式来查找值。 |
2 | CompoundRoot getRoot() 获取包含推送到堆栈上的对象的 CompoundRoot。 |
3 | Object peek() 在不更改堆栈的情况下获取堆栈顶部的对象。 |
4 | Object pop() 获取堆栈顶部的对象并将其从堆栈中移除。 |
5 | void 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 堆栈 − 所有操作变量都存储在此处
Request − 请求范围变量
Parameters − 请求参数
Atributes − 存储在页面、请求、会话和应用程序范围中的属性
重要的是要了解 Action 对象始终在值堆栈中可用。因此,如果您的 Action 对象具有属性 "x" 和 "y",则您可以随时使用它们。
ActionContext 中的对象使用磅号符号引用,但是,值堆栈中的对象可以直接引用。
例如,如果 employee 是操作类的属性,则可以按以下方式引用它 −
<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 示例
创建操作
让我们考虑以下操作类,其中我们正在访问 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 在执行时会将您的操作添加到值堆栈的顶部。因此,将内容放入值堆栈的通常方法是将值的 getter/setter 添加到您的 Action 类,然后使用 <s:property> 标记访问这些值。但我向您展示了 ActionContext 和 ValueStack 在 struts 中的工作原理。
创建视图
让我们在您的 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> 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>
配置文件
以下是 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 http://localhost:8080/HelloWorldStruts2/index.jsp。这将产生以下屏幕

现在在给定的文本框中输入任何单词,然后单击"Say Hello"按钮以执行定义的操作。现在,如果您检查生成的日志,您会在底部找到以下文本 −
valueStack 的大小:3
这将显示以下屏幕,其中将显示您输入的任何值以及我们放在 ValueStack 上的 key1 和 key2 的值。
Struts 2 - 文件上传
Struts 2 框架提供使用"基于 HTML 表单的文件上传"处理文件上传的内置支持。上传文件时,通常会将其存储在临时目录中,并且应由您的 Action 类处理或移动到永久目录,以确保数据不会丢失。
注意 − 服务器可能已制定安全策略,禁止您写入临时目录和属于您的 Web 应用程序的目录以外的目录。
Struts 中的文件上传可通过名为 FileUpload 拦截器的预定义拦截器进行,该拦截器可通过 org.apache.struts2.interceptor.FileUploadInterceptor 类获得,并作为defaultStack的一部分包含在内。您仍然可以在 struts.xml 中使用它来设置各种参数,如下所示。
创建视图文件
让我们从创建浏览和上传选定文件所需的视图开始。因此,让我们创建一个 index.jsp,其中包含允许用户上传文件的纯 HTML 上传表单 −
<%@ 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>
创建操作类
接下来,让我们创建一个名为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 拦截器和参数拦截器为我们完成了所有繁重的工作。
FileUpload 拦截器默认为您提供三个参数。它们以以下模式命名 −
[您的文件名参数] − 这是用户上传的实际文件。在此示例中,它将是"myFile"
[您的文件名参数]ContentType − 这是已上传文件的内容类型。在此示例中,它将是"myFileContentType"
[您的文件名参数]FileName − 这是已上传文件的名称。在此示例中,它将是"myFileFileName"
由于 Struts 拦截器,我们可以使用这三个参数。我们所要做的就是在我们的 Action 类中创建具有正确名称的三个参数,这些变量会自动为我们连接。因此,在上面的示例中,我们有三个参数和一个操作方法,如果一切顺利,则仅返回"成功",否则返回"错误"。
配置文件
以下是控制文件上传过程的 Struts2 配置属性 −
Sr.No | 属性 &描述 |
---|---|
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 http://localhost:8080/HelloWorldStruts2/upload.jsp。这将产生以下屏幕 −

现在使用浏览按钮选择一个文件"Contacts.txt",然后单击上传按钮,该文件将上传到您的服务器,您应该会看到下一页。您可以检查上传的文件是否保存在 C:\apache-tomcat-6.0.33\work 中。

请注意,FileUpload 拦截器会自动删除上传的文件,因此您必须在删除上传文件之前以编程方式将其保存在某个位置。
错误消息
fileUplaod 拦截器使用几个默认错误消息键 −
Sr.No | 错误消息键 &描述 |
---|---|
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 文件夹中。完成此操作后,我们现在可以创建操作类了。
创建操作
操作类具有与数据库表中的列相对应的属性。我们有 user、password 和 name 作为字符串属性。在操作方法中,我们使用用户和密码参数来检查用户是否存在,如果存在,我们将在下一个屏幕中显示用户名。
如果用户输入了错误的信息,我们会再次将其发送到登录屏幕。
以下是 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://localhost/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; } }
创建主页
现在,让我们创建一个 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 文件,该文件将在操作返回 SUCCESS 时调用,但如果操作返回 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>
如果操作返回错误,则以下将是视图文件 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>
配置文件
最后,让我们使用 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>
现在,右键单击项目名称,然后单击 Export > WAR File 以创建 War 文件。然后将此 WAR 部署到 Tomcat 的 webapps 目录中。最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2/index.jsp。这将产生以下屏幕 −

输入错误的用户名和密码。您应该看到下一页。

现在输入 scott 作为用户名和 navy 作为密码。您应该会看到下一页。

Struts 2 - 发送电子邮件
本章介绍如何使用 Struts 2 应用程序发送电子邮件。
对于此练习,您需要从 JavaMail API 1.4.4 下载并安装 mail.jar,并将 mail.jar 文件放在您的 WEB-INF\lib 文件夹中,然后继续按照创建操作、视图和配置文件的标准步骤进行操作。
创建操作
下一步是创建一个负责发送电子邮件的操作方法。让我们创建一个名为 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 库通过提供的参数发送电子邮件。如果邮件发送成功,则操作返回 SUCCESS,否则返回 ERROR。
创建主页
让我们编写主页 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,如果操作返回 SUCCESS,则将调用该文件,但如果操作返回 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>
如果操作返回错误,则以下将是视图文件 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>
配置文件
现在让我们使用 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>
现在,右键单击项目名称,然后单击 Export > WAR File 以创建 War 文件。然后将此 WAR 部署到 Tomcat 的 webapps 目录中。最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2/index.jsp。这将产生以下屏幕 −

输入所需信息并单击 发送电子邮件 按钮。如果一切顺利,那么您应该会看到以下页面。

Struts 2 - 验证框架
在本章中,我们将深入了解 Struts 验证框架。在 Struts 核心中,我们有一个验证框架,它帮助应用程序在执行操作方法之前运行规则以执行验证。
客户端验证通常使用 Javascript 实现。但是,不应仅依赖客户端验证。最佳实践建议在应用程序框架的所有级别引入验证。现在让我们看看在 Struts 项目中添加验证的两种方法。
在这里,我们将以一个 Employee 为例,其姓名和年龄应使用一个简单的页面来捕获,我们将进行这两个验证,以确保用户始终输入的姓名和年龄应在 28 到 65 之间的范围内。
让我们从示例的主 JSP 页面开始。
创建主页
让我们编写主页 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>
创建操作
因此,让我们定义一个小操作类 Employee,然后在 Employee.java 文件中添加一个名为 validate() 的方法,如下所示。确保您的操作类扩展了 ActionSupport 类,否则您的验证方法将不会被执行。
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"); } } }
如上例所示,验证方法检查"姓名"字段是否有值。如果没有提供任何值,我们将为"姓名"字段添加一个字段错误,并附带自定义错误消息。其次,我们检查"年龄"字段的输入值是否在 28 到 65 之间,如果不满足此条件,我们将在验证字段上方添加错误。
配置文件
最后,让我们使用 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 http://localhost:8080/HelloWorldStruts2/index.jsp。这将产生以下屏幕 −

现在不要输入任何必需信息,只需单击提交按钮即可。您将看到以下结果 −

输入所需信息,但输入错误的发件人字段,假设姓名为"test",年龄为 30,最后单击Submit按钮。您将看到以下结果 −

此验证如何工作?
当用户按下提交按钮时,Struts 2 将自动执行验证方法,如果方法中列出的任何"if"语句为真,Struts 2 将调用其 addFieldError 方法。如果添加了任何错误,则 Struts 2 将不会继续调用执行方法。相反,Struts 2 框架将返回 input 作为调用操作的结果。
因此,当验证失败且 Struts 2 返回 input 时,Struts 2 框架将重新显示 index.jsp 文件。由于我们使用了 Struts 2 表单标签,Struts 2 将自动在表单字段上方添加错误消息。
这些错误消息是我们在 addFieldError 方法调用中指定的。addFieldError 方法有两个参数。第一个是错误适用的 form 字段名称,第二个是要在该表单字段上方显示的错误消息。
addFieldError("name","The name is required");
要处理 input 的返回值,我们需要在 struts.xml 中的操作节点中添加以下结果。
<result name = "input">/index.jsp</result>
基于 XML 的验证
进行验证的第二种方法是将 xml 文件放在操作类旁边。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 中。让我们拥有如下员工操作类,而无需 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标记
消息和错误。
在操作类中。
资源包
Struts2使用资源包为Web应用程序的用户提供多种语言和语言环境选项。您无需担心用不同语言编写页面。您所要做的就是为您想要的每种语言创建一个资源包。资源包将包含用户语言的标题、消息和其他文本。资源包是包含应用程序默认语言的键/值对的文件。
资源文件最简单的命名格式是 −
bundlename_language_country.properties
此处,bundlename 可以是 ActionClass、Interface、SuperClass、Model、Package、Global resource properties。下一部分 language_country 表示国家/地区区域设置,例如,西班牙语(西班牙)区域设置由 es_ES 表示,英语(美国)区域设置由 en_US 表示等。您可以跳过可选的国家/地区部分。
当您通过其键引用消息元素时,Struts 框架将按以下顺序搜索相应的消息包 −
- 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、文本标签、UI 标签的 key 属性和 i18n 标签。让我们简要了解一下 −
要显示 i18n 文本,请在 property 标签或任何其他标签(例如以下 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)第一个操作 a 处理语言环境并使用不同语言显示相同的 index.jsp 文件(b)另一个操作是处理提交表单本身。这两个操作都将返回 SUCCESS,但我们将根据返回值采取不同的操作,因为这两个操作的目的不同
处理语言环境的操作
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>
现在,右键单击项目名称,然后单击 Export > WAR File 以创建 War 文件。然后将此 WAR 部署到 Tomcat 的 webapps 目录中。最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2/index.jsp。这将产生以下屏幕 −

现在选择任何一种语言,假设我们选择 Spanish,它将显示以下结果 −

您也可以尝试使用法语。最后,让我们在西班牙语区域设置下尝试单击提交按钮,它将显示以下屏幕 −

恭喜,现在您有一个多语言网页,您可以在全球范围内推出您的网站。
Struts 2 - 类型转换
协议将 HTTP 请求中的所有内容视为 String。这包括数字、布尔值、整数、日期、小数和其他所有内容。但是,在 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。
为了进行本练习,我将环境硬编码为"开发",将操作系统硬编码为"Windows XP SP3"。
在实时项目中,您可以从系统配置中获取此信息。
让我们有以下操作类 −
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.xml 将 system.jsp 和 SystemDetails.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>
右键点击项目名称,点击Export > WAR File创建一个War文件。
然后将这个WAR部署到Tomcat的webapps目录中。
最后,启动Tomcat服务器,尝试访问URL http://localhost:8080/HelloWorldStruts2/system.action。这将产生以下屏幕−

上面的输出有什么问题?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 转换为 String 以及反之亦然。
现在让我们在应用程序中使用该转换器之前先注册它。有两种方法可以注册转换器。
如果转换器只用于特定操作,则必须创建一个属性文件,该文件需要命名为 '[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 类型的对象时都可以自动进行转换。现在,如果您重新编译并重新运行该程序,那么您将获得更好的输出,如下所示 −

显然,现在结果会更好,这意味着我们的 Struts 转换器运行良好。
这就是您可以创建多个转换器并注册它们以根据您的要求使用的方法。
Struts 2 - 主题和模板
在开始本章的实际教程之前,让我们先了解一下 https://struts.apache.org−
给出的几个定义Sr.No | 术语和描述 |
---|---|
1 | TAG 从 JSP、FreeMarker 或 Velocity 中执行的一小段代码。 |
2 | TEMPLATE 一段代码,通常用 FreeMarker 编写,可以通过某些标记(HTML 标记)呈现。 |
3 | THEME 打包在一起以提供通用功能的模板集合。 |
我还建议您浏览一下Struts2 本地化 章节,因为我们将再次采用相同的示例进行练习。
当您在网页中使用 Struts 2 标签(例如 <s:submit...>、<s:textfield...> 等)时,Struts 2 框架会生成具有预配置样式和布局的 HTML 代码。Struts 2 带有三个内置主题 −
Sr.No | 主题 &描述 |
---|---|
1 | 简单主题 没有"花哨"的极简主题。例如,textfield 标签呈现 HTML <input/>标签,没有标签、验证、错误报告或任何其他格式或功能。 |
2 | XHTML 主题 这是 Struts 2 使用的默认主题,提供简单主题提供的所有基本功能,并添加了一些功能,例如标准两列表格布局(用于 HTML)、每个 HTML 的标签、验证和错误报告等。 |
3 | CSS_XHTML 主题 此主题提供简单主题提供的所有基本功能,并添加了一些功能,例如标准两列基于 CSS 的布局、使用 <div>对于 HTML Struts 标签,每个 HTML Struts 标签的标签,根据 CSS 样式表放置。 |
如上所述,如果您不指定主题,则 Struts 2 将默认使用 xhtml 主题。例如,此 Struts 2 选择标签 −
<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 属性
标签周围的表单标签上的 theme 属性
名为"theme"的页面范围属性
名为"theme"的请求范围属性
名为"theme"的会话范围属性
名为"theme"的应用程序范围属性
struts.ui.theme 属性struts.properties(默认为 xhtml)
如果您愿意为不同的标签使用不同的主题,则以下是在标签级别指定它们的语法 −
<s:textfield name = "name" label = "Name" theme="xhtml"/>
因为在每个标签上使用主题不太实用,所以我们只需在 struts.properties 文件中使用以下标签指定规则 −
# 标准 UI 主题 struts.ui.theme = xhtml # 主题模板所在的目录 struts.ui.templateDir = template # 设置默认模板类型。 ftl、vm 或 jsp struts.ui.templateSuffix = ftl
以下是我们从本地化章节中获得的结果,其中我们使用默认主题,并在 struts-default.properties 文件中设置 struts.ui.theme = xhtml,该文件默认位于 struts2-core.xy.z.jar 文件中。

主题如何工作?
对于给定的主题,每个 struts 标签都有一个关联的模板,如 s:textfield → text.ftl 和 s: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.ui.templateSuffix 和 struts.ui.templateDir 在 struts.properties 中相应地设置配置。
创建新主题
创建新主题的最简单方法是复制任何现有主题/模板文件并进行必要的修改。
让我们首先在 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 文件
# 自定义它们 struts.ui.theme = mytheme # 主题模板所在的目录 struts.ui.templateDir = template # 将模板类型设置为 ftl。 struts.ui.templateSuffix = ftl
现在,完成此更改后,右键单击项目名称,然后单击 Export > WAR File 以创建 War 文件。然后将此 WAR 部署到 Tomcat 的 webapps 目录中。最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2。这将产生以下屏幕 −

您可以看到表单组件周围有一个边框,这是我们从 xhtml 主题复制后对主题所做的更改的结果。如果您花一点精力学习 FreeMarker,那么您将能够非常轻松地创建或修改您的主题。
希望现在您对 Sturts 2 主题和模板有了基本的了解!
Struts 2 - 异常处理
Struts 提供了一种更简单的方法来处理未捕获的异常并将用户重定向到专用的错误页面。您可以轻松配置 Struts,以便针对不同的异常设置不同的错误页面。
Struts 通过使用"异常"拦截器使异常处理变得简单。"异常"拦截器是默认堆栈的一部分,因此您无需执行任何额外操作即可对其进行配置。它开箱即用,可供您使用。
让我们看一个简单的 Hello World 示例,在 HelloWorldAction.java 文件中进行了修改。在这里,我们故意在 HelloWorldAction 操作代码中引入了一个 NullPointer 异常。
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 http://localhost:8080/HelloWorldStruts2/index.jsp。这将产生以下屏幕 −

输入值"Struts2"并提交页面。您应该看到以下页面 −

如上例所示,默认异常拦截器在处理异常方面做得很好。
现在让我们为我们的异常创建一个专用的错误页面。创建一个名为 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 配置为使用专用的 Error.jsp 来处理 NullPointerException。如果您现在重新运行该程序,您将看到以下输出 −

除此之外,Struts2 框架还附带一个"日志"拦截器来记录异常。通过启用记录器来记录未捕获的异常,我们可以轻松查看堆栈跟踪并找出问题所在
全局异常映射
我们已经了解了如何处理特定于操作的异常。我们可以全局设置一个将应用于所有操作的异常。例如,为了捕获相同的 NullPointerException 异常,我们可以在 struts.xml 文件中的 <package...> 标签内添加 <global-exception-mappings...> 标签,并将其 <result...> 标签添加到 <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 注解,我们可以实现零配置。
要开始在项目中使用注解,请确保已在 WebContent/WEB-INF/lib 文件夹中包含以下 jar 文件 −
- 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-l ogging-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 验证 一章中解释的验证示例。
在这里,我们将以一个员工为例,他的姓名、年龄将使用一个简单的页面捕获,我们将进行两次验证,以确保 ÜSER 始终输入姓名,年龄应在 28 至 65 岁之间。
让我们从示例的主 JSP 页面开始。
创建主页
让我们编写主页 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>
创建操作
这是使用注解的地方。让我们用注解重新定义操作类Employee,然后在Employee.java文件中添加一个名为validate()的方法,如下所示。确保您的操作类扩展了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 注解是结果的集合。
在结果注解下,我们有两个结果注解。结果注解具有与执行方法的结果相对应的 name。它们还包含一个位置,即应该提供哪个视图,对应于来自 execute() 的返回值
下一个注解是 Action 注解。这用于修饰 execute() 方法。Action 方法还接受一个值,该值是调用操作的 URL。
最后,我使用了两个 validation 注解。我已经在 name 字段上配置了必填字段验证器,并在 age 字段上配置了整数范围验证器。我还为验证指定了自定义消息。
配置文件
我们确实不需要 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 http://localhost:8080/HelloWorldStruts2/index.jsp。这将产生以下屏幕 −

现在不要输入任何必需信息,只需单击提交按钮即可。您将看到以下结果 −

输入所需信息,但输入错误的发件人字段,假设姓名为"test",年龄为 30,最后单击提交按钮。您将看到以下结果 −

Struts 2 注解类型
Struts 2 应用程序可以使用 Java 5 注解作为 XML 和 Java 属性配置的替代方案。您可以查看与不同类别相关的最重要的注解列表 −
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>
合并标签
这些合并标签以两个或多个列表为参数,并将它们合并在一起,如下所示 −
<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 - Data 数据标签
Struts 2 数据标签主要用于操作页面上显示的数据。下面列出了重要的数据标签:<从这里开始>
操作标签
此标签允许开发人员通过指定操作名称和可选命名空间直接从 JSP 页面调用操作。标签的主体内容用于呈现操作的结果。除非指定了 executeResult 参数,否则 struts.xml 中为此操作定义的任何结果处理器都将被忽略。
<div>执行操作的标签</div> <br /> <s:action name = "actionTagAction" executeresult = "true" /> <br /> <div>调用动作类中的特殊方法</div> <br /> <s:action name = "actionTagAction!specialMethod" executeresult = "true" />
Include 标签
这些 include 将用于将一个 JSP 文件包含到另一个 JSP 页面中。
<-- 第一个语法 --> <s:include value = "myJsp.jsp" /> <-- 第二种语法 --> <s:include value = "myJsp.jsp"> <s:param name = "param1" value = "value2" /> <s:param name = "param2" value = "value2" /> </s:include> <-- 第三种语法 -> <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 元素,用于设置该类上的任何变量方法。如果在 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 标签可让您快速轻松地格式化日期。您可以指定自定义格式(例如"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 (String) − 参数的名称
value (Object) − 参数的值
<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、page 和 action。
<s:set name = "myenv" value = "environment.name"/> <s:property value = "myenv"/>
文本标签
这些 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: 和不同的属性。当我们执行上述程序时,我们将获得以下用户界面,前提是您已为所有使用的键设置了正确的映射。

如图所示,s:head 生成 Struts2 应用程序所需的 javascript 和样式表元素。
接下来,我们有 s:div 和 s:text 元素。s:div 用于呈现 HTML Div 元素。这对于不喜欢将 HTML 和 Struts 标签混合在一起的人很有用。对于那些人来说,他们可以选择使用 s:div 来呈现 div。
如图所示的 s:text 用于在屏幕上呈现文本。
接下来我们有熟悉的 s:form 标签。s:form 标签有一个 action 属性,它决定了在哪里提交表单。由于表单中有一个文件上传元素,我们必须将 enctype 设置为 multipart。否则,我们可以将其留空。
在 form 标签的末尾,我们有 s:submit 标签。这用于提交表单。提交表单时,所有表单值都将提交给 s:form 标签中指定的操作。
在 s:form 内部,我们有一个名为 secret 的隐藏属性。这会在 HTML 中呈现一个隐藏元素。在我们的例子中,"secret"元素的值为"abracadabra"。此元素对最终用户不可见,用于将状态从一个视图传送到另一个视图。
接下来我们有 s:label、s:textfield、s:password 和 s:textarea 标签。它们分别用于呈现标签、输入字段、密码和文本区域。我们在"Struts - 发送电子邮件"示例中看到了它们的实际作用。
这里要注意的重要一点是"key"属性的使用。"key"属性用于从属性文件中获取这些控件的标签。我们已经在 Struts2 本地化、国际化章节中介绍了此功能。
然后,我们有 s:file 标签,它呈现输入文件上传组件。此组件允许用户上传文件。在此示例中,我们使用了 s:file 标签的"accept"参数来指定允许上传哪些文件类型。
最后我们有 s:token 标签。令牌标记生成一个唯一令牌,用于查明表单是否被重复提交
呈现表单时,将放置一个隐藏变量作为令牌值。假设令牌为"ABC"。提交此表单时,Struts Fitler 将根据会话中存储的令牌检查令牌。如果匹配,它将从会话中删除令牌。现在,如果意外重新提交表单(通过刷新或点击浏览器后退按钮),表单将以"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>
当我们执行上述程序时,我们的输出将类似于以下 −

现在让我们看一下示例。在第一个示例中,我们创建了一个带有标签"性别"的简单单选按钮。name 属性对于单选按钮标签是必需的,因此我们指定一个名称"性别"。然后我们为性别提供一个列表。该列表填充了值"男性"和"女性"。因此,在输出中我们得到一个包含两个值的单选按钮。
在第二个示例中,我们创建了一个复选框列表。这是为了收集用户的爱好。用户可以有多个爱好,因此我们使用复选框而不是单选按钮。复选框填充了列表"体育"、"电视"和"购物"。这将爱好显示为复选框列表。
选择 UI 标签
让我们探索 Struts 提供的选择标签的不同变体。让我们看一个带有选择标签的简单视图页面 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>
当我们执行上述程序时,我们的输出将类似于以下 −

现在让我们逐一介绍各个案例。
首先,select 标记呈现 HTML 选择框。在第一个示例中,我们创建了一个名为"username"且标签为"username"的简单选择框。选择框将填充一个包含名称 Mike、John 和 Smith 的列表。
在第二个示例中,我们公司的总部设在美国。它在亚洲和欧洲也设有全球办事处。我们希望在选择框中显示办事处,但我们希望按大洲名称对全球办事处进行分组。这是 optgroup 派上用场的地方。我们使用 s:optgroup 标记来创建一个新组。我们为该组提供一个标签和一个单独的列表。
在第三个示例中,使用了组合框。组合框是输入字段和选择框的组合。用户可以从选择框中选择一个值,在这种情况下,输入字段将自动填充用户选择的值。如果用户直接输入值,则不会选择选择框中的任何值。
在我们的示例中,我们的组合框列出了太阳星座。选择框仅列出四个条目,如果列表中没有太阳星座,则允许用户输入太阳星座。我们还向选择框添加了一个标题条目。标题条目显示在选择框的顶部。在我们的示例中,我们希望显示"请选择"。如果用户未选择任何内容,则我们假设值为 -1。在某些情况下,我们不希望用户选择空值。在这些情况下,可以将"emptyOption"属性设置为 false。最后,在我们的示例中,我们提供了"capricorn"作为组合框的默认值。
在第四个示例中,我们有一个双选框。当您想要显示两个选择框时,使用双选框。第一个选择框中选择的值决定第二个选择框中显示的内容。在我们的示例中,第一个选择框显示"技术"和"其他"。如果用户选择技术,我们将在第二个选择框中显示 IT 和硬件。否则,我们将显示会计和人力资源。这可以使用示例中显示的"list"和"doubleList"属性来实现。
在上面的示例中,我们进行了比较以查看顶部选择框是否等于技术。如果是,则显示 IT 和硬件。
我们还需要为顶部框("name = 'Occupations'")和底部框(doubleName = 'occupations2')命名
Struts 2 - Ajax 标签
Struts 使用 DOJO 框架来实现 AJAX 标签。首先,要继续此示例,您需要将 struts2-dojo-plugin-2.2.3.jar 添加到您的类路径中。
您可以从 struts2 下载的 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>
当我们运行上述示例时,我们得到以下输出 −

现在让我们一步一步地完成这个示例。
首先要注意的是添加了一个带有前缀 sx 的新标签库。这个 (struts-dojo-tags) 是专门为 ajax 集成创建的标签库。
然后在 HTML 头部我们调用 sx:head。这将初始化 dojo 框架并使其为页面内的所有 AJAX 调用做好准备。这一步很重要 - 如果没有初始化 sx:head,您的 ajax 调用将无法工作。
首先我们有 autocompleter 标签。autocompleter 标签看起来很像一个选择框。它填充了红色、绿色和蓝色的值。但是选择框与此选择框的不同之处在于它会自动完成。也就是说,如果您开始输入 gr,它将用"绿色"填充。除此之外,此标签与我们之前介绍的 s:select 标签非常相似。
接下来,我们有一个日期时间选择器。此标签创建一个输入字段,旁边有一个按钮。按下按钮时,会显示一个弹出日期时间选择器。当用户选择日期时,日期将以标签属性中指定的格式填充到输入文本中。在我们的示例中,我们已将 dd/MM/yyyy 指定为日期格式。
接下来,我们为在前面的练习中创建的 system.action 文件创建一个 url 标签。它不一定是 system.action - 它可以是您之前创建的任何操作文件。然后我们有一个 div,其超链接设置为 url,延迟设置为 2 秒。运行此程序时,将显示"初始内容"2 秒,然后 div 的内容将被 hello.action 执行的内容替换。
最后,我们有一个带有两个选项卡的简单选项卡面板。选项卡本身是带有标签 Tab 1 和 Tab2 的 div。
值得注意的是,Struts 中的 AJAX 标记集成仍在进行中,并且这种集成的成熟度随着每个版本的发布而逐渐提高。
Struts 2 与 Spring 集成
Spring 是一种流行的 Web 框架,可轻松集成许多常见的 Web 任务。那么问题是,既然有了 Struts2,为什么还需要 Spring?Spring 不仅仅是一个 MVC 框架 - 它还提供了 Struts 所没有的许多其他优点。
例如:依赖注入对任何框架都很有用。在本章中,我们将通过一个简单的示例来了解如何将 Spring 和 Struts2 集成在一起。
首先,您需要从 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
最后从您的WEB-INF/lib中添加struts2-spring-plugin-x.y.z.jar struts lib 目录。如果您使用的是 Eclipse,那么您可能会遇到异常 java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener。
要解决此问题,您必须进入 Marker 选项卡,然后逐个右键单击类依赖项,然后执行快速修复以发布/导出所有依赖项。最后确保 marker 选项卡下没有依赖冲突。

现在让我们按如下方式为 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 的简单操作类,它有两个属性 - 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>
如上所示,我们已经配置了用户 bean,并将值 Michael 和 Jackson 注入到 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 文件非常简单。它只有一个用途 - 显示用户对象的名字和姓氏的值。最后,让我们使用 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>
需要注意的重要一点是,我们使用 id userClass 来引用该类。这意味着我们使用 spring 为 User 类进行依赖注入。
现在右键单击项目名称,然后单击 Export > WAR File 以创建 War 文件。然后将此 WAR 部署到 Tomcat 的 webapps 目录中。最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2/User.jsp。这将产生以下屏幕 −

现在我们已经了解了如何将两个伟大的框架结合在一起。这结束了 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
除上述内容外,我们还必须从您的 WEB-INF/lib 中的 struts2 下载中复制以下 jar 文件。
- commons-beanutils-x.y.zjar
- commons-digester-x.y.jar
- struts2-tiles-plugin-x.y.z.jar
现在让我们设置 web.xml 以用于 Struts-Tiles 集成,如下所示。这里有两个要点需要注意。首先,我们需要告诉 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 中定义一个基本的骨架布局。它有五个可重复使用/可覆盖的区域。即 title、banner、menu、body 和 footer。我们为 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="http://www.tutorialspoint.com/images/tp-logo.gif"/>
menu.jsp 文件将包含以下几行,它们是指向 TigerMenu.action 和 LionMenu.action struts 操作的链接。
<%@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
接下来,让我们创建动作类文件 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 View 结果类型,因此我们将结果类型"tiles"创建为"org.apache.struts2.view.tiles.TilesResult"类。
接下来,我们想说,如果请求是针对 /tigerMenu.action,则将用户带到 tiger tiles 页面,如果请求是针对 /lionMenu.action,则将用户带到 lion tiles 页面。
我们使用一些正则表达式来实现这一点。在我们的操作定义中,我们说与模式"*Menu"匹配的任何内容都将由此操作处理。匹配方法将在 MenuAction 类中调用。也就是说,tigerMenu.action 将调用 tiger(),而 lionMenu.action 将调用 lion()。然后,我们需要将结果映射到适当的图块页面。
现在右键单击项目名称,然后单击导出 > WAR 文件以创建 War 文件。然后将此 WAR 部署到 Tomcat 的 webapps 目录中。最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2/tigerMenu.jsp。这将产生以下屏幕 −

同样,如果您转到 lionMenu.action 页面,您将看到使用相同图块布局的 lion 页面。
Struts 2 与 Hibernate 集成
Hibernate 是一种高性能对象/关系持久性和查询服务,根据开源 GNU 宽通用公共许可证 (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://www.tutorialspoint.com/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。然后我们声明了连接的用户名、密码和池大小。我们还通过将"show_sql"设置为 true 来表明我们希望在日志文件中看到 SQL。请阅读 Hibernate 教程以了解这些属性的含义。
最后,我们将映射类设置为 com.tutorialspoint.hibernate.Student,我们将在本章中创建它。
环境设置
接下来,您需要为这个项目准备大量的 jar。附件是所需 JAR 文件的完整列表的屏幕截图 −

大多数 JAR 文件都可以作为 struts 发行版的一部分获得。如果您安装了应用程序服务器(如 glassfish、websphere 或 jboss),则可以从应用程序服务器的 lib 文件夹中获取剩余的大多数 jar 文件。如果没有,您可以单独下载文件 −
Hibernate jar 文件 − Hibernate.org
Struts hibernate 插件 − Struts hibernate 插件
JTA 文件 − JTA 文件
Dom4j 文件 − Dom4j
log4j 文件 − log4j
其余文件,您应该可以从 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 定义了我们的操作类。我们这里有两个操作方法 - 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 接口。当您的操作类处理具体模型类(例如 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 操作与 ModelAware"AddSudentAction"相关联,因此将自动创建一个学生 bean,其中 firstName、lastName 和 marks 的值将自动填充。
在底部,我们浏览学生列表(参见 AddStudentAction.java)。我们遍历列表并在表中显示 first name、last name 和 marks 的值。
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 默认包。然后我们声明两个操作 - addStudent 和 listStudents。addStudent 调用 AddStudentAction 类上的 execute(),然后在成功后调用 listStudents 操作方法。
listStudent 操作方法调用 AddStudentAction 类上的 listStudents() 并使用 student.jsp 作为视图。
现在,右键单击项目名称,然后单击 Export > WAR File 以创建 War 文件。然后将此 WAR 部署到 Tomcat 的 webapps 目录中。最后,启动 Tomcat 服务器并尝试访问 URL http://localhost:8080/HelloWorldStruts2/student.jsp。这将产生以下屏幕 −

在顶部部分,我们获得一个表单来输入新学生记录的值,底部部分列出数据库中的学生。继续添加新的学生记录并按提交。每次单击"提交"时,屏幕都会刷新并显示更新的列表。