目录

Struts2 - 快速指南

Basic MVC Architecture

M称为M odel V iew C ontroller或MVC ,是用于开发Web应用程序的软件设计模式。 模型视图控制器模式由以下三个部分组成 -

  • Model - 负责维护数据的模式的最低级别。

  • View - 负责向用户显示全部或部分数据。

  • Controller - 控制模型和视图之间交互的软件代码。

MVC很受欢迎,因为它将应用程序逻辑与用户界面层隔离开来,并支持关注点的分离。 Controller在此接收应用程序的所有请求,然后使用Model来准备View所需的任何数据。 然后,View使用Controller准备的数据生成最终的可呈现响应。 MVC抽象可以用图形表示如下。

Struts MVC

该模型

该模型负责管理应用程序的数据。 它响应来自视图的请求,并且还响应来自控制器的指令以更新自身。

风景

它意味着以特定格式呈现数据,由控制器决定呈现数据触发。 它们是基于脚本的模板系统,如JSP,ASP,PHP,并且非常易于与AJAX技术集成。

控制器

控制器负责响应用户输入并对数据模型对象执行交互。 控制器接收输入,验证输入,然后执行修改数据模型状态的业务操作。

Struts2是一个基于MVC的框架。 在接下来的章节中,让我们看看如何在Struts2中使用MVC方法。

Struts 2 - Overview

Struts2是一个基于MVC设计模式的流行且成熟的Web应用程序框架。 Struts2不仅仅是Struts 1的新版本,而且完全重写了Struts架构。

Webwork框架最初以Struts框架为基础,其目标是提供基于Struts的增强和改进框架,使开发人员更容易进行Web开发。

过了一会儿,Webwork框架和Struts社区联手创建了着名的Struts2框架。

Struts 2框架功能

以下是一些可能迫使您考虑Struts2的强大功能 -

  • POJO Forms and POJO Actions - Struts2已经废除了Action Forms,它是Struts框架不可或缺的一部分。 使用Struts2,您可以使用任何POJO来接收表单输入。 同样,您现在可以将任何POJO视为Action类。

  • Tag Support - Struts2改进了表单标记和新标记,允许开发人员编写更少的代码。

  • AJAX Support --Struts2已经认识到Web2.0技术的接管,并通过创建AJAX标签将AJAX支持集成到产品中,这个功能非常类似于标准的Struts2标签。

  • Easy Integration - 通过Struts2提供的各种集成,现在可以更轻松地与Spring,Tiles和SiteMesh等其他框架集成。

  • Template Support - 支持使用模板生成视图。

  • Plugin Support - 可以通过使用插件来增强和增强核心Struts2行为。 Struts2有许多插件可供使用。

  • Profiling - Struts2提供集成的分析功能来调试和分析应用程序。 除此之外,Struts还在内置调试工具的帮助下提供集成调试。

  • Easy to Modify Tags - 可以使用Freemarker模板调整Struts2中的标记标记。 这不需要JSP或Java知识。 基本的HTML,XML和CSS知识足以修改标签。

  • Promote Less configuration - Struts2借助于为各种设置使用默认值来促进更少的配置。 除非它与Struts2设置的默认设置不同,否则您不必配置某些内容。

  • View Technologies - Struts2非常支持多种视图选项(JSP,Freemarker,Velocity和XSLT)

上面列出的是Struts 2的十大功能,使其成为企业就绪框架。

Struts 2的缺点

虽然Struts 2附带了一系列强大的功能,但是当前版本存在一些局限性 - Struts 2需要进一步改进。 列出的是一些要点 -

  • Bigger Learning Curve - 要在Struts中使用MVC,您必须熟悉标准的JSP,Servlet API和一个庞大而精细的框架。

  • Poor Documentation - 与标准的servlet和JSP API相比,Struts拥有更少的在线资源,许多首次使用的用户发现在线Apache文档令人困惑且组织不良。

  • Less Transparent - 使用Struts应用程序,幕后工作比普通的基于Java的Web应用程序要多得多,因此很难理解框架。

最后需要注意的是,一个好的框架应该提供许多不同类型的应用程序可以使用它的通用行为。

Struts 2是最好的Web框架之一,并且高度用于Rich Internet Applications(RIA)的开发。

Struts 2 - Environment Setup

我们的第一个任务是运行最小的Struts 2应用程序。 本章将指导您如何准备开发环境以开始使用Struts 2。

我假设你已经在你的机器上安装了JDK(5 +),Tomcat和Eclipse。 如果您没有安装这些组件,请按照快速通道上的给定步骤进行操作 -

第1步 - 安装Java开发工具包(JDK)

您可以从Oracle的Java站点下载最新版本的SDK - Java SE Downloads 。 您将找到有关在下载文件中安装JDK的说明,请按照给出的说明安装和配置设置。 最后,设置PATH和JAVA_HOME环境变量以引用包含java和javac的目录,通常分别是java_install_dir/bin和java_install_dir。

如果您运行的是Windows并在C:\_ jdk1.5.0_20中安装了SDK,则应在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

或者,如果您使用Borland JBuilder,Eclipse,IntelliJ IDEA或Sun ONE Studio等集成开发环境(IDE),请编译并运行一个简单程序以确认IDE知道您在何处安装Java,否则请按照给出IDE的文档。

第2步 - 设置Apache Tomcat

您可以从https://tomcat.apache.org/下载最新版本的Tomcat。 下载安装后,将二进制分发包解压到一个方便的位置。

例如,在Windows上的C:\apache-tomcat-6.0.33或Linux/Unix上的/usr/local/apachetomcat-6.0.33中,创建指向这些位置的CATALINA_HOME环境变量。

您可以通过在Windows机器上执行以下命令来启动Tomcat,或者您只需双击startup.bat即可

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

可以通过在Unix(Solaris,Linux等)机器上执行以下命令来启动Tomcat -

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

成功启动后,Tomcat附带的默认Web应用程序将通过访问http://localhost:8080/ 。 如果一切正常,那么它应该显示以下结果 -

Tomcat主页

有关配置和运行Tomcat的更多信息,请参阅此处包含的文档以及Tomcat网站: https://tomcat.apache.org/ : https://tomcat.apache.org/

可以通过在Windows机器上执行以下命令来停止Tomcat -

%CATALINA_HOME%\bin\shutdown
or
C:\apache-tomcat-5.5.29\bin\shutdown

可以通过在Unix(Solaris,Linux等)机器上执行以下命令来停止Tomcat -

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

第3步 - 安装Eclipse(IDE)

本教程中的所有示例都是使用Eclipse IDE编写的。 我建议您在机器中安装最新版本的Eclipse。

安装Eclipse从https://www.eclipse.org/downloads/下载最新的Eclipse二进制文件。 下载安装后,将二进制分发包解压到一个方便的位置。

例如,在Windows上的C:\eclipse或Linux/Unix上的/ usr/local/eclipse中,最后适当地设置PATH变量。 可以通过在Windows机器上执行以下命令来启动Eclipse,或者只需双击eclipse.exe即可

%C:\eclipse\eclipse.exe

可以通过在Unix(Solaris,Linux等)机器上执行以下命令来启动Eclipse -

$/usr/local/eclipse/eclipse

成功启动后,如果一切正常,它应显示以下结果 -

Eclipse主页

第4步 - 设置Struts2库

现在如果一切正常,那么你可以继续设置你的Struts2 framemwork。 以下是在您的计算机上下载和安装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中为您提供目录结构,如下所示。

Sturts目录

第二步是在任何位置解压缩zip文件,我在Windows 7机器上的c:\文件夹中下载并解压缩了struts-2.2.3-all.zip ,这样我就可以将所有jar文件放到C:\struts-2.2.3\lib 。 确保正确设置CLASSPATH变量,否则在运行应用程序时将遇到问题。

Struts 2 - Architecture

从高层次来看,Struts2是一个pull-MVC(或MVC2)框架。 Struts2中的Model-ViewController模式使用以下五个核心组件实现 -

  • Actions
  • Interceptors
  • 价值堆栈/ OGNL
  • Results/Result types
  • 查看技术

Struts 2与传统的MVC框架略有不同,传统的MVC框架虽然存在一些重叠,但它们扮演的是模型的角色而不是控制器。

Struts 2架构

上图描绘了Struts2高级架构的M odel, V iew和C ontroller。 控制器使用Struts2调度servlet过滤器和拦截器实现,该模型使用操作实现,视图是结果类型和结果的组合。 值栈和OGNL提供了通用线程,链接和启用其他组件之间的集成。

除上述组件外,还有很多与配置相关的信息。 Web应用程序的配置,以及操作,拦截器,结果等的配置。

这是Struts 2 MVC模式的架构概述。 我们将在后续章节中更详细地介绍每个组件。

请求生命周期

基于上图,您可以了解Struts 2用户请求生命周期的工作流程,如下所示 -

  • 用户向服务器发送请求以请求某些资源(即页面)。

  • Filter Dispatcher查看请求,然后确定相应的Action。

  • 配置的拦截器功能适用于验证,文件上传等。

  • 根据请求的操作执行所选操作。

  • 同样,如果需要,应用配置的拦截器进行任何后处理。

  • 最后,结果由视图准备并将结果返回给用户。

Struts 2 - Hello World Example

正如您已经从Struts 2体系结构中学到的,当您在Struts 2 Web应用程序中单击超链接或提交HTML表单时,Controller会收集输入,并将其发送到名为Actions的Java类。 执行Action后,结果将选择一个资源来呈现响应。 资源通常是JSP,但它也可以是PDF文件,Excel电子表格或Java小程序窗口。

假设您已经构建了开发环境。 现在,让我们继续构建我们的第一个Hello World Struts2项目。 此项目的目的是构建一个Web应用程序,该应用程序收集用户的名称并显示“Hello World”,后跟用户名。

我们必须为任何Struts 2项目创建以下四个组件 -

Sr.No 组件和描述
1

Action

创建一个包含完整业务逻辑的操作类,并控制用户,模型和视图之间的交互。

2

Interceptors

如果需要,创建拦截器,或使用现有的拦截器。 这是Controller的一部分。

3

View

创建JSP以与用户交互以获取输入并呈现最终消息。

4

Configuration Files

创建配置文件以耦合Action,View和Controllers。 这些文件是struts.xml,web.xml,struts.properties。

我将使用Eclipse IDE,以便在Dynamic Web Project下创建所有必需的组件。 现在让我们开始创建动态Web项目。

创建动态Web项目

启动Eclipse,然后使用File 》 New 》 Dynamic Web Project并输入项目名称HelloWorldStruts2并设置其余选项,如下面的屏幕所示:

Hello World Sturts1

在下一个屏幕中选择所有默认选项,最后选中Generate Web.xml deployment descriptor选项。 这将在Eclipse中为您创建一个动态Web项目。 现在使用Windows 》 Show View 》 Project Explorer ,您将看到项目窗口如下 -

Hello World Sturts2

现在将以下文件从struts 2 lib文件夹C:\struts-2.2.3\lib复制到我们项目的WEB-INF\lib文件夹中。 为此,您只需将以下所有文件拖放到WEB-INF\lib文件夹中即可。

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

创建Action类 (Create Action Class)

Action类是Struts 2应用程序的关键,我们在action类中实现了大部分业务逻辑。 因此,让我们在Java Resources 》 src下创建一个java文件HelloWorldAction.java,其包名为com.iowiki.struts2 ,其内容如下所示。

当用户单击URL时,Action类会响应用户操作。 执行一个或多个Action类的方法,并返回String结果。 根据结果​​的值,呈现特定的JSP页面。

package com.iowiki.struts2;
public class HelloWorldAction {
   private String name;
   public String execute() throws Exception {
      return "success";
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

这是一个非常简单的类,有一个名为“name”的属性。 我们有“name”属性的标准getter和setter方法以及返回字符串“success”的execute方法。

Struts 2框架将创建HelloWorldAction类的对象,并调用已执行的方法以响应用户的操作。 您将业务逻辑放在此方法中,最终返回String常量。 换句话说,对于每个URL,您必须实现一个操作类,并且可以直接使用该类名作为操作名称,也可以使用struts.xml文件映射到其他名称,如下所示。

创建一个视图 (Create a View)

我们需要一个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,用户可以单击该URL以告知Struts 2框架调用HelloWorldAction类的已定义方法并呈现HelloWorld.jsp视图。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <title>Hello World</title>
   </head>
   <body>
      <h1>Hello World From Struts2</h1>
      <form action = "hello">
         <label for = "name">Please enter your name</label><br/>
         <input type = "text" name = "name"/>
         <input type = "submit" value = "Say Hello"/>
      </form>
   </body>
</html>

上面的视图文件中定义的hello操作将使用struts.xml文件映射到HelloWorldAction类及其execute方法。 当用户单击Submit按钮时,它将使Struts 2框架运行HelloWorldAction类中定义的execute方法,并根据方法的返回值,选择适当的视图并将其呈现为响应。

配置文件 (Configuration Files)

我们需要一个映射来将URL,HelloWorldAction类(Model)和HelloWorld.jsp(视图)绑定在一起。 映射告诉Struts 2框架哪个类将响应用户的操作(URL),该类的哪个方法将被执行,以及基于该方法返回的String结果呈现什么视图。

那么让我们创建一个名为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.iowiki.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
      </action>
   </package>
</struts>

关于上述配置文件需要理解的几个词。 在这里,我们将常量struts.devMode设置为true ,因为我们在开发环境中工作,我们需要查看一些有用的日志消息。 然后,我们定义一个名为helloworld的包。

如果要将操作组合在一起,创建包非常有用。 在我们的示例中,我们将操作命名为“hello”,它对应于URL /hello.action ,并由HelloWorldAction.class备份。 HelloWorldAction.classexecute方法是在调用URL /hello.action时运行的方法。 如果execute方法的结果返回“success”,那么我们将用户带到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)

启用详细日志

通过在WEB-INF/classes文件夹下创建logging.properties文件,可以在使用Struts 2时启用完整的日志记录功能。 在属性文件中保留以下两行 -

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

默认的logging.properties指定用于将日志记录路由到stdout以及FileHandler的ConsoleHandler。 可以使用SEVERE,WARNING,INFO,CONFIG,FINE,FINER,FINEST或ALL设置处理程序的日志级别阈值。

而已。 我们准备使用Struts 2框架运行Hello World应用程序。

执行应用程序的过程

右键单击项目名称,然后单击“ Export 》 WAR File以创建War文件。

然后在Tomcat的webapps目录中部署此WAR。

最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将为您提供以下屏幕 -

Hello World Struts4

输入值“Struts2”并提交页面。 你应该看到下一页

Hello World Struts5

请注意,您可以将index定义为struts.xml文件中的操作,在这种情况下,您可以将索引页调用为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.iowiki.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
      </action>
   </package>
</struts>

Struts 2 - Configuration Files

本章将向您介绍Struts 2应用程序所需的基本配置。 在这里,我们将看到可以使用web.xml, struts.xml, strutsconfig.xmlstruts.properties等少数重要配置文件进行配置的内容。

老实说,您可以通过使用web.xmlstruts.xml配置文件开始工作(正如您在前一章中已经见过的那样,我们的示例使用这两个文件工作)。 但是,据您所知,我们还会解释其他文件。

web.xml文件

web.xml配置文件是J2EE配置文件,用于确定servlet容器如何处理HTTP请求的元素。 它不是严格意义上的Struts2配置文件,但它是一个需要配置Struts2才能工作的文件。

如前所述,此文件为任何Web应用程序提供入口点。 Struts2应用程序的入口点将是部署描述符(web.xml)中定义的过滤器。 因此,我们将在web.xml中定义FilterDispatcher类的条目。 需要在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/*.action ,这意味着struts过滤器将解析所有URL。 当我们通过Annotations章节时,我们将介绍这一点。

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.iowiki.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
      </action>
      <-- more actions can be listed here -->
   </package>
   <-- more packages can be listed here -->
</struts>

首先要注意的是DOCTYPE 。 所有struts配置文件都需要具有正确的doctype,如我们的小例子所示。 “struts”是根标记元素,我们使用“package”标记声明不同的包。 这里“包”允许配置的分离和模块化。 当您拥有一个大型项目并将项目划分为不同的模块时,这非常有用。

例如,如果您的项目有三个域 - business_application,customer_application和staff_application,那么您可以创建三个包并在相应的包中存储相关的操作。

包标签具有以下属性 -

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就会访问它。

结果确定执行操作后返回浏览器的内容。 从操作返回的字符串应该是结果的名称。 结果按上述操作配置,或作为“全局”结果配置,可用于包中的每个操作。 结果具有可选的nametype属性。 默认名称值为“success”。

Struts.xml文件随着时间的推移会变得越来越大,因此打包它是一种模块化的方法,但是Struts提供了另一种模块化struts.xml文件的方法。 您可以将文件拆分为多个xml文件,并以下列方式导入它们。

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

我们未涉及的其他配置文件是struts-default.xml。 此文件包含Struts的标准配置设置,您不必为99.99%的项目触摸这些设置。 出于这个原因,我们不会对此文件进行太多细节处理。 如果您有兴趣,请查看struts2-core-2.2.3.jar文件中的default.properties文件。

Struts-config.xml文件

struts-config.xml配置文件是Web客户端中View和Model组件之间的链接,但您不必为99.99%的项目触摸这些设置。

配置文件基本上包含以下主要元素 -

Sr.No 拦截器和描述
1

struts-config

这是配置文件的根节点。

2

form-beans

这是将ActionForm子类映射到名称的位置。 在整个strutsconfig.xml文件的其余部分,甚至在JSP页面上,都使用此名称作为ActionForm的别名。

3

global forwards

此部分将您的webapp上的页面映射到名称。 您可以使用此名称来引用实际页面。 这样可以避免在网页上对网址进行硬编码。

4

action-mappings

这是您声明表单处理程序的位置,它们也称为操作映射。

5

controller

本节配置Struts内部,在实际情况中很少使用。

6

plug-in

本节告诉Struts在哪里可以找到属性文件,其中包含提示和错误消息

以下是struts-config.xml文件示例 -

<?xml version = "1.0" Encoding = "ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
   "http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">
<struts-config>
   <!-- ========== Form Bean Definitions ============ -->
   <form-beans>
      <form-bean name = "login" type = "test.struts.LoginForm" />
   </form-beans>
   <!-- ========== Global Forward Definitions ========= -->
   <global-forwards>
   </global-forwards>
   <!-- ========== Action Mapping Definitions ======== -->
   <action-mappings>
      <action
         path = "/login"
         type = "test.struts.LoginAction" >
         <forward name = "valid" path = "/jsp/MainMenu.jsp" />
         <forward name = "invalid" path = "/jsp/LoginView.jsp" />
      </action>
   </action-mappings>
   <!-- ========== Controller Definitions ======== -->
   <controller contentType = "text/html;charset = UTF-8"
      debug = "3" maxFileSize = "1.618M" locale = "true" nocache = "true"/>
</struts-config>

有关struts-config.xml文件的更多详细信息,请查看struts文档。

Struts.properties文件

此配置文件提供了一种更改框架的默认行为的机制。 实际上, struts.properties配置文件中包含的所有属性也可以使用init-paramweb.xml配置,以及使用struts.xml配置文件中的constant标记。 但是,如果您希望将事物分开并且更具特定的struts,那么您可以在WEB-INF/classes文件夹下创建此文件。

此文件中配置的值将覆盖default.properties中配置的默认值,该默认值包含在struts2-core-xyzjar分发中。 您可以考虑使用struts.properties文件更改一些属性 -

### When set to true, Struts will act much more friendly for developers
struts.devMode = true
### Enables reloading of internationalization files
struts.i18n.reload = true
### Enables reloading of XML configuration files
struts.configuration.xml.reload = true
### Sets the port that the server is run on
struts.url.http.port = 8080

这里任何以hash (#)开头的行都将被假定为注释,它将被Struts 2忽略。

Struts 2 - Actions

Actions是Struts2框架的核心,因为它们适用于任何MVC(模型视图控制器)框架。 每个URL都映射到一个特定的操作,该操作提供了处理来自用户的请求所必需的处理逻辑。

但该行动还有两个重要的能力。 首先,无论是JSP还是其他类型的结果,该操作在从请求到视图的数据传输中起着重要作用。 其次,该操作必须帮助框架确定哪个结果应该呈现将在请求的响应中返回的视图。

Create Action

Struts2操作的唯一要求是必须有一个noargument方法返回String或Result对象,并且必须是POJO。 如果未指定无参数方法,则默认行为是使用execute()方法。

(可选)您可以扩展ActionSupport类,该类实现六个接口,包括Action接口。 Action界面如下 -

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

让我们看一下Hello World示例中的action方法 -

package com.iowiki.struts2;
public class HelloWorldAction {
   private String name;
   public String execute() throws Exception {
      return "success";
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

为了说明action方法控制视图的点,让我们对execute方法进行以下更改,并按如下方式扩展ActionSupport类 -

package com.iowiki.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,所以我们可以使用String常量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.iowiki.struts2.HelloWorldAction"
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
         <result name = "error">/AccessDenied.jsp</result>
      </action>
   </package>
</struts>

创建一个视图 (Create a View)

让我们在你的eclipse项目的WebContent文件夹中创建下面的jsp文件HelloWorld.jsp 。 为此,右键单击项目资源管理器中的WebContent文件夹,然后选择“ New 》JSP File 。 如果返回结果为SUCCESS,则会调用此文件,这是Action接口中定义的String常量“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,则等于String常量“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文件不需要更改,所以让我们使用我们在Examples章节中创建的web.xml。 现在,我们已准备好使用Struts 2框架运行Hello World应用程序。

执行应用程序

右键单击项目名称,然后单击“ Export 》 WAR文件以创建War文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将为您提供以下屏幕 -

Hello World Struts4

让我们输入一个单词“SECRET”,您应该看到以下页面 -

helloworldstruts51

现在输入“SECRET”以外的任何单词,您应该看到以下页面 -

helloworldstruts6

创建多个操作

您将经常定义多个操作来处​​理不同的请求并向用户提供不同的URL,因此您将定义下面定义的不同类 -

package com.iowiki.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.iowiki.struts2.HelloWorld" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
         <result name = "error">/AccessDenied.jsp</result>
      </action>
      <action name = "something" 
         class = "com.iowiki.struts2.SomeOtherClass" 
         method = "execute">
         <result name = "success">/Something.jsp</result>
         <result name = "error">/AccessDenied.jsp</result>
      </action>
   </package>
</struts>

正如您在上面的假设示例中所看到的,操作结果SUCCESSERROR’s是重复的。

要解决此问题,建议您创建一个包含结果结果的类。

Struts 2 - Interceptors

拦截器在概念上与servlet过滤器或JDKs Proxy类相同。 拦截器允许横切功能与动作和框架分开实现。 您可以使用拦截器实现以下目标 -

  • 在调用操作之前提供预处理逻辑。

  • 在调用操作后提供后处理逻辑。

  • 捕获异常以便可以执行备用处理。

Struts2框架中提供的许多功能都是使用拦截器实现的;

Examples包括异常处理,文件上传,生命周期回调等。事实上,由于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.iowiki.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文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将产生以下屏幕 -

Hello World Struts 4

现在在给定的文本框中输入任何单词,然后单击Say Hello按钮以执行定义的操作。 现在,如果您要检查生成的日志,您将找到以下文本 -

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

由于timer拦截器正在生成底线,因此告知动作总共需要执行109ms。

创建自定义拦截器

在应用程序中使用自定义拦截器是提供横切应用程序功能的一种优雅方式。 创建自定义拦截器很容易; 需要扩展的接口是以下Interceptor接口 -

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

顾名思义,init()方法提供了一种初始化拦截器的方法,而destroy()方法为拦截器清理提供了一种工具。 与动作不同,拦截器可以跨请求重用,并且需要线程安全,尤其是intercept()方法。

ActionInvocation对象提供对运行时环境的访问。 它允许访问操作本身和方法来调用操作并确定是否已经调用了操作。

如果您不需要初始化或清理代码,则可以扩展AbstractInterceptor类。 这提供了init()和destroy()方法的默认nooperation实现。

创建拦截器类

让我们在Java Resources 》 src文件夹中创建以下MyInterceptor.java -

package com.iowiki.struts2;
import java.util.*;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor extends AbstractInterceptor {
   public String intercept(ActionInvocation invocation)throws Exception {
      /* let us do some pre-processing */
      String output = "Pre-Processing"; 
      System.out.println(output);
      /* let us call action or next interceptor */
      String result = invocation.invoke();
      /* let us do some post-processing */
      output = "Post-Processing"; 
      System.out.println(output);
      return result;
   }
}

正如您所注意到的,实际操作将通过invocation.invoke()调用使用拦截器执行。 因此,您可以根据您的要求进行一些预处理和一些后处理。

框架本身通过首次调用ActionInvocation对象的invoke()来启动该过程。 每次invoke() ,ActionInvocation都会查询其状态并执行下一个拦截器。 当调用了所有已配置的拦截器时,invoke()方法将导致执行操作本身。

下图通过请求流程显示了相同的概念 -

ActionInvocation

创建Action类 (Create Action Class)

让我们在Java Resources 》 src下创建一个java文件HelloWorldAction.java,其包名为com.iowiki.struts2 ,其内容如下所示。

package com.iowiki.struts2;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorldAction extends ActionSupport {
   private String name;
   public String execute() throws Exception {
      System.out.println("Inside action....");
      return "success";
   }  
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

这是我们在前面的例子中看到的同一个类。 我们有“name”属性的标准getter和setter方法以及返回字符串“success”的execute方法。

创建一个视图 (Create a View)

让我们在你的eclipse项目的WebContent文件夹中创建下面的jsp文件HelloWorld.jsp

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>
<html>
   <head>
      <title>Hello World</title>
   </head>
   <body>
      Hello World, <s:property value = "name"/>
   </body>
</html>

创建主页面

我们还需要在WebContent文件夹中创建index.jsp 。 此文件将用作初始操作URL,用户可以单击该URL以告知Struts 2框架调用HelloWorldAction类的已定义方法并呈现HelloWorld.jsp视图。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <title>Hello World</title>
   </head>
   <body>
      <h1>Hello World From Struts2</h1>
      <form action = "hello">
         <label for = "name">Please enter your name</label><br/>
         <input type = "text" name = "name"/>
         <input type = "submit" value = "Say Hello"/>
      </form>
   </body>
</html>

上面的视图文件中定义的hello操作将使用struts.xml文件映射到HelloWorldAction类及其execute方法。

配置文件 (Configuration Files)

现在,我们需要注册我们的拦截器,然后调用它,因为我们在前面的例子中调用了默认拦截器。 要注册新定义的拦截器, ... interceptors>标记直接放在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.iowiki.struts2.MyInterceptor" />
      </interceptors>
      <action name = "hello" 
         class = "com.iowiki.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文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将产生以下屏幕 -

Hello World Struts 4

现在在给定的文本框中输入任何单词,然后单击Say Hello按钮以执行定义的操作。 现在,如果您要检查生成的日志,您会在底部找到以下文本 -

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

堆叠多个拦截器

可以想象,必须为每个动作配置多个拦截器很快就会变得非常难以管理。 因此,拦截器使用拦截器堆栈进行管理。 这是一个直接来自strutsdefault.xml文件的示例 -

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

上面的赌注叫做basicStack ,可以在你的配置中使用,如下所示。 此配置节点位于“package ... /”节点下。 每个“interceptor-ref ... /”标记引用在当前拦截器堆栈之前配置的拦截器或拦截器堆栈。 因此,在配置初始拦截器和拦截器堆栈时,确保名称在所有拦截器和拦截器堆栈配置中是唯一的非常重要。

我们已经看到了如何将拦截器应用于动作,应用拦截器堆栈也没有什么不同。 事实上,我们使用完全相同的标签 -

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

上述“basicStack”注册将通过hello动作注册所有六个拦截器的完整股份。 应该注意,拦截器按照已配置的顺序执行。 例如,在上面的例子中,将首先执行异常,第二个将是servlet-config,依此类推。

Struts 2 - Results & Result Types

如前所述, 《results》标签在Struts2 MVC框架中扮演view的角色。 该操作负责执行业务逻辑。 执行业务逻辑后的下一步是使用《results》标记显示视图。

通常会在结果中附加一些导航规则。 例如,如果操作方法是对用户进行身份验证,则有三种可能的结果。

  • 成功登录
  • 登录失败 - 用户名或密码不正确
  • 帐户被锁定

在这种情况下,操作方法将配置三个可能的结果字符串和三个不同的视图来呈现结果。 我们已经在前面的例子中看到了这一点。

但是,Struts2并没有将您与使用JSP作为视图技术联系在一起。 毕竟,MVC范例的整个目的是保持层分离和高度可配置。 例如,对于Web2.0客户端,您可能希望返回XML或JSON作为输出。 在这种情况下,您可以为XML或JSON创建新的结果类型并实现此目的。

Struts附带了许多预定义的result types以及我们已经看到的任何默认结果类型dispatcher ,它用于调度到JSP页面。 Struts允许您使用其他标记语言来显示结果,流行的选择包括Velocity, Freemaker, XSLTTiles

调度程序结果类型

dispatcher结果类型是默认类型,如果未指定其他结果类型,则使用该类型。 它用于转发到服务器上的servlet,JSP,HTML页面等。 它使用RequestDispatcher.forward()方法。

我们在前面的示例中看到了“简写”版本,其中我们提供了一个JSP路径作为结果标记的主体。

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

我们还可以使用元素中的标记指定JSP文件,如下所示 -

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

我们还可以提供一个parse参数,默认情况下为true。 parse参数确定是否将为OGNL表达式解析location参数。

FreeMaker结果类型

在这个例子中,我们将看到如何使用FreeMaker作为视图技术。 Freemaker是一种流行的模板引擎,用于使用预定义模板生成输出。 现在让我们创建一个名为hello.fm模板文件, hello.fm包含以下内容 -

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.iowiki.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文件。

然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将产生以下屏幕。

Hello World Struts 4

输入值“Struts2”并提交页面。 你应该看到下一页。

Hello World Struts 5

如您所见,这与JSP视图完全相同,只是我们不依赖于使用JSP作为视图技术。 我们在这个例子中使用过Freemaker。

重定向结果类型

redirect结果类型调用标准的response.sendRedirect()方法,使浏览器创建对给定位置的新请求。

我们可以在元素的主体中提供位置,也可以在元素中提供位置。 重定向还支持parse参数。 这是使用XML配置的示例 -

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

因此,只需修改struts.xml文件以定义上面提到的重定向类型,并创建一个新文件NewWorld.jpg,只要hello操作返回成功,您将被重定向。 您可以查看Struts 2 Redirect Action示例以便更好地理解。

Struts 2 - Value Stack/OGNL

价值堆栈

值堆栈是一组多个对象,它们按提供的顺序保存以下对象 -

Sr.No 对象和描述
1

Temporary Objects

在执行页面期间创建了各种临时对象。 例如,在JSP标记中循环的集合的当前迭代值。

2

The Model Object

如果在struts应用程序中使用模型对象,则当前模型对象将放置在值堆栈上的操作之前。

3

The Action Object

这将是正在执行的当前操作对象。

4

Named Objects

这些对象包括#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

Object-Graph Navigation Language (OGNL)是一种功能强大的表达式语言,用于引用和操作ValueStack上的数据。 OGNL还有助于数据传输和类型转换。

OGNL与JSP表达式语言非常相似。 OGNL基于在上下文中具有根或默认对象的想法。 可以使用标记符号来引用默认或根对象的属性,标记符号是井号。

如前所述,OGNL基于上下文,Struts构建一个ActionContext映射以与OGNL一起使用。 ActionContext映射包含以下内容 -

  • Application - 应用程序范围变量

  • Session - 会话范围变量

  • Root/value stack - 所有操作变量都存储在此处

  • Request - 请求范围变量

  • Parameters - 请求参数

  • Atributes - 存储在页面,请求,会话和应用程序范围中的属性

重要的是要理解Action对象始终在值栈中可用。 因此,如果您的Action对象具有属性“x”“y”则可以随时使用。

ActionContext中的对象使用井号符号引用,但是,可以直接引用值栈中的对象。

例如,如果employee是action类的属性,那么可以引用它如下 -

<s:property value = "name"/>

代替

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

如果您在会话中有一个名为“login”的属性,您可以按如下方式检索它 -

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

OGNL还支持处理集合 - 即Map,List和Set。 例如,要显示颜色下拉列表,您可以 -

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

OGNL表达式巧妙地将“红色”,“黄色”,“绿色”解释为颜色并基于此构建列表。

当我们研究不同的标签时,OGNL表达式将在下一章中广泛使用。 因此,不要孤立地查看它们,让我们使用Form Tags/Control Tags/Data Tags和Ajax Tags部分中的一些示例来查看它。

ValueStack/OGNL Example

创建动作

让我们考虑以下动作类,我们访问valueStack,然后在我们的视图中设置几个我们将使用OGNL访问的键,即JSP页面。

package com.iowiki.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在执行时会将您的操作添加到valueStack的顶部。 因此,将内容放在Value Stack上的常用方法是将值的getter/setter添加到Action类,然后使用标记来访问值。 但是我告诉你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.iowiki.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>

右键单击项目名称,然后单击“ Export 》 WAR File以创建War文件。 然后在Tomcat的webapps目录中部署此WAR。

最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将产生以下屏幕

Hello World Struts 4

现在在给定的文本框中输入任何单词,然后单击“Say Hello”按钮以执行定义的操作。 现在,如果您要检查生成的日志,您会在底部找到以下文本 -

Size of the valueStack: 3

这将显示以下屏幕,该屏幕将显示您将输入的任何值以及我们在ValueStack上放置的key1和key2的值。

Struts 2 - File Uploads

Struts 2框架使用“基于表单的HTML文件上载”为处理文件上载提供内置支持。 上传文件时,它通常会存储在临时目录中,并且应由Action类处理或移动它们到永久目录,以确保数据不会丢失。

Note - 服务器可能具有安全策略,禁止您写入临时目录以外的目录以及属于Web应用程序的目录。

可以通过名为FileUpload拦截器的预定义拦截器在Struts中上传文件,该拦截器可通过org.apache.struts2.interceptor.FileUploadInterceptor类获得,并作为defaultStack一部分包含在内。 仍然可以在struts.xml中使用它来设置各种参数,我们将在下面看到。

创建视图文件

让我们从创建浏览和上传所选文件所需的视图开始。 因此,让我们使用纯HTML上传表单创建一个index.jsp ,允许用户上传文件 -

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <title>File Upload</title>
   </head>
   <body>
      <form action = "upload" method = "post" enctype = "multipart/form-data">
         <label for = "myFile">Upload your file</label>
         <input type = "file" name = "myFile" />
         <input type = "submit" value = "Upload"/>
      </form>
   </body>
</html>

在上面的例子中有几点值得注意。 首先,表单的enctype设置为multipart/form-data 。 应设置此选项,以便文件上载拦截器成功处理文件上载。 下一点需要注意的是表单的操作方法upload和文件上载字段的名称 - 即myFile 。 我们需要此信息来创建操作方法和struts配置。

接下来,让我们创建一个简单的jsp文件success.jsp ,以便在success.jsp时显示文件上传的结果。

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>
<html>
   <head>
      <title>File Upload Success</title>
   </head>
   <body>
      You have successfully uploaded <s:property value = "myFileFileName"/>
   </body>
</html>

以下将是结果文件error.jsp ,以防上传文件时出现一些错误 -

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>
<html>
   <head>
      <title>File Upload Error</title>
   </head>
   <body>
      There has been an error in uploading the file.
   </body>
</html>

创建Action类 (Create Action Class)

接下来,让我们创建一个名为uploadFile.java的Java类,它将负责上传文件并将该文件存储在安全的位置 -

package com.iowiki.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拦截器为您提供三个参数。 它们以下列模式命名 -

  • [your file name parameter] - 这是用户上传的实际文件。 在这个例子中它将是“myFile”

  • [your file name parameter]ContentType - 这是上载文件的内容类型。 在这个例子中它将是“myFileContentType”

  • [your file name parameter]FileName - 这是上载文件的名称。 在这个例子中它将是“myFileFileName”

由于Struts拦截器,我们可以使用这三个参数。 我们所要做的就是在Action类中使用正确的名称创建三个参数,并自动为这些变量自动连接。 所以,在上面的例子中,我们有三个参数和一个动作方法,如果一切正常,它只返回“成功”,否则返回“错误”。

配置文件 (Configuration Files)

以下是控制文件上载过程的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.iowiki.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.iowiki.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>

现在右键单击项目名称,然后单击“ Export 》 WAR File以创建War文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/upload.jsp 。 这将产生以下屏幕 -

Hello World Struts 7

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

Hello World Struts 8

请注意,FileUpload Interceptor会自动删除上载的文件,因此您必须在删除之前在某个位置以编程方式保存上载的文件。

错误消息

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 - Database Access

本章将教您如何使用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文件夹中。 完成此操作后,我们现在可以创建动作类了。

Create Action

操作类具有与数据库表中的列对应的属性。 我们将user, passwordname作为String属性。 在action方法中,我们使用user和password参数来检查用户是否存在,如果是,我们在下一个屏幕中显示用户名。

如果用户输入了错误信息,我们会再次将其发送到登录屏幕。

以下是LoginAction.java文件的内容 -

package com.iowiki.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>

创建视图 (Create Views)

现在让我们创建success.jsp文件,该文件将在case操作返回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从操作返回ERROR,则以下将是视图文件error.jsp

<%@ page contentType = "text/html; charset = UTF-8" %>
<%@ taglib prefix = "s" uri = "/struts-tags" %>
<html>
   <head>
      <title>Invalid User Name or Password</title>
   </head>
   <body>
      Wrong user name or password provided.
   </body>
</html>

配置文件 (Configuration Files)

最后,让我们使用struts.xml配置文件将所有内容放在一起,如下所示 -

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
      <action name = "loginaction" 
         class = "com.iowiki.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文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将产生以下屏幕 -

Hello World Struts 9

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

Hello World Struts 10

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

Hello World Struts 11

Struts 2 - Sending Email

本章介绍如何使用Struts 2应用程序发送电子邮件。

在本练习中,您需要从JavaMail API 1.4.4下载并安装mail.jar,并将mail.jar文件放在WEB-INF\lib文件夹中,然后继续执行创建操作,查看和配置的标准步骤文件。

Create Action

下一步是创建一个负责发送电子邮件的Action方法。 让我们创建一个名为Emailer.java的新类, Emailer.java包含以下内容。

package com.iowiki.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 - 电子邮件的Subject

  • 正文 - 实际的电子邮件消息

我们没有考虑对上述字段进行任何验证,验证将在下一章中添加。 现在让我们看一下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>

创建视图 (Create Views)

我们将使用JSP文件success.jsp ,它将在case操作返回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从操作返回ERROR,则以下将是视图文件error.jsp

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <title>Email Error</title>
   </head>
   <body>
      There is a problem sending your email to <s:property value = "to"/>.
   </body>
</html>

配置文件 (Configuration Files)

现在让我们使用struts.xml配置文件将所有内容放在一起,如下所示 -

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
      <action name = "emailer" 
         class = "com.iowiki.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文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将产生以下屏幕 -

电子邮件用户输入

输入所需信息,然后单击Send Email按钮。 如果一切顺利,那么您应该看到以下页面。

电邮成功

Struts 2 - Validations Framework

在本章中,我们将深入研究Struts验证框架。 在Struts核心,我们有验证框架,可以帮助应用程序运行规则,以便在执行操作方法之前执行验证。

客户端验证通常使用Javascript实现。 但是,不应该单独依赖客户端验证。 最佳实践建议应在应用程序框架的所有级别引入验证。 现在让我们看看为Struts项目添加验证的两种方法。

在这里,我们将举例说明一个Employee的名字和年龄应该使用一个简单的页面来捕获,我们将把这两个验证放在一起,以确保用户总是输入一个名称和年龄,该名称和年龄应在28到28之间。 65。

让我们从示例的主JSP页面开始。

创建主页面

让我们编写主页JSP文件index.jsp ,它将用于收集上面提到的Employee相关信息。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <title>Employee Form</title>
   </head>
   <body>
      <s:form action = "empinfo" method = "post">
         <s:textfield name = "name" label = "Name" size = "20" />
         <s:textfield name = "age" label = "Age" size = "20" />
         <s:submit name = "submit" label = "Submit" align="center" />
      </s:form>
   </body>
</html>

index.jsp使用了我们尚未涉及的Struts标记,但我们将在标签相关章节中研究它们。 但是现在,假设s:textfield标签打印输入字段,s:submit打印一个提交按钮。 我们为每个标签使用了label属性,为每个标签创建标签。

创建视图 (Create Views)

我们将使用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>

Create Action

因此,让我们定义一个小动作类Employee ,然后添加一个名为validate()的方法,如下所示在Employee.java文件中。 确保您的操作类扩展了ActionSupport类,否则将不会执行您的validate方法。

package com.iowiki.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之间,如果此条件不符合,我们在验证字段上方添加错误。

配置文件 (Configuration Files)

最后,让我们使用struts.xml配置文件将所有内容放在一起,如下所示 -

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

现在,右键单击项目名称,然后单击“ Export 》 WAR File以创建War文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将产生以下屏幕 -

电子邮件用户输入

现在不要输入任何必要的信息,只需点击Submit按钮即可。 您将看到以下结果 -

错误

输入所需信息,但输入错误的From字段,让我们将名称命名为“test”,将年龄改为30,最后单击Submit按钮。 您将看到以下结果 -

成功

此验证如何工作?

当用户按下提交按钮时,Struts 2将自动执行validate方法,如果方法中列出的任何“if”语句为true,Struts 2将调用其addFieldError方法。 如果添加了任何错误,Struts 2将不会继续调用execute方法。 而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的action节点。

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

基于XML的验证

第二种进行验证的方法是在操作类旁边放置一个xml文件。 基于Struts2 XML的验证提供了更多的验证选项,如电子邮件验证,整数范围验证,表单验证字段,表达式验证,正则表达式验证,必需的验证,必需字符串验证,stringlength验证等。

xml文件需要命名为'[action-class]'-validation.xml 。 因此,在我们的例子中,我们创建了一个名为Employee-validation.xml的文件,其中包含以下内容 -

<!DOCTYPE validators PUBLIC 
   "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
   "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
   <field name = "name">
      <field-validator type = "required">
         <message>
            The name is required.
         </message>
      </field-validator>
   </field>
   <field name = "age">
     <field-validator type = "int">
         <param name = "min">29</param>
         <param name = "max">64</param>
         <message>
            Age must be in between 28 and 65
         </message>
      </field-validator>
   </field>
</validators>

上面的XML文件理想情况下会与类文件一起保存在CLASSPATH中。 让我们按照以下方式使用Employee操作类,而不使用validate()方法 -

package com.iowiki.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默认有更多的验证器。 常用验证器包括Date Validator,Regex验证器和String Length验证器。 检查以下链接以获取更多详细信息Struts - 基于XML的验证器

Struts2 - Localization, internationalization (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 - 这将用于Franch语言环境。

  • global_es.properties - 这将用于西班牙语语言环境。

访问消息

有几种方法可以访问消息资源,包括getText,文本标记,UI标记的键属性和i18n标记。 让我们简要地看一下 -

要显示i18n文本,请在属性标记或任何其他标记(如UI标记)中调用getText ,如下所示 -

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

text tag从默认资源包中检索消息,即struts.properties

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

i18n tag将任意资源包推送到值堆栈。 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来处理Locale并显示具有不同语言的相同index.jsp文件(b)另一个操作是处理提交表单本身。 这两个操作都将返回SUCCESS,但我们将根据返回值采取不同的操作,因为这两个操作的目的不同

采取措施照顾Locale

package com.iowiki.struts2;
import com.opensymphony.xwork2.ActionSupport;
public class Locale extends ActionSupport {
   public String execute() {
       return SUCCESS;
   }
}

提交表格的行动

package com.iowiki.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.iowiki.struts2.Employee"
         method = "execute">
         <result name = "input">/index.jsp</result>
         <result name = "success">/success.jsp</result>
      </action>
      <action name = "locale" 
         class = "com.iowiki.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文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将产生以下屏幕 -

英语输出

现在选择任何一种语言,让我们说我们选择Spanish ,它会显示以下结果 -

西班牙语输出

您也可以尝试使用法语。 最后,让我们在西班牙语语言环境中尝试单击“ Submit按钮,它将显示以下屏幕 -

西班牙成功

恭喜,现在您有了多语言网页,您可以在全球范围内启动您的网站。

Struts 2 - Type Conversion

HTTP请求中的所有内容都被协议视为String 。 这包括数字,布尔,整数,日期,小数等等。 但是,在Struts类中,您可以拥有任何数据类型的属性。

Struts如何为您自动添加属性?

Struts使用各种类型的转换器来完成繁重的工作。

例如,如果Action类中有一个整数属性,Struts会自动将请求参数转换为整数属性,而无需执行任何操作。 默认情况下,Struts附带了许多类型转换器

如果您使用以下列出的任何转换器,那么您无需担心 -

  • Integer, Float, Double, Decimal
  • 日期和日期时间
  • Arrays and Collections
  • Enumerations
  • Boolean
  • BigDecimal

有时,当您使用自己的数据类型时,有必要添加自己的转换器,以使Struts知道如何在显示之前转换这些值。 请考虑以下POJO类Environment.java

package com.iowiki.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.iowiki.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来显示Environment和操作系统信息。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <title>System Details</title>
   </head>
   <body>
      Environment: <s:property value = "environment"/><br/>
      Operating System:<s:property value = "operatingSystem"/>
   </body>
</html>

让我们使用struts.xmlsystem.jspSystemDetails.java类连接在一起。

SystemDetails类有一个简单的execute()方法,它返回字符串“ SUCCESS ”。

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "helloworld" extends = "struts-default">
      <action name = "system" 
            class = "com.iowiki.struts2.SystemDetails" 
            method = "execute">
         <result name = "success">/System.jsp</result>
      </action>
   </package>
</struts>
  • 右键单击项目名称,然后单击“ Export 》 WAR File以创建War文件。

  • 然后在Tomcat的webapps目录中部署此WAR。

  • 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/system.action 。 这将产生以下屏幕 -

系统信息

上面的输出有什么问题? Struts知道如何显示和转换字符串“Windows XP SP3”和其他内置数据类型,但它不知道如何处理Environment类型的属性。 它只是在类上调用toString()方法

要解决此问题,现在让我们为Environment类创建并注册一个简单的TypeConverter

使用以下命令创建一个名为EnvironmentConverter.java的类。

package com.iowiki.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.iowiki.struts2.EnvironmentConverter

在上面的示例中,“environment”是SystemDetails.java类中属性的名称,我们告诉Struts使用EnvironmentConverter进行此属性的转换。

但是,我们不会这样做,相反,我们将全局注册此转换器,以便它可以在整个应用程序中使用。 为此,在WEBINF/classes文件夹中创建一个名为xwork-conversion.properties的属性文件,其中WEBINF/classes以下行

com.iowiki.struts2.Environment = \
   com.iowiki.struts2.EnvironmentConverter

这只是全局注册转换器,因此Struts每次遇到类型为Environment的对象时都可以自动进行转换。 现在,如果您重新编译并重新运行该程序,那么您将获得更好的输出,如下所示 -

系统信息

显然,现在结果会更好,这意味着我们的Struts转换器工作正常。

这是如何创建多个转换器并注册它们以根据您的要求使用。

Struts 2 - Themes & Templates

在开始本章的实际教程之前,让我们看一下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

SIMPLE theme

最小的主题,没有“花里胡哨”。 例如,textfield标记呈现HTML 《input》标记,没有标签,验证,错误报告或任何其他格式或功能。

2

XHTML theme

这是Struts 2使用的默认主题,它提供了简单主题提供的所有基础知识,并添加了一些功能,如HTML的标准双列表布局,每个HTML的标签,验证和错误报告等。

3

CSS_XHTML theme

这个主题提供了简单主题提供的所有基础知识,并添加了一些功能,如标准的两列基于CSS的布局,使用

作为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.properties中的struts.ui.theme属性(默认为xhtml)

如果您愿意为不同的标签使用不同的主题,以下是在标签级别指定它们的语法 -

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

因为在每个标记的基础上使用主题并不是很实际,所以我们可以使用以下标记在struts.properties文件中指定规则 -

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

以下是我们从本地化章节中获取的结果,其中我们使用默认主题,并在struts-default.properties文件中设置struts.ui.theme = xhtmlstruts-default.properties文件默认位于struts2-core.xy.z.jar文件中。

英语输出

主题如何运作?

对于给定的主题,每个struts标签都有一个关联的模板,如s:textfield → text.ftls:password → password.ftl等。

这些模板文件压缩在struts2-core.xy.z.jar文件中。 这些模板文件为每个标记保留了预定义的HTML布局。

通过这种方式, Struts 2框架使用Sturts标签和相关模板生成最终的HTML标记代码。

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

默认模板是用FreeMarker编写的,它们的扩展名为.ftl

您还可以使用velocity或JSP设计模板,并使用struts.ui.templateSuffixstruts.ui.templateDir在struts.properties中设置配置。

创造新主题

创建新主题的最简单方法是复制任何现有主题/模板文件并进行必要的修改。

让我们首先在WebContent/WEBINF/classes创建一个名为template的文件夹,并创建一个具有新主题名称的子文件夹。 例如, WebContent/WEB-INF/classes/template/mytheme

从这里开始,您可以从头开始构建模板,或者您也可以从Struts2 distribution中复制模板,以便将来根据需要进行修改。

我们将修改现有的默认模板xhtml用于学习目的。 现在,让我们将struts2-core-xyzjar/template/xhtml的内容复制到我们的主题目录,并仅修改WebContent/WEBINF/classes/template/mytheme/control .ftl文件。 当我们打开control.ftl时,它将具有以下行 -

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

让我们更改上面的文件control.ftl以获得以下内容 -

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

如果您将检查form.ftl那么您会发现control.ftl在此文件中使用,但form.ftl从xhtml主题引用此文件。 所以让我们改变如下 -

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

我认为,你对FreeMarker模板语言不太了解,你仍然可以通过查看.ftl文件来了解要做的事情。

但是,让我们保存上面的更改,并返回到我们的本地化示例并使用以下内容创建WebContent/WEB-INF/classes/struts.properties文件

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

现在,在此更改后,右键单击项目名称,然后单击“ Export 》 WAR File以创建War文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2 。 这将产生以下屏幕 -

主题和模板

您可以看到表单组件周围的边框,这是我们在从xhtml主题复制后在主题中所做的更改的结果。 如果您不费力学习FreeMarker,那么您将能够非常轻松地创建或修改主题。

我希望你现在对Sturts 2主题和模板有基本的了解,不是吗?

Struts 2 - Exception Handling

Struts提供了一种更简单的方法来处理未捕获的异常并将用户重定向到专用的错误页面。 您可以轻松地将Struts配置为针对不同的异常具有不同的错误页面。

Struts通过使用“异常”拦截器使异常处理变得容易。 “异常”拦截器作为默认堆栈的一部分包含在内,因此您无需执行任何额外的配置。 它开箱即用,随时可供您使用。

让我们看一个简单的Hello World示例,在HelloWorldAction.java文件中进行一些修改。 在这里,我们故意在HelloWorldAction动作代码中引入了NullPointer异常。

package com.iowiki.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.iowiki.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
      </action>
   </package>
</struts>

现在右键单击项目名称,然后单击“ Export 》 WAR File以创建War文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将产生以下屏幕 -

Hello World输入

输入值“Struts2”并提交页面。 你应该看到以下页面 -

异常输出

如上例所示,默认的异常拦截器可以很好地处理异常。

现在让我们为Exception创建一个专用的错误页面。 使用以下内容创建名为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.iowiki.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。 如果您现在重新运行该程序,您现在将看到以下输出 -

Hello World输出

除此之外,Struts2框架还带有一个“日志记录”拦截器来记录异常。 通过启用记录器来记录未捕获的异常,我们可以轻松查看堆栈跟踪并找出出错的地方

全局异常映射

我们已经看到了如何处理特定于行动的异常。 我们可以在全局范围内设置一个适用于所有操作的例外。 例如,要捕获相同的NullPointerException异常,我们可以在“package ...”标记内添加《global-exception-mappings...》 ...”标记,并在“action ...”中添加“result ...”标记。 。“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">
      <global-exception-mappings>
         <exception-mapping exception = "java.lang.NullPointerException"
         result = "error" />
      </global-exception-mappings>
      <action name = "hello" 
         class = "com.iowiki.struts2.HelloWorldAction" 
         method = "execute">
         <result name = "success">/HelloWorld.jsp</result>
         <result name = "error">/Error.jsp</result>
      </action>
   </package>
</struts>

Struts 2 - Annotations

如前所述,Struts提供了两种配置形式。 传统方法是使用struts.xml文件进行所有配置。 到目前为止,我们已经在教程中看到了很多这样的例子。 配置Struts的另一种方法是使用Java 5 Annotations功能。 使用struts注释,我们可以实现Zero Configuration

要在项目中开始使用注释,请确保在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-logging-x.y.z.jar
  • commons-logging-api-x.y.jar
  • freemarker-x.y.z.jar
  • javassist-.xy.z.GA
  • ognl-x.y.z.jar
  • struts2-core-x.y.z.jar
  • xwork-core.x.y.z.jar

现在,让我们看看如何取消struts.xml文件中的可用配置并将其替换为注释。

为了解释Struts2中Annotation的概念,我们必须重新考虑Struts2 Validations一章中解释的验证示例。

在这里,我们将举例说明一个员工的名字,年龄将使用一个简单的页面捕获,我们将进行两次验证,以确保ÜSER始终输入一个名称,年龄应在28到65之间。

让我们从示例的主JSP页面开始。

创建主页面

让我们编写主页JSP文件index.jsp ,用于收集上面提到的Employee相关信息。

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <title>Employee Form</title>
   </head>
   <body>
      <s:form action = "empinfo" method = "post">
         <s:textfield name = "name" label = "Name" size = "20" />
         <s:textfield name = "age" label = "Age" size = "20" />
         <s:submit name = "submit" label = "Submit" align="center" />
      </s:form>
   </body>
</html>

index.jsp使用了我们尚未涉及的Struts标记,但我们将在标签相关章节中研究它们。 但是现在,假设s:textfield标签打印输入字段,s:submit打印一个提交按钮。 我们为每个标签使用了label属性,为每个标签创建标签。

创建视图 (Create Views)

我们将使用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>

Create Action

这是使用注释的地方。 让我们用注释重新定义动作类Employee ,然后在Employee.java文件中添加一个名为validate ()的方法,如下所示。 确保您的操作类扩展了ActionSupport类,否则将不会执行您的validate方法。

package com.iowiki.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注释。 结果注释是结果的集合。

  • 在结果注释下,我们有两个结果注释。 结果注释具有与execute方法的结果相对应的name 。 它们还包含一个位置,该位置应该提供与execute()的返回值相对应的视图

  • 下一个注释是Action注释。 这用于装饰execute()方法。 Action方法还接受一个值,该值是调用操作的URL。

  • 最后,我使用了两个validation注释。 我在name字段上配置了必需的字段验证器,在age字段上配置了整数范围验证器。 我还为验证指定了自定义消息。

配置文件 (Configuration Files)

我们真的不需要struts.xml配置文件,所以让我们删除这个文件,让我们检查一下web.xml文件的内容 -

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

现在,右键单击项目名称,然后单击“ Export 》 WAR File以创建War文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/index.jsp 。 这将产生以下屏幕 -

电子邮件用户输入

现在不要输入任何必要的信息,只需点击Submit按钮即可。 您将看到以下结果 -

错误

输入所需信息,但输入错误的From字段,让我们将名称命名为“test”,将年龄改为30,最后单击Submit按钮。 您将看到以下结果 -

成功

Struts 2注释类型

Struts 2应用程序可以使用Java 5注释作为XML和Java属性配置的替代方法。 您可以查看与不同类别相关的最重要注释列表 -

Struts 2注释类型

Struts 2 - Control Tags

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>

检查详细示例

迭代器标签

这个iterator将迭代一个值。 可迭代的值可以是itherjava.util.Collection或java.util.Iterator文件。 迭代迭代器时,可以使用Sort标记对结果或SubSet标记进行排序,以获取列表或数组的子集。

以下示例检索值堆栈上当前对象的getDays()方法的值,并使用它进行迭代。

标记打印出迭代器的当前值。

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

检查详细示例

合并标签

这些merge标记将两个或多个列表作为参数并将它们合并在一起,如下所示 -

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

检查详细示例

附加标记

这些append标记将两个或多个列表作为参数并将它们全部附加在一起,如下所示 -

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

检查详细示例

生成器标签

这些generator标签根据提供的val属性生成迭代器。 以下生成器标记生成迭代器并使用迭代器标记将其打印出来。

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

检查详细示例

Struts 2 - Data Tags

Struts 2 data tags主要用于处理页面上显示的数据。 下面列出了重要的数据标签:“从这里开始”

行动标签

此标记使开发人员可以通过指定操作名称和可选命名空间直接从JSP页面调用操作。 标记的主体内容用于呈现Action的结果。 除非指定了executeResult参数,否则将忽略在struts.xml中为此操作定义的任何结果处理器。

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

检查详细示例

包含标签

这些include将用于在另一个JSP页面中包含JSP文件。

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

检查详细示例

豆标签

这些bean标记实例化一个符合JavaBeans规范的类。 这个标签有一个主体,它可以包含许多Param元素来设置该类的任何mutator方法。 如果在BeanTag上设置了var属性,它会将实例化的bean放入堆栈的Context中。

<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标记用于获取值的属性,如果未指定,则默认为堆栈的顶部。

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

检查详细示例

推送标签

这些push标签用于推动堆栈上的值以简化使用。

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

检查详细示例

设置标签

这些set标记为指定范围内的变量赋值。 当您希望将变量分配给复杂表达式,然后每次只引用该变量而不是复杂表达式时,它非常有用。 可用的范围是application, session, request, pageaction

<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。

<-- 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 - The Form Tags

form标记列表是Struts UI标记的子集。 这些标记有助于呈现Struts Web应用程序所需的用户界面,并可分为三类。 本章将介绍所有三种类型的UI标签 -

简单的UI标签

我们已经在我们的示例中使用了这些标记,我们将在本章中对它们进行刷新。 让我们看一个带有几个简单UI标签的简单视图页面email.jsp -

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <s:head/>
      <title>Hello World</title>
   </head>
   <body>
      <s:div>Email Form</s:div>
      <s:text name = "Please fill in the form below:" />
      <s:form action = "hello" method = "post" enctype = "multipart/form-data">
         <s:hidden name = "secret" value = "abracadabra"/>
         <s:textfield key = "email.from" name = "from" />
         <s:password key = "email.password" name = "password" />
         <s:textfield key = "email.to" name = "to" />
         <s:textfield key = "email.subject" name = "subject" />
         <s:textarea key = "email.body" name = "email.body" />
         <s:label for = "attachment" value = "Attachment"/>
         <s:file name = "attachment" accept = "text/html,text/plain" />
         <s:token />
         <s:submit key = "submit" />
      </s:form>
   </body>
</html>

如果您了解HTML,那么所有使用的标签都是非常常见的HTML标签,附加前缀为s:以及每个标签和不同的属性。 当我们执行上述程序时,如果您为所有使用的键设置了正确的映射,我们将获得以下用户界面。

Struts简单的UI标签

如图所示,s:head生成Struts2应用程序所需的javascript和stylesheet元素。

接下来,我们有s:div和s:文本元素。 s:div用于呈现HTML Div元素。 这对于不喜欢将HTML和Struts标记混合在一起的用户非常有用。 对于那些人,他们可以选择使用s:div来渲染div。

s:显示的文本用于在屏幕上呈现文本。

接下来我们有了famiilar s:form标签。 s:form标签有一个action属性,用于确定提交表单的位置。 因为我们在表单中有一个文件上传元素,所以我们必须将enctype设置为multipart。 否则,我们可以留空。

在表单标记的末尾,我们有s:submit标记。 这用于提交表单。 提交表单后,所有表单值都将提交到s:form标记中指定的操作。

在s:form中,我们有一个名为secret的隐藏属性。 这将在HTML中呈现隐藏元素。 在我们的例子中,“secret”元素的值为“abracadabra”。 该元素对最终用户不可见,用于将状态从一个视图传送到另一个视图。

接下来我们有s:label,s:textfield,s:password和s:textarea标签。 它们分别用于渲染标签,输入字段,密码和文本区域。 我们已经在“Struts - 发送电子邮件”示例中看到了这些内容。

这里要注意的重要一点是使用“key”属性。 “key”属性用于从属性文件中获取这些控件的标签。 我们已经在Struts2 Localization,国际化章节中介绍了这个功能。

然后,我们有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>

当我们执行上述程序时,我们的输出将类似于以下内容 -

Struts组UI标签

我们现在来看看这个例子。 在第一个示例中,我们创建了一个标签为“Gender”的简单单选按钮。 name属性对于单选按钮标记是必需的,因此我们指定名称为“gender”。 然后,我们提供性别列表。 该列表填充了“男性”和“女性”的值。 因此,在输出中我们得到一个带有两个值的单选按钮。

在第二个示例中,我们创建了一个复选框列表。 这是为了收集用户的爱好。 用户可能有多个爱好,因此我们使用复选框而不是单选按钮。 该复选框填充了“sports”,“TV”和“Shopping”列表。 这将业余爱好列为复选框列表。

选择UI标签

让我们来探索Struts提供的Select Tag的不同变体。 让我们看一下带有select标签的简单视图页面HelloWorld.jsp -

<%@ page contentType = "text/html; charset = UTF-8"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<html>
   <head>
      <title>Hello World</title>
      <s:head />
   </head>
   <body>
      <s:form action = "login.action">
         <s:select name = "username" label = "Username"
            list = "{'Mike','John','Smith'}" />
         <s:select label = "Company Office" name = "mySelection"
            value = "%{'America'}" list="%{#{'America':'America'}}">
            <s:optgroup label = "Asia" 
               list = "%{#{'India':'India','China':'China'}}" />
            <s:optgroup label = "Europe"
               list="%{#{'UK':'UK','Sweden':'Sweden','Italy':'Italy'}}" />
         </s:select>
         <s:combobox label = "My Sign" name = "mySign"
            list = "#{'aries':'aries','capricorn':'capricorn'}" headerkey = "-1" 
            headervalue = "--- Please Select ---" emptyOption = "true" value = "capricorn" />
         <s:doubleselect label = "Occupation" name = "occupation"
            list = "{'Technical','Other'}" doublename = "occupations2"
            doubleList="top == 'Technical' ? 
            {'I.T', 'Hardware'} : {'Accounting', 'H.R'}" />
      </s:form>
   </body>
</html>

当我们执行上述程序时,我们的输出将类似于以下内容 -

Struts选择UI标签

现在让我们一个接一个地审视个案。

  • 首先,select标签呈现HTML选择框。 在第一个示例中,我们创建了一个名为“username”的简单选择框和标签“username”。 选择框将填充一个包含名称Mike,John和Smith的列表。

  • 在第二个例子中,我们公司在美国设有总部。 它还在亚洲和欧洲设有全球办事处。 我们希望在选择框中显示办公室,但我们希望按照非洲大陆的名称对全球办事处进行分组。 这是optgroup派上用场的地方。 我们使用s:optgroup标签创建一个新组。 我们给该组一个标签和一个单独的列表。

  • 在第三个例子中,使用组合框。 组合框是输入字段和选择框的组合。 用户可以从选择框中选择一个值,在这种情况下,输入字段将自动填入用户选择的值。 如果用户直接输入值,则不会选择选择框中的值。

  • 在我们的例子中,我们有一个列出太阳星座的组合框。 选择框仅列出四个条目,允许用户输入他的太阳星座(如果它不在列表中)。 我们还在选择框中添加标题条目。 headerentry是显示在选择框顶部的那个。 在我们的例子中,我们想要显示“请选择”。 如果用户没有选择任何内容,那么我们假设-1为值。 在某些情况下,我们不希望用户选择空值。 在这些条件下,可以将“emptyOption”属性设置为false。 最后,在我们的示例中,我们提供“摩羯座”作为组合框的默认值。

  • 在第四个例子中,我们有一个双重选择。 如果要显示两个选择框,则使用双精度选择。 在第一个选择框中选择的值确定第二个选择框中显示的值。 在我们的示例中,第一个选择框显示“Technical”和“Other”。 如果用户选择技术,我们将在第二个选择框中显示IT和硬件。 否则我们将显示会计和人力资源。 这可以使用示例中所示的“list”和“doubleList”atrributes。

在上面的示例中,我们进行了比较,以查看顶部选择框是否等于技术。 如果是,那么我们显示IT和硬件。

我们还需要为顶部框(“name ='Occupations')和底部框(doubleName ='occupations2')命名

Struts 2 - The Ajax Tags

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>

当我们运行上面的例子时,我们得到以下输出 -

Struts Ajax标签

现在让我们一步一步地完成这个例子。

首先要注意的是添加了一个带有前缀sx的新标签库。 这个(struts-dojo-tags)是专门为ajax集成创建的标记库。

然后在HTML头部内部调用sx:head。 这会初始化dojo框架并使其为页面内的所有AJAX调用做好准备。 这一步很重要 - 如果没有初始化sx:head,你的ajax调用将无法工作。

首先,我们有自动完成标签。 autocompleter标签看起来非常像一个选择框。 它的值为红色,绿色和蓝色。 但是选择框与此选项之间的区别在于它自动完成。 也就是说,如果你开始输入gr,它将填充“绿色”。 除此之外,这个标签与我们之前介绍的s:select标签非常相似。

接下来,我们有一个日期时间选择器。 此标记创建一个输入字段,旁边有一个按钮。 按下按钮时,将显示弹出日期时间选择器。 当用户选择日期时,日期将以标记属性中指定的格式填充到输入文本中。 在我们的示例中,我们指定dd/MM/yyyy作为日期的格式。

接下来,我们为我们在早期练习中创建的system.action文件创建一个url标记。 它不必是system.action - 它可以是您之前创建的任何操作文件。 然后我们有一个div,超链接设置为url,延迟设置为2秒。 运行此操作时会发生什么,“初始内容”将显示2秒钟,然后div的内容将替换为hello.action执行中的内容。

最后,我们有一个带有两个标签的简单标签面板。 选项卡使用标签Tab 1和Tab2对它们进行分隔。

值得注意的是,Struts中的AJAX标记集成仍在进行中,并且每次发布时,此集成的成熟度都在逐渐增加。

Struts 2 & Spring Integration

Spring是一个流行的Web框架,可以轻松集成许多常见的Web任务。 所以问题是,当我们拥有Struts2时,为什么我们需要Spring呢? 好吧,Spring不仅仅是一个MVC框架 - 它提供了很多Struts中没有的其他好东西。

例如:依赖注入可以对任何框架有用。 在本章中,我们将通过一个简单的示例来了解如何将Spring和Struts2集成在一起。

首先,您需要将以下文件添加到Spring安装的项目构建路径中。 您可以从https://www.springsource.org/download下载并安装最新版本的Spring Framework

  • 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

最后在struts lib目录中的WEB-INF/lib添加struts2-spring-plugin-xyzjar 。 如果您使用的是Eclipse,则可能会遇到异常java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener

要解决此问题,您必须进入Marker选项卡并逐个单击类依赖关系并执行快速修复以发布/导出所有依赖项。 最后确保标记选项卡下没有可用的依赖冲突。

Struts和Sprint集成

现在让我们为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.iowiki.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.iowiki.struts2.User">
      <property name = "firstName" value = "Michael" />
      <property name = "lastName" value = "Jackson" />
   </bean>
</beans>

如上所示,我们已经配置了用户bean,并且已经将值MichaelJackson注入到bean中。 我们还给这个bean命名为“userClass”,以便我们可以在其他地方重用它。 接下来让我们在WebContent文件夹中创建User.jsp -

<%@ page language = "java" contentType = "text/html; charset = ISO-8859-1"
   pageEncoding = "ISO-8859-1"%>
<%@ taglib prefix = "s" uri = "/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
   "http://www.w3.org/TR/html4/loose.dtd">
<html>
   <head>
      <title>Hello World</title>
   </head>
   <body>
      <h1>Hello World From Struts2 - Spring integration</h1>
      <s:form>
         <s:textfield name = "firstName" label = "First Name"/><br/>
         <s:textfield name = "lastName" label = "Last Name"/><br/>
      </s:form>
   </body>
</html>

User.jsp文件非常简单。 它仅用于一个目的 - 显示用户对象的名字和姓氏的值。 最后,让我们使用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文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/User.jsp 。 这将产生以下屏幕 -

Struts和Spring集成

我们现在已经看到了如何将两个伟大的框架结合在一起。 这就是Struts - Spring集成章节的结尾。

Struts 2 & Tiles Integration

在本章中,我们将介绍将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

现在让我们为Struts-Tiles集成设置web.xml ,如下所示。 这里有两点需要注意。 首先,我们需要告诉tile,在哪里找到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, bodyfooter 。 我们提供baseLayout的默认值,然后我们创建两个从默认布局扩展的自定义。 老虎布局类似于基本布局,除了它使用tiger.jsp作为其主体和文本“Tiger”作为标题。 类似地,狮子布局类似于基本布局,除了它使用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页面放在一起。 我们将tile属性插入到我们需要它们的位置。 接下来,让我们创建一个包含以下内容的banner.jsp文件 -

<img src="http://www.iowiki.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.iowiki.struts2;
import com.opensymphony.xwork2.ActionSupport;
public class MenuAction extends ActionSupport {
   public String tiger() { return "tiger"; }
   public String lion() { return "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.iowiki.struts2.MenuAction">
         <result name = "tiger" type = "tiles">tiger</result>
         <result name = "lion" type = "tiles">lion</result>
      </action>
   </package>
</struts>

让我们检查一下我们在上面文件中做了什么。 首先,我们声明了一个名为“tiles”的新结果类型,因为我们现在使用tile而不是plain 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()。 然后,我们需要将结果的结果映射到适当的切片页面。

现在右键单击项目名称,然后单击“ Export 》 WAR File以创建War文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/tigerMenu.jsp 。 这将产生以下屏幕 -

Struts和Tiles集成

同样,如果您转到lionMenu.action页面,您将看到使用相同图块布局的狮子页面。

Struts 2 and Hibernate Integration

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.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.iowiki.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.iowiki.hibernate.Student" />
   </session-factory>
</hibernate-configuration> 

我们来看看hibernate配置文件。 首先,我们声明我们正在使用MySQL驱动程序。 然后我们声明了jdbc url用于连接数据库。 然后我们声明了连接的用户名,密码和池大小。 我们还指出,我们希望通过将“show_sql”设置为true来查看日志文件中的SQL。 请仔细阅读hibernate教程,了解这些属性的含义。

最后,我们将映射类设置为com.iowiki.hibernate.Student,我们将在本章中创建它。

环境设置

接下来,你需要为这个项目提供大量的罐子。 附件是所需JAR文件的完整列表的屏幕截图 -

Struts和Hibernate Jars

大多数JAR文件都可以作为struts发行版的一部分获得。 如果您安装了诸如glassfish,websphere或jboss之类的应用程序服务器,那么您可以从appserver的lib文件夹中获取大部分剩余的jar文件。 如果没有,您可以单独下载文件 -

其余的文件,你应该能够从你的Struts2发行版中获得。

Hibernate类

现在让我们为hibernate集成创建所需的java类。 以下是Student.java的内容 -

package com.iowiki.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.iowiki.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类的数据访问层。 它有方法列出所有学生,然后保存新的学生记录。

行动类

以下文件AddStudentAction.java定义了我们的动作类。 我们这里有两个动作方法 - execute()和listStudents()。 execute()方法用于添加新的学生记录。 我们使用dao的save()方法来实现这一点。

另一种方法是listStudents()用于列出学生。 我们使用dao的list方法来获取所有学生的列表。

package com.iowiki.struts2;
import java.util.ArrayList;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.iowiki.hibernate.Student;
import com.iowiki.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.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和标记。 由于addStudent操作与ModelAware“AddSudentAction”绑定,因此将自动创建一个学生bean,其中firstName,lastName和marks的值已自动填充。

在底部,我们将浏览学生列表(请参阅AddStudentAction.java)。 我们遍历列表并显示表中名字,姓氏和标记的值。

Struts配置

让我们使用struts.xml将它们放在一起 -

<?xml version = "1.0" Encoding = "UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <constant name = "struts.devMode" value = "true" />
   <package name = "myhibernate" extends = "hibernate-default">
      <action name = "addStudent" method = "execute"
         class = "com.iowiki.struts2.AddStudentAction">
         <result name = "success" type = "redirect">
            listStudents
         </result>
      </action>
      <action name = "listStudents" method = "listStudents"
         class = "com.iowiki.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文件。 然后在Tomcat的webapps目录中部署此WAR。 最后,启动Tomcat服务器并尝试访问URL http://localhost:8080/HelloWorldStruts2/student.jsp 。 这将产生以下屏幕 -

Struts和Hibernate结果

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

↑回到顶部↑
WIKI教程 @2018