TutorialsPoint Struts2 教程

来源：易百教程

Struts2教程

Apache Struts 2 是一种流行的 Java模型 - 视图 - 控制器（MVC）框架，成功地结合了 WebWork和Struts1.x 两种 web 框架。

Apache Struts2与Struts1完全不同，它的核心功能都是使用拦截实现“值栈”的概念，OGNL表达式和Struts2标签来解决应用程序数据，很多注解和约定，使这个框架更加易于使用。 在本教程中，它提供了许多使用Struts2的MVC框架的实例和解释。

欢迎来到易百教程学习Struts2。

Struts2 快速入门

Struts2快速入门的例子。

Struts 2 hello world (XML版本) 使用XML文件的Struts 2 Hello World 示例

Struts 2 Hello World (注解版本) 使用注释的Struts 2 Hello World 示例

@ResultPath 注释示例 @ResultPath 注释说明和示例

Struts2 配置

任何关于 Struts2 的配置文件。

多个Struts配置文件示例拆分大的Struts配置文件分成多个小的配置文件。

Struts2 命名空间配置和解释 Struts2命名空间是一个新的概念，用来处理多个模块，由下式给出一个命名空间对应的每个模块。

Struts2开发模式启用了Struts2开发模式将会使调试变得更容易。

如何删除Struts2动作的后缀扩展名默认的“.action”扩展名是丑陋的，并不是用户友好的，可以删除或用另一个扩展名来取代它。

Struts2 动作和表单

Struts 2的动作和表单数据管理。

使用Struts2动作Struts 2的动作说明和示例。

Struts 2 ActionError & ActionMessage Example Struts 2的ActionError和ActionMessage的解释和例子。

Struts 2 ModelDriven example 自动将的表单数据传输到对象。

Struts2 拦截器

关于Struts 2的拦截器。

映射拦截动作配置拦截器动作。

重写拦截器参数几种方法来覆盖拦截器的参数。

拦截器栈的例子拦截器堆栈用于建立一组的拦截器，以再利用。

创建自己的拦截器创建自己的拦截器指南，以满足您的需求。

execAndWait拦截器例子一个非常方便的拦截器长时间运行动作在后台，显示用户的自定义的等待页面。

Struts 2 UI标签

Struts 2的UI标签，来渲染HTML表单和非表单组件。

TextBox文档示例 Struts2 <s:textfield> 文本实例.

Password 示例 Struts2 <s:password> 密码实例.

Hidden隐藏值示例 Struts2 <s:hidden> 隐藏值例子

Textarea - 文本域 Struts2 <s:textarea> textarea例子

Radio 单选按键示例 Struts2 <s:radio> radio单选按钮例子

预选单选按钮预选单选按钮值示例

复选框heckbox 示例 Struts2 <s:checkbox> 复选框示例

复选框checkboxes 示例 Struts2 <s:checkboxlist> 多发复选框的例子

设置复选框的默认值设置多个复选框的默认值

下拉框示例 Struts2 <s:select> 下拉框例子

自动选择下拉框示例自动选择下拉框值指南

组合框示例 Struts2 <s:combobox> 组合框的例子

head 示例 Struts2 <s:head>, 呈现一个HTML头组件

文件上传示例 Struts2 <s:file> 文件上传示例

多文件上传示例 Struts2 <s:file> 多文件上传示例

级联选择示例 Struts2 <s:doubleselect>, 创建两个HTML下拉框，当第一下拉列表中选择，第二下拉列表将相应地改变

updownselect 示例 Struts2 <s:updownselect>, 创建一个带有按钮，向上或向下移动在选择组件的选项选择HTML组件。

optiontransferselect 示例 Struts2 <s:optiontransferselect>, 两个“updownselect”选择组件排列在左侧和右侧，在它们中间包含有按钮来移动自己的选择选项。

datetimepicker 日期选择 Struts2 <s:datetimepicker>, 将呈现一个文本框和追加后面的日历图标，单击日历图标上会提示的日期时间选择器组件。

autocompleter自动完成示例 Struts2 <s:autocompleter>, 一个组合框，会自动提示下拉的提示菜单，在用户输入文本框时。

autocompleter + JSON 示例举个例子，使用JSON数据填充到autocompleter组件。

Struts 2 控制标签

在 Struts2 中的控制标签或逻辑标签，用来做条件处理，迭代，处理和显示数据。

<s:iterator>标签迭代示例 Struts2迭代器标签用来迭代一个值，它可以是任何的 java.util.Collection 或 java.util.Iterator

<s:if>, <s:elseIf>, <s:else> 标签示例 Struts2 if,elseif和else标签被用来执行基本条件检查。

<s:append>标签示例 Struts2 <s:append>标签用来组合几个迭代器（由列表或映射创建）到一个迭代器

<s:generator> 标签示例 struts2 <s:generator>标记用于基于在页中提供“val”属性，以产生一个迭代。

<s:merge>标签示例 Struts2 <s:merge>标签用来合并几个迭代器（以列表或映射创建）成一个迭代器。

<s:sort>标签示例 Struts2 <s:sort>是用于排序一个列表，它通过使用 java.util.Comparator 来实现。

subset tag example Struts2 <s:subset>标记用于输出一个迭代元素的子集或部分。

Struts2 数据标签

Struts2数据标签，从ValueStack中获取数据，或将数据放入ValusStack。

<s:a>标签示例 Struts2的<s:a>标签被用于渲染HTML的“<a>”标签。

<s:action>标签示例 Struts2的<s:action>标签用来直接在一个JSP页面中调用Action类

<s:bean>标签示例 Struts2的<s:bean>标签用来在JSP页面中实例化一个类

<s:date>标签示例 Struts2的<s:date>标签用来在JSP页面格式Date对象。

<s:debug>标签示例 Struts 2的<s:debug>标签是一个非常有用的调试标记，用于输出“值栈”的内容，并在JSP页面中输出“堆栈上下文”的详细信息。

<s:include>标签示例 Struts 2的<s:include>标签用来直接包含JSP或HTML页面到当前页面。

<s:i18n>标签示例 Struts 2的<s:i18n>标签用来获取声明的资源包，而不仅仅是资源包，也可获取当前操作相关联的消息。

<s:param>标签示例 Struts2的<s:param>标签用来参数化其他标签。

<s:property>标签示例 Struts2的<s:property>标签用来从一个类获取当前默认Action类的属性值。

<s:push>标签示例 Struts2的<s:push>标签用来推值到堆栈的顶部，以便它可以容易访问或参考。

<s:set>标签示例 Struts2的<s:set>标签用来在指定的范围内（应用，会话，请求，页面，或动作）赋值给一个变量

<s:text>标签示例 Struts2的<s:text>标签用于从操作类取出资源包消息

<s:url>标签示例 Struts2的 <s:url> 标签用来创建一个URL，并输出作为文本格式

Struts2 资源包和本地化

Struts2的资源包来支持网络定位功能（多语言）

资源包使用示例 Struts2的资源包的解释和例子

i18n 或本地化示例一个Struts 2的国际化和多语言的例子来说明如何使用资源包来显示不同语言的消息

key 属性示例 Struts 2 key属性在UI组件是处理本地化的常用方法，也UI标签编码的一个非常有效的方法

Chinese 本地化问题一个常见的中国本地化的问题

配置全局资源包配置Struts2的全局资源包指南

Struts2主题

Struts2 的布局是由“XHTML”主题设计的，所以了解 Struts2 主题概念是必须的。

Struts2 主题和模板 Struts 2主题和模板的说明和示例

Struts2集成其它框架

Struts2与任何他人框架的整合 - Spring, Hibernate, Quartz, Log4j…

Struts2 + Spring集成实例 Struts2和Spring框架集成。

Struts2 + Quartz调度集成实例 Struts2和Quartz调度框架集成。

Struts2 + Hibernate 集成实例集成 Struts2 和 Hibernate 框架。

Struts2 + Hibernate使用“Full Hibernate Plugin"插件集成使用 “Full Hibernate Plugin”集成Struts2 和Hibernate3

Struts2 + Spring + Hibernate集成实例集成Struts2，Spring和Hibernate三个框架。

Struts 2 + Log4j 集成实例集成Struts 2 和Log4j 框架.

Struts2 FAQ

FilterDispatcher 和 StrutsPrepareAndExecuteFilter区别？关于开发问 filterdispatcher 和 strutsprepareandexecutefilter 之间的差异。

在Struts2中获取 HttpServletRequest 获取 Struts2 HttpServletRequest对象的实例。

在Struts2获取HttpServletResponse对象在Struts2中如何获取 HttpServletResponse 对象实例

在Struts2中如何获取ServletContext对象在Struts2获取ServletContext对象实例

在Struts2中配置静态参数(有示例代码) 在Struts2配置静态参数实例

Struts2下载文件实例（有实例代码） Struts2实现下载文件实例

Struts2 和 JSON 实例（有实例代码）举个例子来说明Struts2集成JSON数据。

Struts2 参考

Struts2 官方文档

Struts2 通用标签

http://en.wikipedia.org/wiki/Apache_Struts

Struts 2 hello world (XML版本) - Struts2教程

在这个例子中，我们将学习如何在Struts 2中创建一个Hello World例子。

使用以下库或工具：

MyEclipse 10

Struts 2.1

整个工程结构如下图所示：

1. 创建一个Web项目工程

启动打开 MyEclipse，创建一个Web工程名称为：struts2-xml-demo，选择 File -> New -> Web Project ，如下图所示：

在这个项目上添加 struts2 的支持，右键点击 struts2-xml-demo 工程，选择 MyEclipse -> Add Struts Capabilities，在弹出的对话框中选择 Strut 2.1，如下图所示：

2. JSP视图文件

这是一个JSP登录页面，它使用Struts2标签来显示用户名，密码输入框和提交按钮。

Fie : login.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head></head>
<body>
    <h1>Struts 2 Hello World Example</h1>

    <s:form action="Welcome">
        <s:textfield name="username" label="Username" />
        <s:password name="password" label="Password" />
        <s:submit />
    </s:form>

</body>
</html>

文件: welcome_user.jsp – 一个JSP视图用来页面显示欢迎信息给用户。

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head></head>
<body>
    <h1>Struts 2 Hello World 示例</h1>

    <h2>
        Hello
        <s:property value="username" />
    </h2>

</body>
</html>

对 Struts1 和 Struts2 有非常相似的UI标签语法，只是在命名HTML元素，例如，术语有一点不同：

Struts 1

<%@taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<html:form action="Welcome">
   <html:text property="username"/>
</html:form>

Struts 2

<%@ taglib prefix="s" uri="/struts-tags" %>
<s:form action="Welcome">
    <s:textfield name="username" label="Username"/>
</s:form>

5. 动作，所有的业务逻辑放在这里

一个简单的 Struts2 的 Action 类，它里面声明的所有业务逻辑。

File : WelcomeUserAction.java

package com.yiibai.user.action;

/**
 *
 * @author yiibai.com
 *
 */
public class WelcomeUserAction {

    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    // all struts logic here
    public String execute() {

        return "SUCCESS";

    }
}

在Struts2中，Action类实现任何接口或扩展任何类不是必需的，但它需要创建一个execute()方法来实现所有的业务逻辑，并返回一个字符串值，告诉用户重定向到哪里。

注意您可能会看到一些用户实现 com.opensymphony.xwork2.Action 类， 但它是完全可选的(不是必须的)，因为com.opensymphony.xwork2.Action只是提供一些方便的常量。Struts1中的Action类需要扩展org.apache.struts.action.Action。 但是，Struts 2的Action类是可选的，但是仍然允许执行com.opensymphony.xwork2.Action的一些方便的常量，或者扩展com.opensymphony.xwork2.ActionSupport 对于一些常见的默认动作执行的功能。

5. Struts配置文件

Strut配置文件是用来连接所有的东西在一起。 XML文件名必须是 “struts.xml”。在这个实例中，它位于

File : struts.xml

_<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
    <package name="user" namespace="/User" extends="struts-default">
        <action name="Login">
            <result>/login.jsp</result>
        </action>
        <action name="Welcome" class="com.yiibai.user.action.WelcomeUserAction">
            <result name="SUCCESS">/welcome_user.jsp</result>
        </action>
    </package>
</struts>_

声明包和包含动作类，动作类是不言自明的，但你仍可能会感兴趣下面的新标签：

1. package name=”user” 就在包名，并不真正去关心它。

2. namespace=”/User” 它用于匹配“/User”URL模式。

注意实际上，Struts2的命名空间相当于Struts的1多个功能模块

3. extends=”struts-default” 这意味着该包是扩展了struts-default 包组件和拦截器，这是在struts-default.xml中文件中声明的，位于struts2-core.jar 文件的根目录。

6. web.xml

配置Web应用程序部署描述符(web.xml)文件Struts2的集成到Web项目。

File web.xml

_<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></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.ng.filter.StrutsPrepareAndExecuteFilter
      </filter-class>
  </filter>
  <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>*.action</url-pattern>
  </filter-mapping></web-app>_

7. 运行测试结果

在Struts2中，可以直接使用.action后缀访问操作类。如下URL：

http://localhost:8080/struts2-xml-demo/User/Login.action

提交后到 http://localhost:8080/Struts2Example/User/Welcome.action 显示如下：

Struts2注解示例 - Struts2教程

在这个教程，我们重复使用以前 STRUST2 Hello World(XML版本)的例子，并将其转换成注解版本。

Struts2 注解概念

Struts2注解是由Struts 2的约定插件的支持，所以，必须要了解其背后的“扫描方法”和“命名转换”机制的魔力。

1. 扫描方法

许多Struts 2的文章或书籍说，可以配置过滤器的“init-param”或“struts.convention.action.packages”告诉Struts2，其中扫描注解的类。 例如，

web.xml

<filter>
  <filter-name>struts2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
  <init-param>
    <param-name>actionPackages</param-name>
    <param-value>com.yiibai.common</param-value>
  </init-param>
</filter>

从测试(Struts22.1.6和2.1.8版本)，这是不正确的，不管你把在“param-value”还是 “struts.convention.action.packages“, 在Struts 2会忽略它，并只扫描指定的文件夹命名：struts, struts2, action 或 actions 。

下面是扫描工作

扫描其位于包的命名注解的类 “struts, struts2, action 或 actions“.

接着，扫描相匹配下列任一条件的文件：

实例了 com.opensymphony.xwork2.Action 接口。

扩展了 com.opensymphony.xwork2.ActionSupport 类

文件名用动作(例如：UserAction，LoginAction)结束

详细请查看这里Struts 2 约定插件文件

2. 命名转换器

Struts 2的约定插件将所有的注解操作文件名转换为指定的格式。

例如 : LoginAction.java

首先，去掉“Action”字符在文件名的末尾，如果存在的话。

其次，转换文件名的第一个字母为小写。

因此，去除结束并转换第一个字母为小写后，LoginAction.action 将变为 login.action。Struts2约定插件的“扫描方法”和“命名转换”特性真正带来了很多的便利和好处，只有当你的Struts2项目正确下面的命名约定才会带来好处; 否则，这将是一场灾难。

Struts 2 注解例子

现在是时候开始转换过程了，我们使用MyEclipse 10 创建一个工程为：struts2example。

最终的项目结构

2. LoginAction

扩展ActionSupport并创建了LoginAction，什么也不做，ActionSupport 默认返回 “success” 字符串,这将匹配 @Result 并重定位到 “pages/login.jsp“.

注解版本

package com.yiibai.user.action;

import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.ResultPath;

import com.opensymphony.xwork2.ActionSupport;

@Namespace("/User")
@ResultPath(value="/")
@Result(name="success",location="/login.jsp")
public class LoginAction extends ActionSupport{

}

XML 实现版本

**<package name="user" namespace="/User" extends="struts-default">
    <action name="Login">
        <result>/login.jsp</result>
    </action>
</package>**

3. WelcomeUserAction

重写execute()方法并指定 @Action 和 @Result 注解。

注解版本

package com.yiibai.user.action;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.ResultPath;

import com.opensymphony.xwork2.ActionSupport;

@Namespace("/User")
@ResultPath(value="/")
public class WelcomeUserAction extends ActionSupport{

    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Action(value="Welcome", results={
        @Result(name="success",location="welcome_user.jsp")
    })
    public String execute() {

        return SUCCESS;

    }
}

XML 实现版本

<package name="user" namespace="/User" extends="struts-default">
   <action name="Welcome" class="com.yiibai.user.action.WelcomeUserAction">
    <result name="SUCCESS">/welcome_user.jsp</result>
   </action>
</package>

Struts 2 注解 – @Action, @Result 和 @Namespace 不言自明，可以将它与XML比较。@ResultPath 可能需要一点点的解释，请参阅本 @ResultPath示例

4. JSP视图页面

普通JSP视图页面来接受用户名和密码后点击提交按钮，并重定向到一个欢迎页面。

login.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head></head>
<body>
    <h1>Struts 2 注解示例</h1>

    <s:form action="Welcome">
        <s:textfield name="username" label="用户名" />
        <s:password name="password" label="密码" />
        <s:submit value="提交"/>
    </s:form>

</body>
</html>

welcome_user.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head></head>
<body>
<h1>Struts 2 注解示例</h1>

<h4>您好, <s:property value="username"/></h4>

</body>
</html>

5. struts.xml

所有类注解无需创建 struts.xml 文件。

6. web.xml

只要创建一个典型的web.xml文件，并声明FilterDispatcher过滤器标准。

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Struts 2 Web Application</display-name>

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

7. 运行测试

LoginAction.action 改为 login.action，请参阅上面的“命名转换器”。

http://localhost:8080/struts2example/User/login.action

提交到 http://localhost:8080/Struts2Example/User/Welcome.action 后显示：

参考

Struts 2 约定插件文档

Strust 2 Hello World (XML 版本)

Struts2 @ResultPath注释示例 - Struts2教程

在Struts 2中, @ResultPath 注解用于控制Struts2找到存储的结果或JSP页面。默认情况下，它会找到结果页在 “WEB-INF/content/” 文件夹。不知道为什么在Struts2注解设置 “WEB-INF/content/” 作为默认目录, 但是大部分的应用并不将结果页放入到 “WEB-INF/content/” 目录. 可能Struts2惯例也并不是一个标准的文件夹结构。 我一般是在 Struts 2 根路径作为默认的文件夹。

@ResultPath 示例

1. 默认结果路径

在登录动作类,设置 “/User” 作为命名空间, 并重定向到 “pages/login.jsp” 页面。

P.S 假设struts2example是上下文servlet名称

@Namespace("/User")
@Result(name="success",location="pages/login.jsp")
public class LoginAction extends ActionSupport{
}

访问它，如下：

http://localhost:8080/struts2example/User/login.action

Struts 2将从默认位置找到“login.jsp”结果页面：

/struts2example/WEB-INF/content/User/pages/login.jsp

2. 定制结果路径

如果JSP结果页面存储在其他位置，那么可以使用 @ResultPath注释设置改变它。

@Namespace("/User")
@ResultPath(value="/")
@Result(name="success",location="pages/login.jsp")
public class LoginAction extends ActionSupport{
}

再一次访问：

http://localhost:8080/struts2example/User/login.action

现在Struts2将从不同的位置找到“login.jsp”结果页面：

/Struts2Example/User/pages/login.jsp

全局@ResultPath

@ResultPath只适用于类级别。在全局范围内应用它，可以在 struts.xml 文件中进行配置。

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.convention.result.path" value="/"/>
</struts>

参考

Struts 2 @ResultPath 注解文档

Struts2 include(包含)多个配置文件 - Struts2教程

Struts 2自带有“包含文件”功能，包含多个Struts配置文件合并为一个单元。

单个Struts配置文件

让我们来看看一个糟糕的 Struts 2 配置示例。

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>

<package name="default" namespace="/" extends="struts-default">
</package>

<package name="audit" namespace="/audit" extends="struts-default">
    <action name="WelcomeAudit">
        <result>pages/welcome_audit.jsp</result>
    </action>
</package>

<package name="user" namespace="/user" extends="struts-default">
    <action name="WelcomeUser">
        <result>pages/welcome_user.jsp</result>
    </action>
</package>

</struts>

在上面的Struts配置文件中，组织所有“用户”和“审核”配置设置在一个文件中，这不是建议的，必须回避。应该打破这种形式，而将struts.xml文件分成更小的模块相关的部分。

多个Struts配置文件

在Struts2，应该给每个模块一个Struts配置文件。在这种情况下，可以创建三个文件：

audit-struts.xml – 将所有审计模块设置在这里。

user-struts.xml – 将所有用户模块设置在这里。

struts.xml – 默认设置，包含 struts-audit.xml 和 Struts-user.xml 两个文件。

struts-audit.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>

<package name="audit" namespace="/audit" extends="struts-default">
    <action name="WelcomeAudit">
        <result>pages/welcome_audit.jsp</result>
    </action>
</package>

</struts>

struts-user.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>

<package name="user" namespace="/user" extends="struts-default">
    <action name="WelcomeUser">
        <result>pages/welcome_user.jsp</result>
    </action>
</package>

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

<package name="default" namespace="/" extends="struts-default">
</package>

<include file="conf/user-struts.xml"></include>
<include file="conf/audit-struts.xml"></include>

</struts>

现在文件夹结构看起来如下：

Struts2命名空间配置和解释 - Struts2教程

Struts 2的命名空间是一个新的概念，用来处理多个模块。由下式给出一个命名空间的每个模块。此外，它还可以用来避免位于不同的模块相同的操作名称之间的冲突。

看下面的一张图来了解一个URL匹配Struts 2的动作命名空间。

1. 命名空间配置

让我们通过一个Struts2的命名空间配置的例子来了解它是如何与URL和文件夹相匹配。

P.S 包中的“name”不会影响结果，只是给一个有意义的名字。

struts.xml

**<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
    <package name="default" namespace="/" extends="struts-default">
        <action name="SayWelcome">
            <result>/pages/welcome.jsp</result>
        </action>
    </package>

    <package name="common" namespace="/common" extends="struts-default">
        <action name="SayWelcome">
            <result>/common/pages/welcome.jsp</result>
        </action>
    </package>

    <package name="user" namespace="/user" extends="struts-default">
        <action name="SayWelcome">
            <result>/common/user/welcome.jsp</result>
        </action>
    </package>
</struts>**

Struts 2的动作命名空间映射到文件夹结构。

2. JSP视图页面

3 JSP页面视图具有相同的文件名，但是在不同的模块位置。

根 – pages/welcome.jsp

<html>
<head>
<title>Struts2命名空间示例 - yiibai.com</title>
</head>
<body>
    <h1>Struts2命名空间示例</h1>
    <h4>Welcome - namespace = "root"</h4>
</body>
</html>

Common 模块 – common/pages/welcome.jsp

<html>
<head>
<title>Struts2命名空间示例 - yiibai.com</title>
</head>
<body>
    <h1>Struts2命名空间示例</h1>
    <h4>Welcome - namespace = "common"</h4>
</body>
</html>

User 模块 – user/pages/welcome.jsp

<html>
<head>
<title>Struts2命名空间示例 - yiibai.com</title>
</head>
<body>
    <h1>Struts2命名空间示例</h1>

    <h4>Welcome - namespace = "user"</h4>
</body>
</html>

3. 映射 – 如何工作?

示例 1 URL : http://localhost:8080/Struts2Example/SayWelcome.action

将匹配根命名空间。

    <package name="default" namespace="/" extends="struts-default">
        <action name="SayWelcome">
            <result>/pages/welcome.jsp</result>
        </action>
    </package>

这会显示 pages/welcome.jsp 页面的内容

示例 2 URL : http://localhost:8080/Struts2Example/common/SayWelcome.action 这会匹配 common 命名空间的内容：

    <package name="common" namespace="/common" extends="struts-default">
        <action name="SayWelcome">
            <result>/common/pages/welcome.jsp</result>
        </action>
    </package>

这会显示 **common/pages/welcome.jsp **页面的内容

示例 3 URL : http://localhost:8080/Struts2Example/user/SayWelcome.action 这会匹配 common 命名空间的内容：

<package name="user" namespace="/user" extends="struts-default">
    <action name="SayWelcome">
        <result>/common/user/welcome.jsp</result>
    </action>
</package>

这会显示 user/pages/welcome.jsp 页面的内容.

参考

Struts2命名空间配置参考

代码下载：http://pan.baidu.com/s/1hqe1nZe

Struts2开发者模式 - Struts2教程

在Struts2开发中，这应该是第一个学习配置的值。为了启用 Struts 2 的开发模式，可以通过自动配置显著增加Struts2的开发速度和属性文件加载，以及额外的日志和调试功能。

注：自动重新加载功能真的是一个方便的功能。每次修改属性或XML配置文件更改，应用程序不再需要重启才能生效。默认情况下，Struts 2的开发模式是禁用的。

启用Struts2开发模式

将“struts.devMode”的值设置为true，可以在Struts的属性文件或XML配置文件。

struts.properties

struts.devMode = true

struts.xml

<struts>
     <constant name="struts.devMode" value="true" />
</struts>

禁用Struts 2的开发模式

设置“struts.devMode”为false，无论是在Struts属性文件或XML配置文件。

struts.properties

struts.devMode = false

struts.xml

<struts>
     <constant name="struts.devMode" value="false" />
</struts>

开发模式只适合于开发和调试环境。在生产环境中，你必须禁用它。因为整个应用程序的配置它会引起对性能显著影响，属性文件将在每次请求重新加载，许多额外的日志和调试信息也将提供。

参考

Struts 2 开发模式文档

如何删除Struts2动作的后缀扩展名 - Struts2教程

在Struts2中，所有动作类有一个默认的后缀 .action 扩展。 例如，

<struts>
  <package name="default" namespace="/" extends="struts-default">
    <action name="SayStruts2">
        <result>pages/printStruts2.jsp</result>
    </action>
  </package>
</struts>

如要访问“SayStruts2”动作类，需要使用以下网址：

Action URL : http://localhost:8080/Struts2Example/SayStruts2.action

配置动作扩展

Struts 2是允许配置扩展名的，要对其进行更改，只需要声明一个常数“struts.action.extension”值：

1. html 扩展

更改动作类为 .html 的扩展名。

<struts>

  <constant name="struts.action.extension" value="html"/>

  <package name="default" namespace="/" extends="struts-default">
    <action name="SayStruts2">
        <result>pages/printStruts2.jsp</result>
    </action>
  </package>

</struts>

现在，可以通过访问“SayStruts2”动作类，使用如下URL：

Action URL : http://localhost:8080/Struts2Example/SayStruts2.html

2. 不使用扩展

动作类更改为空的扩展。

<struts>

  <constant name="struts.action.extension" value=""/>

  <package name="default" namespace="/" extends="struts-default">
    <action name="SayStruts2">
        <result>pages/printStruts2.jsp</result>
    </action>
  </package>

</struts>

现在，可以通过如下的URL来访问“SayStruts2' 动作类：

Action URL : http://localhost:8080/Struts2Example/SayStruts2

使用Struts2动作 - Struts2教程

在Struts2中，会花大部分的时间用在用动作来处理工作。动作类包含业务逻辑，获取资源包，保存数据，验证，并选择应发回给用户的视图的结果页面。这是Struts2的核心，所以必须要了解动作的基本概念。

1. 动作 - Action

Struts 2动作不强迫你实现任何接口或扩展类，它只是需要你实现一个 execute()方法返回一个字符串来表示其应该返回的结果页面。

package com.yiibai.user.action;
public class LoginAction{
    //business logic
    public String execute() {
        return "success";
    }
}

在struts.xml中，配置使用Action类动作(action)标记和类属性。定义结果页面用结果的标签和动作名称返回给用户，可以用它来访问动作类的名称属性。

<package name="user" namespace="/User" extends="struts-default">
  <action name="validateUser" class="com.yiibai.user.action.LoginAction">
    <result name="success">pages/welcome.jsp</result>
  </action>
<package>

现在，可以通过 .action 扩展名后缀访问动作。

http://localhost:8080/Struts2Example/User/validateUser.action

默认.action是可配置的，只需要设置“struts.action.extension”的值，以满足您的需要。

2. 可选动作接口

Struts 2带有一个可选的动作接口(com.opensymphony.xwork2.Action)。通过实现这个接口，它带来了一些方便和好处，看下面的源代码：

package com.opensymphony.xwork2;
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;
}

这个接口是非常简单的，配有5常用常数值：success, error, none, input and logic。现在的动作类可以直接使用常量。

package com.yiibai.user.action;
import com.opensymphony.xwork2.Action;
public class LoginAction{
    //business logic
    public String execute() {
        return SUCCESS;
    }
}

不明白为什么很多Struts开发人员喜欢实现此动作接口，它更好地扩展了ActionSupport。

3. ActionSupport

Support 类，通常的做法是提供接口的默认实现。

ActionSupport (com.opensymphony.xwork2.ActionSupport), 一个非常强大和方便的类，它提供了几个重要接口的缺省实现：

public class ActionSupport implements Action, Validateable,
   ValidationAware, TextProvider, LocaleProvider, Serializable {
 ...
}

ActionSupport 类提供一些功能：

1. 验证 – 声明一个validate()方法，并在里面实现验证代码。

文字本地化 – 使用gettext()方法来获得资源包的消息。

package com.yiibai.user.action;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport{
    private String username;
    private String password;
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    //business logic
    public String execute() {
        return "SUCCESS";
    }
        //simple validation
    public void validate(){
        if("".equals(getUsername())){
            addFieldError("username", getText("username.required"));
        }
        if("".equals(getPassword())){
            addFieldError("password", getText("password.required"));
        }
    }
}

在大多数情况下，应该扩展此类妥当，方便提供功能，除非你有理由不这样做。这也是一个很不错的学习类，以了解如何做一些重要的Struts2接口的实现。

4. 动作注释

Struts 2对注解有很好的支持，你可以摆脱XML文件，并使用@action在动作类上替换。

package com.yiibai.user.action;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.ResultPath;
import com.opensymphony.xwork2.ActionSupport;
@Namespace("/User")
@ResultPath(value="/")
public class ValidateUserAction extends ActionSupport{
    @Action(value="Welcome", results={
        @Result(name="success",location="pages/welcome_user.jsp")
    })
    public String execute() {
        return SUCCESS;
    }
}

总结

扩展ActionSupport类，它适合在大多数情况下。

Struts2的ActionError＆ActionMessage示例 - Struts2教程

本教程显示使用Struts2的 ActionError 和 ActionMessage 类。

ActionError – 是用来发送错误信息反馈给用户 - 通过 <s:actionerror/> 来显示。

<s:if test="hasActionErrors()">
   <div class="errors">
      <s:actionerror/>
   </div>
</s:if>

ActionMessage – 用于发送信息的反馈消息给用户，通过 <s:actionmessage/> 来显示。

<s:if test="hasActionMessages()">
   <div class="welcome">
      <s:actionmessage/>
   </div>
</s:if>

这里有一个简单的登录表单，如果用户名不等于“yiibai.com”将显示错误消息(actionerror)，否则重定向到另一个页面，显示欢迎信息(ActionMessage)。此外，所有的标签和错误消息检索来自资源包(属性文件)。

1. 文件夹结构

在MyEclipse中创建一个web工程，名称为：struts2-errormsg，看这个项目结构，如下图：

2. 属性文件

一共有两个属性文件用来存储信息，其中 LoginAction.properties 文件放在 com.yiibai.user.action 包下。

LoginAction.properties

#Welcome messages
welcome.hello = 你好
#error message
username.required = 用户名不可以为空
password.required = 密码不可以为空

global.properties

#Global messages
global.username = 用户名
global.password = 密码
global.submit = 提交
global.reset = 重置

3. 动作-Action

一个经典的动作类，做一个简单的检查，以确认用户名是否等于“yiibai.com"，并使用 addActionError()设置错误信息或addActionMessage()设置成功的消息。

package com.yiibai.user.action;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport{

    private String username;
    private String password;

    public String getPassword() {
        return password;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    //business logic
    public String execute() {

        return "SUCCESS";

    }

    //simple validation
    public void validate(){
        if("yiibai.com".equals(getUsername())){
            addActionMessage("You are valid user!");
        }else{
            addActionError("I don't know you, dont try to hack me!");
        }
    }
}

4. JSP页面视图

两个简单的JSP页面以及CSS样式自定义错误消息。

login.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts2 ActionError & ActionMessage 示例</title>
<style type="text/css">
.errors {
    background-color:#FFCCCC;
    border:1px solid #CC0000;
    width:400px;
    margin-bottom:8px;
}
.errors li{
    list-style: none;
}
</style>
</head>
<body>
<h1>Struts2 ActionError & ActionMessage 示例</h1>
<s:if test="hasActionErrors()">
   <div class="errors">
      <s:actionerror/>
   </div>
</s:if>
<s:form action="validateUser">
    <s:textfield key="global.username" name="username"/>
    <s:password key="global.password" name="password"/>
    <s:submit key="global.submit" name="submit"/>
</s:form>
</body>
</html>

welcome.jsp

**<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Struts2 ActionError & ActionMessage 示例</title>
<style type="text/css">
.welcome {
    background-color: #DDFFDD;
    border: 1px solid #009900;
    width: 200px;
}
.welcome li {
    list-style: none;
}
</style>
</head>
<body>
    <h1>Struts 2 ActionError & ActionMessage示例</h1>
    <s:if test="hasActionMessages()">
        <div class="welcome">
            <s:actionmessage />
        </div>
    </s:if>
    <h4>
        <s:property value="getText('welcome.hello')" />
        <s:property value="username" />
    </h4>
</body>
</html>**

5. 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.custom.i18n.resources" value="global" />

  <package name="user" namespace="/user" extends="struts-default">
     <action name="login">
     <result>/pages/login.jsp</result>
     </action>
     <action name="validateUser" class="com.yiibai.user.action.LoginAction">
     <result name="SUCCESS">/pages/welcome.jsp</result>
     <result name="input">/pages/login.jsp</result>
     </action>
   </package>

</struts>

在Struts2，ActionError和ActionMessage功能和用法与Struts1非常相似。

6. 运行并测试

http://localhost:8080/struts2-errormsg/user/login.action

用户名是无效的，显示错误信息：<s:actionerror/>

用户名是有效的，显示欢迎信息：<s:actionmessage/>

源代码下载 – Struts2-ActionError-ActionMessage.zip

Struts2模型驱动实例 - Struts2教程

这里我们创建一个web工程为：struts2-modeldrive ，用于讲解演示Struts2模型驱动这一章内容的学习。

如果一个动作实现了“模型驱动”- ModelDriven 接口，它就获得了表单数据自动传输到对象的额外能力。请参见下面的完整的例子：

1. 域对象

一个顾客(customer)对象，有 setter 和 getter 方法。

Customer.java

package com.yiibai.common;

public class Customer{

    String name;
    int age;

    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;
    }

}

2. 动作 - Action

Action类，实现了模型驱动ModelDriven 接口，声明getModel()方法返回客户的对象。当表单数据提交到这个动作，它会自动将表单数据传输到客户的属性。

客户对象必须手动初始化。

CustomerAction.java

package com.yiibai.common.action;

import com.yiibai.common.Customer;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class CustomerAction extends ActionSupport
    implements ModelDriven{

    //have to initialize it
    Customer customer = new Customer();

    public String execute() throws Exception {

        return SUCCESS;

    }

    public Object getModel() {

        return customer;

    }
}

3. JSP页面

JSP页面的模型驱动(ModelDriven)的示范。

addCustomer.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
</head>

<body>
<h1>Struts 2 ModelDriven example</h1>

<h2>Add Customer</h2>
<s:form  action="customerAction" >
  <s:textfield name="name" label="Name" />
  <s:textfield name="age" label="Age" value=""/>
  <s:submit />
</s:form>

</body>
</html>

success.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
</head>

<body>
<h1>Struts 2 ModelDriven example</h1>

<h2>Customer Details</h2>
Name : <s:property value="name" /><br>
Age : <s:property value="age" /><br>

</body>
</html>

4. 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="default" namespace="/" extends="struts-default">

        <action name="addCustomerAction"
            class="com.yiibai.common.action.CustomerAction" >
            <result name="success">pages/addCustomer.jsp</result>
        </action>

        <action name="customerAction"
            class="com.yiibai.common.action.CustomerAction" >
            <result name="success">pages/success.jsp</result>
        </action>

    </package>

</struts>

5. 示例

访问客户表，填写表格 (name : “yiibai.com”, age ” “26”) 并点击提交按钮，表单数据(name & age) 将自动转移到客户的属性(name & age) (按属性名称匹配)。

http://localhost:8080/struts2-modeldrive/addCustomerAction.action

http://localhost:8080/struts2-modeldrive/customerAction.action

工程源代码下载 - http://pan.baidu.com/s/1hqxyjf2

Struts2映射拦截动作 - Struts2教程

Struts 2的开发者用来声明行为属于一个包，扩展 “struts-default“, 其中包含默认设置的拦截。

<package name="default" namespace="/" extends="struts-default">
    <action name="testingAction"
        class="com.yiibai.common.action.TestingAction" >
        <result name="success">pages/result.jsp</result>
    </action>
</package>

拦截器的默认设置进行分组为“defaultStack”在struts-default.xml文件中，它位于 struts2-core.jar 文件，“defaultStack”提供所有的核心Struts2功能，这是最适合应用的需要。

试着学习struts-default.xml文件，它总是最好的拦截器的参考。

映射拦截动作

为了其它的拦截器映射到动作，请使用“interceptor-ref”元素。

<package name="default" namespace="/" extends="struts-default">
    <action name="testingAction"
        class="com.yiibai.common.action.TestingAction" >
        <interceptor-ref name="timer"/>
        <interceptor-ref name="logger"/>
        <result name="success">pages/result.jsp</result>
    </action>
</package>

在上面的代码片段，将其映射“timer” 和 “logger”通过“interceptor-ref”元素拦截到“TestingAction”动作类。拦截器会按它们声明的顺序触发。

由于“TestingAction”它声明自己的拦截器，它的直接失去拦截器的所有继承默认设置，你必须明确才能使用它，见下面声明“defaultStack”的例子。

<package name="default" namespace="/" extends="struts-default">
    <action name="testingAction"
        class="com.yiibai.common.action.TestingAction" >
        <interceptor-ref name="timer"/>
        <interceptor-ref name="logger"/>
        <interceptor-ref name="defaultStack"/>
        <result name="success">pages/result.jsp</result>
    </action>
</package>

参考

Struts 2 拦截器文档

Struts2重写拦截器参数 - Struts2教程

在Struts2中，可以设置或通过普通的标签重写拦截器的参数。见下面的例子：

<package name="default" namespace="/" extends="struts-default">
   <action name="whateverAction"
    class="com.yiibai.common.action.WhateverAction" >
    <interceptor-ref name="workflow">
        <param name="excludeMethods">whateverMethod</param>
    </interceptor-ref>
    <result name="success">pages/whatever.jsp</result>
   </action>
</package>

然而，在上面的代码片段，动作类被声明为自己的拦截器， 它会导致继承“defaultStack”拦截器的直接丢失。

如果你想保持“defaultStack”拦截器，并覆盖工作流的excludeMethods参数呢？没问题，试试这个：

<package name="default" namespace="/" extends="struts-default">
   <action name="whateverAction"
    class="com.yiibai.common.action.WhateverAction" >
    <interceptor-ref name="defaultStack">
        <param name="workflow.excludeMethods">whateverMethod</param>
    </interceptor-ref>
    <result name="success">pages/whatever.jsp</result>
   </action>
</package>

上面的代码片段将保持“defaultStack”拦截并覆盖“workflow”参数。

参考

Struts2拦截器文档

Struts2流程拦截器文档

Struts2拦截器栈的例子 - Struts2教程

很多时候，相同的一组拦截器可以适用于不同的动作类，例如，

<package name="default" namespace="/" extends="struts-default">

    <action name="checkInAction"
    class="com.yiibai.common.action.CheckInAction" >
    <interceptor-ref name="timer"/>
        <interceptor-ref name="logger"/>
    <interceptor-ref name="defaultStack" />
    <result name="success">/pages/checkIn.jsp</result>
    </action>

    <action name="checkOutAction"
    class="com.yiibai.common.action.CheckOutAction" >
    <interceptor-ref name="timer"/>
        <interceptor-ref name="logger"/>
    <interceptor-ref name="defaultStack" />
    <result name="success">/pages/checkOut.jsp</result>
    </action>

</package>

在上述情况下，它有许多重复工作以及不能重复使用。

幸运的是，在Struts 2自带的拦截器栈，使开发人员建立一组拦截到一个单元名为“栈名字”， 和可以通过“栈名字”引用操作它。

最佳做法建议组合相同的一组拦截器到一个拦截器栈摆脱重复的工作，并增加了项目的可重用性。

<package name="default" namespace="/" extends="struts-default">

     <interceptors>
           <interceptor-stack name="defaultStackWithLog">
             <interceptor-ref name="timer"/>
             <interceptor-ref name="logger"/>
         <interceptor-ref name="defaultStack" />
        </interceptor-stack>
    </interceptors>

    <action name="checkInAction"
    class="com.yiibai.common.action.CheckInAction" >
    <interceptor-ref name="defaultStackWithLog"/>
    <result name="success">/pages/checkIn.jsp</result>
    </action>

    <action name="checkOutAction"
    class="com.yiibai.common.action.CheckOutAction" >
    <interceptor-ref name="defaultStackWithLog"/>
    <result name="success">/pages/checkOut.jsp</result>
    </action>

</package>

在上面的例子更新，声明一个拦截器栈，命名为“defaultStackWithLog”其中包括“timer“, “logger” 和 “defaultStack” 拦截器，并且它通过“interceptor-ref”元素引用一个正常的拦截器。

参考

Struts2拦截器文档

Struts2 execAndWait拦截器例子 - Struts2教程

在Struts2中附带一个名为“execAndWait”一个非常有趣的“执行和等待”拦截器，这是一个非常方便的拦截器长时间运行操作在后台，显示用户的自定义的等待页面。在本教程中，它显示了一个完整的使用 Struts2 execAndWait 拦截器的例子。

1. 动作

一个普通的动作类，有一个长时间运行进程，证明了execAndWait效果。

LongProcessAction.java

package com.yiibai.common.action;

import com.opensymphony.xwork2.ActionSupport;

public class LongProcessAction extends ActionSupport{

    public String execute() throws Exception {

        //it should be delay few seconds,
        //unless you have a super powerful computer.
        for(int i =0; i<1000000; i++){
            System.out.println(i);
        }
        return SUCCESS;

    }
}

2. JSP页面

创建两个页面：

wait.jsp - 显示给用户，长时间运行的进程。

success.jsp - 显示给用户的过程完成之后。

HTML meta refresh 记得把元刷新的等待页面顶部; 否则，该网页将不重定向到成功页面，即使该过程完成。

在这个wait.jsp，元刷新设置在每5秒网页重新加载，如果该过程完成后，将重定向到 success.jsp, 否则留在同一个页面。

wait.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts 2 execAndWait 示例</title>
<meta http-equiv="refresh" content="5;url=<s:url includeParams="all" />"/>
</head>

<body>
<h1>Struts 2 execAndWait 示例</h1>

<h3>Please wait while we process your request...</h3>

</body>
</html>

success.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts 2 execAndWait 示例</title>
</head>

<body>
<h1>Struts 2 execAndWait 示例</h1>

<h3>Done</h3>

</body>
</html>

3. 执行和等待拦截器

链接动作类并声明“execAndWait”拦截器。execAndWait 参数

delay (optional) : 以毫秒为单位初始延迟显示在wait.jsp。默认是没有延迟的。

delaySleepInterval (optional) : 时间间隔是以毫秒为单位来检查后台进程是否已经完成，默认值是100毫秒。

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="default" namespace="/" extends="struts-default">
        <action name="longProcessAction"
            class="com.yiibai.common.action.LongProcessAction" >

            <interceptor-ref name="execAndWait">
                <param name="delay">1000</param>
                <param name="delaySleepInterval">500</param>
            </interceptor-ref>

            <result name="wait">/pages/wait.jsp</result>
            <result name="success">/pages/success.jsp</result>
        </action>

    </package>
</struts>

在这种情况下，将延迟1秒显示至wait.jsp，并检查后台进程是否在每500毫秒完成。即使这个过程完成后，它仍然需要等待 wait.jsp 元刷新来触发页面重载。

4. 示例

访问网址： http://localhost:8080/struts2execandwait/longProcessAction.action

延时1秒，显示在 wait.jsp 。Struts 2 ExecAndWait interceptor example

当该过程完成时，自动显示在 success.jsp。

代码下载：http://pan.baidu.com/s/1o62BHGY

参考

Struts2 execAndWait拦截器文档

HTML Meta Refresh

Struts2文件上传例子 - Struts2教程

在Struts2， <s:file> 标签用于创建一个HTML文件上传组件，允许用户从本地磁盘选择文件，并将其上传到服务器。在本教程中，您将创建与文件上传组件JSP页面，设置最大大小和允许上传文件的内容类型，并显示上传文件的详细信息。

这里创建一个Web工程：strut2uploadfile，来演示在多个复选框如何设置的默认值，整个项目的结构如下图所示：

1. 动作类

Action类的文件上传，声明“File”变量来存储用户上传的文件，两个字符串变量以存储文件名和内容类型。“文件上传拦截器”通过设置“X”的ContentType()，并设置“X”FileName()会自动注入上传的文件细节，确保方法名拼写正确。

P.S X是以存储上传的文件中的变量。

文件上传功能是依赖于“文件上传拦截器”，确保将其纳入行动的堆栈。幸运的是，默认的堆栈已经包含了“文件上传拦截器”。

FileUploadAction.java

package com.yiibai.common.action;

import java.io.File;

import com.opensymphony.xwork2.ActionSupport;

public class FileUploadAction extends ActionSupport{

    private File fileUpload;
    private String fileUploadContentType;
    private String fileUploadFileName;

    public String getFileUploadContentType() {
        return fileUploadContentType;
    }

    public void setFileUploadContentType(String fileUploadContentType) {
        this.fileUploadContentType = fileUploadContentType;
    }

    public String getFileUploadFileName() {
        return fileUploadFileName;
    }

    public void setFileUploadFileName(String fileUploadFileName) {
        this.fileUploadFileName = fileUploadFileName;
    }

    public File getFileUpload() {
        return fileUpload;
    }

    public void setFileUpload(File fileUpload) {
        this.fileUpload = fileUpload;
    }

    public String execute() throws Exception{

        return SUCCESS;

    }

    public String display() {
        return NONE;
    }

}

2. 结果页面

使用<s:file>标签来渲染一个文件上传组件，并设置表单的enctype类型为：“multipart/form-data”。

fileupload.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<s:head />
</head>

<body>
<h1>Struts 2 <s:file> file upload example</h1>

<s:form action="resultAction" namespace="/"
method="POST" enctype="multipart/form-data">

<s:file name="fileUpload" label="Select a File to upload" size="40" />

<s:submit value="submit" name="submit" />

</s:form>

</body>
</html>

result.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>

<body>
<h1>Struts 2 <s:file> file upload example</h1>

<div><div class="ads-in-post hide_if_width_less_800">
<script async src="../Images///pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- 728x90 - After2ndH4 -->
<ins class="adsbygoogle hide_if_width_less_800"
     style="display:inline-block;width:728px;height:90px"
     data-ad-client="ca-pub-2836379775501347"
     data-ad-slot="3642936086"
     data-ad-region="yiibairegion"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div></div><h2>
   File Name : <s:property value="fileUploadFileName"/>
</h2>

<h2>
   Content Type : <s:property value="fileUploadContentType"/>
</h2>

<h2>
   File : <s:property value="fileUpload"/>
</h2>

</body>
</html>

3. 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="default" namespace="/" extends="struts-default">

    <action name="fileUploadAction"
        class="com.yiibai.common.action.FileUploadAction" method="display">
        <result name="none">/pages/fileupload.jsp</result>
    </action>

    <action name="resultAction" class="com.yiibai.common.action.FileUploadAction">
        <interceptor-ref name="exception"/>
            <interceptor-ref name="i18n"/>
            <interceptor-ref name="fileUpload">
               <param name="allowedTypes">text/plain</param>
               <param name="maximumSize">10240</param>
          </interceptor-ref>
            <interceptor-ref name="params">
                <param name="excludeParams">dojo\..*,^struts\..*</param>
            </interceptor-ref>
            <interceptor-ref name="validation">
                <param name="excludeMethods">input,back,cancel,browse</param>
            </interceptor-ref>
            <interceptor-ref name="workflow">
                <param name="excludeMethods">input,back,cancel,browse</param>
            </interceptor-ref>

        <result name="success">/pages/result.jsp</result>
        <result name="input">/pages/fileupload.jsp</result>

    </action>
   </package>
</struts>

文件大小限制在这个例子中，您将通过“文件上传拦截”上传文件大小的限制, 该值以字节为单位计数。在本实例中，上载文件的最大尺寸是10KB。

注：上传文件的默认最大文件大小为2MB

文件类型可以通过设置“文件上传拦截器”允许的文件类型。在这种情况下，上传文件只接受“text/plain”的类型。

在Struts2中，有好几种方面做到这一点，查看Struts2的文件上传文档。

4. 示例

http://localhost:8080/Struts2Example/fileUploadAction.action

错误信息提示，如果您上传一个文件，该文件超过10KB，或者未选文本文件。

上传名为“yiibai.com.txt”的文本文件, 文件大小 : 5kb.

上传的文件将被视为一个临时文件，具有长的随机文件名，如：upload376584a7_129811223798000_00000010.tmp. 请确保这个临时文件复制到其他地方。 阅读文件实用文档复制文件。

参考

Struts 2 文件文档

http://struts.apache.org/2.0.14/docs/file-upload.html

http://struts.apache.org/2.0.14/docs/how-do-we-upload-files.html

http://commons.apache.org/io/api-1.4/org/apache/commons/io/FileUtils.html

下载代码 – http://pan.baidu.com/s/1eQDH07S

Struts2资源包使用示例 - Struts2教程

要使用资源包从属性文件检索消息，必须了解Struts2的资源包搜索顺序：

资源包搜索顺序

资源包中搜索按以下顺序：

ActionClass.properties

Interface.properties

BaseClass.properties

ModelDriven’s model

package.properties

搜索国际化消息键的层次结构本身

全局资源属性

请参阅Struts2资源包文档详细解释。

在实践中，是不可能组织属性的文件的顺序。所以，只要了解几个常用的搜索顺序应该是足够了： package.properties 和 global resource properties。参见下图：

如果com.yiibai.user.action.LoginAction想通过资源包获得消息，它将搜索

com.yiibai.user.action.LoginAction.properties (找到，退出，否则下一个)

com.yiibai.user.action.package.properties (找到，退出，否则下一个)

com.yiibai.user.package.properties (找到，退出，否则下一个) …一路不断在每个父目录的根目录查找package.properties

查找全局资源属性，如果将其配置在应用程序中。

明白这搜索顺序可以给你更多的信心来决定正确的文件夹的属性文件。

获取资源包

下面是访问该资源包的几个例子：

P.S ‘username.required‘ 和 ‘username‘ 在一个属性文件中的键。

1. 动作类

在Action类，可以扩展了ActionSupport和通过getText(‘key’) 函数获取资源包。

...
public class LoginAction extends ActionSupport{
    ...
    public void validate(){
        if("".equals(getUsername())){
            addFieldError("username", getText("username.required"));
        }
    }
}

2. <s:property>标签

在属性标记，使用 getText(‘key’).

<s:property value="getText('username')" />

3. <s:text>标签

在text标签，设置“name”属性的键。

<s:text name="username" />

4. Key属性

UI组件的主要属性有特殊的功能，查看这个key属性例子详细信息。

<s:textfield key="username" />

5. I18n标签

国际化i18n 标签可以从“name”属性声明指定资源包得到消息。在这个例子中，它要求从com/yiibai/user/package.properties文件中以获得 “username” 的消息。

<s:i18n name="com.yiibai.user.package" >
     <s:text name="username" />
</s:i18n>

访问 URL http://localhost:8080/struts2resourcebundle/user/login.action，输出以下结果：

下载完整的项目实践(struts2resourcebundle) – http://pan.baidu.com/s/1dD2UQ2l

Struts2本地化和国际化 - Struts2教程

Struts 2的国际化(I18N)和本地化(i10n)或多语言的例子，来说明如何使用资源包来显示不同语言的消息。在这个例子中，您将创建一个简单的登录屏幕，通过Struts 2的UI组件显示来自资源包的消息， 并更改基于所选的语言选项的语言环境。

1. 工程结构

项目结构，如下图片显示：

2. Properties文件

确保属性文件命名为国家指定的代码。在一些“非欧洲”或“非英语”之类的字符，应该始终编码的内容 native2ascii属性

global.properties

#Global messages
global.username = Username
global.password = Password
global.submit = Submit

global_zh_CN.properties

#Global messages
global.username = \u7528\u6237\u540d
global.password = \u5bc6\u7801
global.submit=\u63d0\u4ea4

global_fr.properties

#Global messages
global.username = Nom d'utilisateur
global.password = Mot de passe
global.submit = Soumettre

global_de.properties

#Global messages
global.username = Benutzername
global.password = Kennwort
global.submit = Einreichen

请仔细阅读Struts2资源包的例子来了解Struts 2的自动搜索属性文件。

3. 动作类

两个动作类，LocaleAction基本上是什么都不做， 而 LoginAction 会做一个简单的验证和通过gettext()显示来自资源包错误信息。

LocaleAction.java

package com.yiibai.common.action;

import com.opensymphony.xwork2.ActionSupport;

public class LocaleAction extends ActionSupport{

    //business logic
    public String execute() {
        return "SUCCESS";
    }
}

LoginAction.java

package com.yiibai.user.action;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport{

    private String username;
    private String password;

    //...getter and setter methods

    //business logic
    public String execute() {
        return "SUCCESS";
    }

    //simple validation
    public void validate(){
        if("".equals(getUsername())){
            addFieldError("username", getText("username.required"));
        }
        if("".equals(getPassword())){
            addFieldError("password", getText("password.required"));
        }
    }
}

4. 视图页面

一个登录页面带有一个文本框，密码和提交UI组件。为了支持Struts2 本地化，必须声明 <%@ page contentType=”text/html;charset=UTF-8″ %>在您的视图页面，否则能将有问题的“UTF-8数据”正确显示，尤其是中国汉字。阅读这篇文章，关于Struts2中国本土化问题。

login.jsp

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

<body>
<h1>Struts 2 localization example</h1>

<s:form action="validateUser" namespace="/user">

    <s:textfield key="global.username" name="username" />
    <s:password key="global.password" name="password"/>
    <s:submit key="global.submit" name="submit" />

</s:form>

<s:url id="localeEN" namespace="/" action="locale" >
   <s:param name="request_locale" >en</s:param>
</s:url>
<s:url id="localezhCN" namespace="/" action="locale" >
   <s:param name="request_locale" >zh_CN</s:param>
</s:url>
<s:url id="localeDE" namespace="/" action="locale" >
   <s:param name="request_locale" >de</s:param>
</s:url>
<s:url id="localeFR" namespace="/" action="locale" >
   <s:param name="request_locale" >fr</s:param>
</s:url>

<s:a href="%{localeEN}" >English</s:a>
<s:a href="%{localezhCN}" >Chinese</s:a>
<s:a href="%{localeDE}" >German</s:a>
<s:a href="%{localeFR}" >France</s:a>

</body>
</html>

要更改默认的语言环境，只需要声明“request_locale”参数，设置你喜欢的语言代码，并传递给一个Action类。在 Struts2中，com.opensymphony.xwork2.interceptor.I18nInterceptor 拦截器, 在 struts-default.xml中声明将拦截Action类，并相应地处理语言环境。

5. 显示资源包的消息？

在Struts2，有很多的方式来显示所选择的语言或语言环境的资源包的信息。有关示例，

<s:textfield key="global.username" name="username" />
<s:text name="global.username" />
<s:property value="getText('global.username')" />
<s:text name="global.password" />

在Struts1，有一个标准的 bean:message 来显示资源包的消息。但是在Struts 2中，有这么多相当于显示资源包的消息(甚至内部的工作不同)方式，基本上，无论选择的是什么，在 Struts2 也将显示正确的资源包的消息。

6. struts.xml

Struts2 的配置文件，链接一起。

<?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.custom.i18n.resources" value="global" />
     <constant name="struts.devMode" value="true" />

    <package name="user" namespace="/user" extends="struts-default">
       <action name="login">
        <result>/pages/login.jsp</result>
       </action>
       <action name="validateUser" class="com.yiibai.user.action.LoginAction">
        <result name="SUCCESS">/pages/welcome.jsp</result>
        <result name="input">/pages/login.jsp</result>
       </action>
    </package>

    <package name="default" namespace="/" extends="struts-default">
       <action name="locale" class="com.yiibai.common.action.LocaleAction">
        <result name="SUCCESS">/user/pages/login.jsp</result>
       </action>
    </package>

</struts>

7. 示例

http://localhost:8080/i18nlocalization/user/login.action

http://localhost:8080/i18nlocalization/locale.action?request_locale=en

http://localhost:8080/i18nlocalization/locale.action?request_locale=zh_CN

http://localhost:8080/i18nlocalization/locale.action?request_locale=de

http://localhost:8080/i18nlocalization/locale.action?request_locale=fr

参考

http://struts.apache.org/2.1.8/docs/localization.html

http://www.yiibai.com/java/java-convert-chinese-character-to-unicode-with-native2ascii/

http://www.yiibai.com/struts2/struts-2-resource-bundle-example/

http://www.yiibai.com/struts/struts-internationalizing-or-localization-example/

代码下载 - http://pan.baidu.com/s/1jGCUaJ8

Struts2 key键属性示例 - Struts2教程

在Struts2，在UI组件的“key”属性来处理本地化的常用方法，也是编码UI标签的一个非常有效的方式。见下面两种情况：

1. Properties属性文件

属性文件包含一条消息。

global.properties

global.username = Username

2. 示例1

如果分配一个“key”属性到一个文本框。键(key)属性会从资源包中获取信息，并使其在默认XHTML text.tfl模板基础上渲染。

<s:form action="validateUser">
    <s:textfield key="global.username" />
</s:form>

现在它将会使用“global.username {left-side}”和 “Username {right-side}”，并匹配相应的XHTML text.tfl模板。

<td class="tdLabel">
   <label for="validateUser_{left-side}" class="label">{right-side}:</label>
</td>
<td>
   <input type="text" name="{left-side}" value="" id="validateUser_{left-side}"/>
</td>

最后的 HTML

<td class="tdLabel">
   <label for="validateUser_global_username" class="label">Username:</label>
</td>
<td>
   <input type="text" name="global.username" value="" id="validateUser_global_username"/>
</td>

键属性将使用 {left-side}作为文本框名称和ID; {right-side} 作为标签值。

3. 示例2

在某些情况下，可能需要显式声明的一个不同的名称的文本框。

<s:form action="validateUser">
    <s:textfield key="global.username" name="username"/>
</s:form>

现在key属性将使用“Username {right-side}”来只匹配的标签值， 文本框的名称和ID将明确覆盖。

最后的 HTML

<td class="tdLabel">
   <label for="validateUser_username" class="label">Username:</label>
</td>
<td>
   <input type="text" name="username" value="" id="validateUser_username"/>
</td>

key属性可以提高你的开发速度，使代码更有效，这是值得学习的。

Struts2中文本地化问题 - Struts2教程

一个 Struts2 的国际化定位的问题，用来显示中国汉字...

案例1：属性有特殊字符的文件

属性文件存储用户名，密码信息，并以中文字符提交。此属性文件以UTF-8格式创建的，但内容不使用 native2ascii 编码。

让我们试着通过一些UI标签，来显示中国汉字。查看页面声明为UTF-8格式的HTML元标记来显示。

...
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
...
<s:form action="validateUser">
    <s:textfield key="global.username" name="username"/>
    <s:password key="global.password" name="password"/>
    <s:submit key="global.submit" name="submit" />

    <div>Testing 1 : <s:property value="getText('global.username')" /></div>
    <div>Testing 2 : <s:text name="global.password" /></div></br/>
</s:form>
...
<s:url id="localezhCN" namespace="/" action="locale" >
   <s:param name="request_locale" >zh_CN</s:param>
</s:url>
...
<s:a href="%{localezhCN}" >Chinese</s:a>
...

结果

令人惊奇的是，以下三个UI标签都能够正确地显示中国消息

<s:textfield key="global.username" name="username"/>
<s:password key="global.password" name="password"/>
Testing 2 : <s:text name="global.password" />

然而，“s:submit” 和 “getText()” 却无法显示呢？据Java的国际化文档，要使用资源包正确显示特殊字符，则必须用 native2ascii 工具进行处理。

深入到 TextProvider.getText()的源代码后，它使用的资源 bundle.getString()来从资源包检索的消息，所以不正确的消息是合理的。但是，为什么“s:text“, “s:textfield” 和 “s:password” 能够正确显示了中文的消息，为什么“s:submit”会失败？在有太多的问题，让我们看看示例2...

案例2：有特殊字符的属性文件(编码)

这一次，属性文件使用native2ascii工具处理中国汉字的编码正确。

结果如下所示：

其结果是完全逆转，现在 “s:submit” 和 “getText()” 是能够正确地显示它，但其他UI组件失败。 这里是按预期方式工作的，因为在Struts 2推荐使用getText()，以显示国际化或本地化的消息。问题是，为什么“s:submit”会不同呢？

Struts2..哪里有问题？

这里有几个问题：

为什么 s:submit 有如此不同的效果？

对国际化应该是非常简单的，为什么在Struts 2有这种问题？ 或者我们误解了Struts2 国际化如何工作了？

为什么有这么多的方式来显示来自资源包的消息？为什么不直接组织成一个方法？ 在Struts1，只需使用“bean:message”，为什么Struts 2中它看起来很复杂？

Struts2的支持XML资源包？ 我们可能不太喜欢用native2ascii工具对数据进行编码为UTF-8格式，它使属性文件不可读。 Apache Wicket的在这个问题做了很好的工作，可能是在Struts 2中吸取教训。

那么，如何正确地在 Struts2 中显示中国汉字？

许多文章和教程使用以下方法来显示资源包的消息：

<s:text name="global.username"/>
<s:property value="getText('global.username')"/>

然而，这仅适用于英国或一些“英语状(欧洲)” 的字符，如法文，德文。但对中文或日文，这两种方法将返回完全不同的输出。真的不知道Struts2的本地化该怎么办了。

解决办法

问题是在HTML meta标签，

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>

在Struts1，上述meta标签必须正确显示UTF-8的数据，但这在 Struts2 是有问题的。

在Struts2，meta标签不起作用，我们应该把 <%@ page contentType=”text/html;charset=UTF-8″ %>标签放在页面的第一行。例如下面的代码片断：

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

结果显示如下：

所有的中文消息正确显示。

回答之前的问题

为什么 s:submit 有如此不同的效果？A: 暂无评论

对国际化应该是非常简单的，为什么在Struts 2有这种问题？ 或者我们误解了Struts2 国际化如何工作了？A: 确保把** <%@ page contentType=”text/html;charset=UTF-8″ %>” 放在页面的第一行。**

为什么有这么多的方式来显示来自资源包的消息？为什么不直接组织成一个方法？ 在Struts1，只需使用“bean:message”，为什么Struts 2中它看起来很复杂？A: s:text, key, getText(), name… , 所有的都能够正确地显示中文或UTF-8编码的数据，只要确保把正确的“字符集”放在视图页面中。**

Struts2的支持XML资源包？ 我们可能不太喜欢用native2ascii工具对数据进行编码为UTF-8格式，它使属性文件不可读。 Apache Wicket的在这个问题做了很好的工作，可能是在Struts 2中吸取教训。A:希望在Struts2的下一版本可以支持在XML资源包。

那么，如何正确地在 Struts2 中显示中国汉字？A: 看看上页的解决办法

参考

http://www.yiibai.com/java/java-convert-chinese-character-to-unicode-with-native2ascii.html

http://forums.sun.com/thread.jspa?threadID=5185040

http://www.coderanch.com/t/452139/Struts/applicationresources-properties-utf-characters#2013557

http://struts.apache.org/2.1.8/docs/localization.html

http://hxzon00.blog.163.com/blog/static/10489241620088121449163/

下载代码(globalresource) – http://pan.baidu.com/s/1mgzt3dQ

Struts2+Spring集成实例 - Struts2教程

在本教程中，我们来学习Struts2和Spring的集成。

1. 工程结构

下面的图是本教程的项目文件夹结构。

2. Spring监听器

配置Spring监听器 “org.springframework.web.context.ContextLoaderListener” 到 web.xml 文件中。

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Struts 2 Web Application</display-name>

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

  <listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>

</web-app>

3. 注册Spring Bean

注册所有的Spring Beans 配置在 applicationContext.xml 文件中, Spring监听器会自动找到这个 XML 文件。

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="userBo" class="com.yiibai.user.bo.impl.UserBoImpl" />

    <bean id="userSpringAction" class="com.yiibai.user.action.UserSpringAction">
        <property name="userBo" ref="userBo" />
    </bean>

</beans>

UserBo.java

package com.yiibai.user.bo;

public interface UserBo{

    public void printUser();

}

UserBoImpl.java

package com.yiibai.user.bo.impl;

import com.yiibai.user.bo.UserBo;

public class UserBoImpl implements UserBo{

    public void printUser(){
        System.out.println("printUser() is executed...");
    }

}

UserSpringAction.java

package com.yiibai.user.action;

import com.yiibai.user.bo.UserBo;

public class UserSpringAction{

    //DI via Spring
    UserBo userBo;

    public UserBo getUserBo() {
        return userBo;
    }

    public void setUserBo(UserBo userBo) {
        this.userBo = userBo;
    }

    public String execute() throws Exception {

        userBo.printUser();
        return "success";

    }
}

4. 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="default" namespace="/" extends="struts-default">

        <action name="userAction"
            class="com.yiibai.user.action.UserAction" >
            <result name="success">pages/user.jsp</result>
        </action>

        <action name="userSpringAction"
            class="userSpringAction" >
            <result name="success">pages/user.jsp</result>
        </action>

    </package>

</struts>

5. 示例

现在，所有的Struts2和Spring的集成工作已经完成，现在看到下面的用例来访问 Spring 的 “userBo” Bean。

用例 1 : 让 Spring 充当 Struts2的Action类，并访问Spring的Bean。

用例 2 : 在Struts2的Action类中访问Spring的Bean。

用例1

在这个例子中，userSpringAction充当Struts2的Action类，也可以使用普通Spring的方式注入Spring的userBo。

//struts.xml
<action name="userSpringAction"
    class="userSpringAction" >
    <result name="success">pages/user.jsp</result>
</action>

//applicationContext.xml
<bean id="userSpringAction" class="com.yiibai.user.action.UserSpringAction">
    <property name="userBo" ref="userBo" />
</bean>

要访问此操作，请使用网址： http://localhost:8080/struts2spring/userSpringAction.action

用例 2

默认情况下，Spring监听器启用 “通过匹配bean的名字自动装配“。 因此，它会通过setUserBo自动传递Spring “userBo” Bean 到UserAction。请参阅下面的Struts2动作：

Spring的自动装配功能可以修改为 name(默认), type, auto 或 constructor, 可能需要参考 Struts2的Spring插件文档。

UserAction.java

package com.yiibai.user.action;

import com.yiibai.user.bo.UserBo;
import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport{

    //DI via Spring
    UserBo userBo;

    public UserBo getUserBo() {
        return userBo;
    }

    public void setUserBo(UserBo userBo) {
        this.userBo = userBo;
    }

    public String execute() throws Exception {

        userBo.printUser();
        return SUCCESS;

    }
}

要访问此操作，请使用网址： http://localhost:8080/struts2spring/userAction.action

WebApplicationContextUtils 另外，也可以使用Spring 通用 WebApplicationContextUtils 类来直接获得Spring的bean。

package com.yiibai.user.action;

import org.apache.struts2.ServletActionContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.yiibai.user.bo.UserBo;
import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport{

    public String execute() throws Exception {

        WebApplicationContext context =
            WebApplicationContextUtils.getRequiredWebApplicationContext(
                                    ServletActionContext.getServletContext()
                        );

        UserBo userBo1 = (UserBo)context.getBean("userBo");
        userBo1.printUser();

        return SUCCESS;

    }
}

这是一个又长又臭的文章(包教不包会)，请下载完整的项目并按照源代码去一步步实现。

参考

Struts2 Spring 插件文档

Struts + Spring 集成实例

代码下载 - http://pan.baidu.com/s/1dDhqQ5b

Struts2+Hibernate使用Full Hibernate Plugin集成 - Struts2教程

在上篇 Struts2 + Hibernate集成 实例中, 它使用 servlet 上下文监听 Hibernate 的 Session，而且把Struts2和Hibernate框架集成。

但是，总有一些东西要提高。在本教程中，我们将展示如何整合Struts2+Hibernate，并使用Struts2一个名为“Full Hibernate Plugin“的插件。

见下面的集成步骤：

把 “Full Hibernate Plugin” jar 放入到工程类路径。

使用 “@SessionTarget” 注释来注入到 Hibernate session; 当“@TransactionTarget” 注释注入到Hibernate 事务。

在 struts.xml, 让包扩展 “hibernate-default“，而不是默认的堆栈。

看看下面的关系：

Struts 2 <-- (Full Hibernate Plugin) ---> Hibernate <-----> Database

注，本教程是从以前的 Struts2 + Hibernate集成 实例(servlet context listener)更新版本。因此，JSP 和 Hibernate 配置基本相同，只是整合的部分是有点不同，尝试比较既能发现不同。

1. 工程结构

在节教程，我们创建一个工程名为 full-hibernate 的web工程。看看这个项目文件夹的完整结构。

2. MySQL创建表脚本

Customer表结构

CREATE TABLE `customer` (
  `customer_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  `address` varchar(255) NOT NULL,
  `create_date` datetime NOT NULL,
  PRIMARY KEY (`customer_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

3. Hibernate相关配置

所有 Hibernate 的模型和配置的东西。

Customer.java – 为customer 表创建一个类。

package com.yiibai.customer.model;

import java.util.Date;

public class Customer implements java.io.Serializable {

    private Long customerId;
    private String name;
    private String address;
    private Date createdDate;

    //getter and setter methods
}

Customer.hbm.xml – Hibernate 的 customer 表映射。

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 20 Julai 2010 11:40:18 AM by Hibernate Tools 3.2.5.Beta -->
<hibernate-mapping>
    <class name="com.yiibai.customer.model.Customer"
        table="customer" catalog="yiibai">
        <id name="customerId" type="java.lang.Long">
            <column name="CUSTOMER_ID" />
            <generator class="identity" />
        </id>
        <property name="name" type="string">
            <column name="NAME" length="45" not-null="true" />
        </property>
        <property name="address" type="string">
            <column name="ADDRESS" not-null="true" />
        </property>
        <property name="createdDate" type="timestamp">
            <column name="CREATED_DATE" length="19" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

文件: hibernate.cfg.xml, Hibernate 数据库配置

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
    <property name="hibernate.connection.password">password</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/yiibai</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="show_sql">true</property>
    <property name="format_sql">true</property>
    <property name="use_sql_comments">false</property>
    <mapping resource="com/yiibai/customer/hibernate/Customer.hbm.xml" />
  </session-factory>
</hibernate-configuration>

5. DAO

实现DAO设计模式执行数据库操作。在 CustomerDAOImpl 类, 声明Hibernate会话和事务为类成员。在Struts 2的项目初始化， “Full Hibernate Plugin” 使用 @SessionTarget 和 @TransactionTarget 分别标注将注入相应的 Hibernate 会话和事务成为类成员。

CustomerDAO.java

package com.yiibai.customer.dao;

import java.util.List;

import com.yiibai.customer.model.Customer;

public interface CustomerDAO{

    void addCustomer(Customer customer);

    List<Customer> listCustomer();

}

CustomerDAOImpl.java

package com.yiibai.customer.dao.impl;

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;
import com.yiibai.customer.dao.CustomerDAO;
import com.yiibai.customer.model.Customer;

public class CustomerDAOImpl implements CustomerDAO{

    @SessionTarget
    Session session;

    @TransactionTarget
    Transaction transaction;

    //add the customer
    public void addCustomer(Customer customer){

        session.save(customer);

    }

    //return all the customers in list
    public List<Customer> listCustomer(){

        return session.createQuery("from Customer").list();

    }

}

6. Action

在Action类，调用DAO类来执行数据库操作。

CustomerAction.java

package com.yiibai.customer.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.yiibai.customer.dao.CustomerDAO;
import com.yiibai.customer.dao.impl.CustomerDAOImpl;
import com.yiibai.customer.model.Customer;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class CustomerAction extends ActionSupport
    implements ModelDriven{

    Customer customer = new Customer();
    List<Customer> customerList = new ArrayList<Customer>();
    CustomerDAO customerDAO = new CustomerDAOImpl();

    public String execute() throws Exception {
        return SUCCESS;
    }

    public Object getModel() {
        return customer;
    }

    public List<Customer> getCustomerList() {
        return customerList;
    }

    public void setCustomerList(List<Customer> customerList) {
        this.customerList = customerList;
    }

    //save customer
    public String addCustomer() throws Exception{

        //save it
        customer.setCreatedDate(new Date());
        customerDAO.addCustomer(customer);

        //reload the customer list
        customerList = null;
        customerList = customerDAO.listCustomer();

        return SUCCESS;

    }

    //list all customers
    public String listCustomer() throws Exception{

        customerList = customerDAO.listCustomer();

        return SUCCESS;

    }

}

7. JSP 页面

JSP页面添加并列出客户。

customer.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
</head>

<body>
<h1>Struts 2 Full Hibernate Plugin example</h1>

<h2>Add Customer</h2>
<s:form action="addCustomerAction" >
  <s:textfield name="name" label="Name" value="" />
  <s:textarea name="address" label="Address" value="" cols="50" rows="5" />
  <s:submit />
</s:form>

<h2>All Customers</h2>

<s:if test="customerList.size() > 0">
<table border="1px" cellpadding="8px">
    <tr>
        <th>Customer Id</th>
        <th>Name</th>
        <th>Address</th>
        <th>Created Date</th>
    </tr>
    <s:iterator value="customerList" status="userStatus">
        <tr>
            <td><s:property value="customerId" /></td>
            <td><s:property value="name" /></td>
            <td><s:property value="address" /></td>
            <td><s:date name="createdDate" format="dd/MM/yyyy" /></td>
        </tr>
    </s:iterator>
</table>
</s:if>
<br/>
<br/>

</body>
</html>

8. struts.xml

链接所有〜让包扩展 “hibernate-default” 来代替 “struts-default“.

<?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="default" namespace="/" extends="hibernate-default">

    <action name="addCustomerAction"
    class="com.yiibai.customer.action.CustomerAction" method="addCustomer" >
       <result name="success">pages/customer.jsp</result>
    </action>

    <action name="listCustomerAction"
    class="com.yiibai.customer.action.CustomerAction" method="listCustomer" >
        <result name="success">pages/customer.jsp</result>
    </action>

</package>
</struts>

9. 实例

访问以下网址 : http://localhost:8080/full-hibernate/addCustomerAction.action

参考

Struts2 Full Hibernate插件文档

Struts2 + Hibernate集成实例

安装库到Maven本地资源库

下载代码

下载所有源代码 – http://pan.baidu.com/s/1o6tjSam

Struts2+Hibernate集成实例 - Struts2教程

在 Struts2 中，没有官方的插件集成Hibernate框架。但是，可以通过以下步骤解决方法：

注册一个自定义的 ServletContextListener

在 ServletContextListener 类, 初始化Hibernate会话，并将其存储到servlet上下文。

在动作类, 可以通过servlet上下文的Hibernate会话，并执行任务正常的Hibernate操作。

请参阅它们的关系：

Struts 2 <-- (Servlet Context) ---> Hibernate <-----> Database

在本教程中，在Struts中2开发我们显示了一个简单的客户模块(添加和列表功能)，并使用 Hibernate 进行数据库操作。使用上述部分机制集成(存储和检索在servlet上下文Hibernate的Session)。

1. 工程目录结构

来看看这个完整的项目文件夹结构。

2. MySQL表结构脚本

创建一个客户(customer)表。下面是SQL表脚本。

CREATE TABLE `customer` (
  `customer_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL,
  `address` varchar(255) NOT NULL,
  `create_date` datetime NOT NULL,
  PRIMARY KEY (`customer_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

4. Hibernate 相关配置

Hibernate的模型和配置的东西。

Customer.java – 创建客户表对应的一个类。

package com.yiibai.customer.model;

import java.util.Date;

public class Customer implements java.io.Serializable {

    private Long customerId;
    private String name;
    private String address;
    private Date createdDate;

    //getter and setter methods
}

Customer.hbm.xml – Hibernate映射文件客户表。

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.yiibai.customer.model.Customer"
    table="customer" catalog="yiibai">

        <id name="customerId" type="java.lang.Long">
            <column name="CUSTOMER_ID" />
            <generator class="identity" />
        </id>
        <property name="name" type="string">
            <column name="NAME" length="45" not-null="true" />
        </property>
        <property name="address" type="string">
            <column name="ADDRESS" not-null="true" />
        </property>
        <property name="createdDate" type="timestamp">
            <column name="CREATED_DATE" length="19" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

hibernate.cfg.xml – Hibernate数据库配置文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
    <property name="hibernate.connection.password">password</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/yiibai</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="show_sql">true</property>
    <property name="format_sql">true</property>
    <property name="use_sql_comments">false</property>
    <mapping resource="com/yiibai/customer/hibernate/Customer.hbm.xml" />
  </session-factory>
</hibernate-configuration>

5. Hibernate ServletContextListener

创建一个类 ServletContextListener, 并初始化Hibernate会话，并将其存储到servlet上下文。

HibernateListener .java

package com.yiibai.listener;

import java.net.URL;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateListener implements ServletContextListener{

    private Configuration config;
    private SessionFactory factory;
    private String path = "/hibernate.cfg.xml";
    private static Class clazz = HibernateListener.class;

    public static final String KEY_NAME = clazz.getName();

    public void contextDestroyed(ServletContextEvent event) {
      //
    }

    public void contextInitialized(ServletContextEvent event) {

     try {
            URL url = HibernateListener.class.getResource(path);
            config = new Configuration().configure(url);
            factory = config.buildSessionFactory();

            //save the Hibernate session factory into serlvet context
            event.getServletContext().setAttribute(KEY_NAME, factory);
      } catch (Exception e) {
             System.out.println(e.getMessage());
       }
    }
}

在 web.xml 文件中注册监听器。

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Struts 2 Web Application</display-name>

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

  <listener>
    <listener-class>
      com.yiibai.listener.HibernateListener
    </listener-class>
  </listener>

</web-app>

6. Action

在动作类, 可以通过servlet上下文的Hibernate会话和执行正常的Hibernate任务。

CustomerAction.java

package com.yiibai.customer.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.struts2.ServletActionContext;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.yiibai.customer.model.Customer;
import com.yiibai.listener.HibernateListener;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class CustomerAction extends ActionSupport
    implements ModelDriven{

    Customer customer = new Customer();
    List<Customer> customerList = new ArrayList<Customer>();

    public String execute() throws Exception {
        return SUCCESS;
    }

    public Object getModel() {
        return customer;
    }

    public List<Customer> getCustomerList() {
        return customerList;
    }

    public void setCustomerList(List<Customer> customerList) {
        this.customerList = customerList;
    }

    //save customer
    public String addCustomer() throws Exception{

        //get hibernate session from the servlet context
        SessionFactory sessionFactory =
             (SessionFactory) ServletActionContext.getServletContext()
                     .getAttribute(HibernateListener.KEY_NAME);

        Session session = sessionFactory.openSession();

        //save it
        customer.setCreatedDate(new Date());

        session.beginTransaction();
        session.save(customer);
        session.getTransaction().commit();

        //reload the customer list
        customerList = null;
        customerList = session.createQuery("from Customer").list();

        return SUCCESS;

    }

    //list all customers
    public String listCustomer() throws Exception{

        //get hibernate session from the servlet context
        SessionFactory sessionFactory =
             (SessionFactory) ServletActionContext.getServletContext()
                     .getAttribute(HibernateListener.KEY_NAME);

        Session session = sessionFactory.openSession();

        customerList = session.createQuery("from Customer").list();

        return SUCCESS;

    }
}

7. JSP 页面

JSP页面用来添加和列出的客户。

customer.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
</head>

<body>
<h1>Struts 2 + Hibernate integration example</h1>

<h2>Add Customer</h2>
<s:form action="addCustomerAction" >
  <s:textfield name="name" label="Name" value="" />
  <s:textarea name="address" label="Address" value="" cols="50" rows="5" />
  <s:submit />
</s:form>

<h2>All Customers</h2>

<s:if test="customerList.size() > 0">
<table border="1px" cellpadding="8px">
    <tr>
        <th>Customer Id</th>
        <th>Name</th>
        <th>Address</th>
        <th>Created Date</th>
    </tr>
    <s:iterator value="customerList" status="userStatus">
        <tr>
            <td><s:property value="customerId" /></td>
            <td><s:property value="name" /></td>
            <td><s:property value="address" /></td>
            <td><s:date name="createdDate" format="dd/MM/yyyy" /></td>
        </tr>
    </s:iterator>
</table>
</s:if>
<br/>
<br/>

</body>
</html>

8. 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="default" namespace="/" extends="struts-default">

    <action name="addCustomerAction"
    class="com.yiibai.customer.action.CustomerAction" method="addCustomer" >
       <result name="success">pages/customer.jsp</result>
    </action>

    <action name="listCustomerAction"
    class="com.yiibai.customer.action.CustomerAction" method="listCustomer" >
        <result name="success">pages/customer.jsp</result>
    </action>

  </package>
</struts>

9. 实例测试执行

访问客户模块：http://localhost:8080/struts2hibernate/listCustomerAction.action

在名称和地址字段填写，点击提交按钮，插入的客户的详细信息会马上列出结果。

参考

Struts2 + Hibernate使用“Full Hibernate Plugin"集成

ServletContextListener 文档

Struts + Hibernate集成实例

代码下载 - http://pan.baidu.com/s/1hqhQJ7A

Struts2+Spring+Hibernate集成实例 - Struts2教程

在本教程中，它显示的集成 “Struts2 + Spring + Hibernate“，请务必检查以下之前继续学习教程。

Struts2 + Hibernate集成实例

Struts2 + Spring 集成实例

参见集成步骤总结：

获取所有的依赖库(很多)。

注册 Spring 的 ContextLoaderListener 来整合 Struts2 和 Spring。

使用 Spring 的 LocalSessionFactoryBean 来集成 Spring 和 Hibernate。

完成所有连接。

请参阅它们之的关系：

Struts 2 <-- (ContextLoaderListener) --> Spring <-- (LocalSessionFactoryBean) --> Hibernate

这将是一个很长的教程，相关解释并不是很多，请务必阅读上述2篇文章的详细情况说明以方面学习。

这将要创建一个客户页面，以添加客户和列表的自定义函数。前端使用Struts2显示，Spring作为依赖注入引擎，而 Hibernate 用来执行数据库操作。让我们开始...

1. 工程文件夹结构

在本章中，我们创建一个 ssh 的web工程，工程的目录结构如下图所示：

2. MySQL表结构结构

客户(customer)表脚本。

DROP TABLE IF EXISTS `yiibai`.`customer`;
CREATE TABLE  `yiibai`.`customer` (
  `CUSTOMER_ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `NAME` varchar(45) NOT NULL,
  `ADDRESS` varchar(255) NOT NULL,
  `CREATED_DATE` datetime NOT NULL,
  PRIMARY KEY (`CUSTOMER_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

3. Hibernate相关配置

只有模型和映射文件是必需的，因为这里要用Spring处理Hibernate配置。

Customer.java – 创建客户表对应的一个类。

package com.yiibai.customer.model;

import java.util.Date;

public class Customer implements java.io.Serializable {

    private Long customerId;
    private String name;
    private String address;
    private Date createdDate;

    //getter and setter methods
}

Customer.hbm.xml – Hibernate的客户映射文件。

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 20 Julai 2010 11:40:18 AM by Hibernate Tools 3.2.5.Beta -->
<hibernate-mapping>
    <class name="com.yiibai.customer.model.Customer"
        table="customer" catalog="yiibai">
        <id name="customerId" type="java.lang.Long">
            <column name="customer_id" />
            <generator class="identity" />
        </id>
        <property name="name" type="string">
            <column name="name" length="45" not-null="true" />
        </property>
        <property name="address" type="string">
            <column name="address" not-null="true" />
        </property>
        <property name="createdDate" type="timestamp">
            <column name="create_date" length="19" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

5. Struts2相关

实现了 Bo 和 DAO 设计模式。所有Bo和DAO将由Spring Spring bean配置文件注入。在DAO中，让它扩展Spring的HibernateDaoSupport来集成 Spring 和 Hibernate。

CustomerBo.java

package com.yiibai.customer.bo;

import java.util.List;
import com.yiibai.customer.model.Customer;

public interface CustomerBo{

    void addCustomer(Customer customer);
    List<Customer> listCustomer();

}

CustomerBoImpl.java

package com.yiibai.customer.bo.impl;

import java.util.List;
import com.yiibai.customer.bo.CustomerBo;
import com.yiibai.customer.dao.CustomerDAO;
import com.yiibai.customer.model.Customer;

public class CustomerBoImpl implements CustomerBo{

    CustomerDAO customerDAO;
    //DI via Spring
    public void setCustomerDAO(CustomerDAO customerDAO) {
        this.customerDAO = customerDAO;
    }

    //call DAO to save customer
    public void addCustomer(Customer customer){
        customerDAO.addCustomer(customer);
    }

    //call DAO to return customers
    public List<Customer> listCustomer(){
        return customerDAO.listCustomer();
    }
}

CustomerDAO.java

package com.yiibai.customer.dao;

import java.util.List;
import com.yiibai.customer.model.Customer;

public interface CustomerDAO{

    void addCustomer(Customer customer);
    List<Customer> listCustomer();

}

CustomerDAOImpl.java

package com.yiibai.customer.dao.impl;

import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.yiibai.customer.dao.CustomerDAO;
import com.yiibai.customer.model.Customer;

public class CustomerDAOImpl extends HibernateDaoSupport
    implements CustomerDAO{

    //add the customer
    public void addCustomer(Customer customer){
        getHibernateTemplate().save(customer);
    }

    //return all the customers in list
    public List<Customer> listCustomer(){
        return getHibernateTemplate().find("from Customer");
    }

}

CustomerAction.java – Struts2 的动作不再需要扩展ActionSupport，它将由 Spring 来处理。

package com.yiibai.customer.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.yiibai.customer.bo.CustomerBo;
import com.yiibai.customer.model.Customer;
import com.opensymphony.xwork2.ModelDriven;

public class CustomerAction implements ModelDriven{

    Customer customer = new Customer();
    List<Customer> customerList = new ArrayList<Customer>();

    CustomerBo customerBo;
    //DI via Spring
    public void setCustomerBo(CustomerBo customerBo) {
        this.customerBo = customerBo;
    }

    public Object getModel() {
        return customer;
    }

    public List<Customer> getCustomerList() {
        return customerList;
    }

    public void setCustomerList(List<Customer> customerList) {
        this.customerList = customerList;
    }

    //save customer
    public String addCustomer() throws Exception{

        //save it
        customer.setCreatedDate(new Date());
        customerBo.addCustomer(customer);

        //reload the customer list
        customerList = null;
        customerList = customerBo.listCustomer();

        return "success";

    }

    //list all customers
    public String listCustomer() throws Exception{

        customerList = customerBo.listCustomer();

        return "success";

    }

}

6. Spring相关配置

几乎所有的配置都是在这里完成是由Spring专门来整合。

CustomerBean.xml – 声明 Spring 的 bean：Action, BO 和 DAO.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

     <bean id="customerAction" class="com.yiibai.customer.action.CustomerAction">
        <property name="customerBo" ref="customerBo" />
    </bean>

    <bean id="customerBo" class="com.yiibai.customer.bo.impl.CustomerBoImpl" >
        <property name="customerDAO" ref="customerDAO" />
    </bean>

       <bean id="customerDAO" class="com.yiibai.customer.dao.impl.CustomerDAOImpl" >
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

</beans>

database.properties – 声明数据库详细信息

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/yiibai
jdbc.username=root
jdbc.password=password

DataSource.xml – 创建一个数据库源的Bean

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

 <bean
   class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location">
     <value>WEB-INF/classes/config/database/properties/database.properties</value>
   </property>
</bean>

  <bean id="dataSource"
         class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
  </bean>

</beans>

HibernateSessionFactory.xml – 创建一个SessionFactory Bean来集成Spring和Hibernate。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<!-- Hibernate session factory -->
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

    <property name="dataSource">
      <ref bean="dataSource"/>
    </property>

    <property name="hibernateProperties">
       <props>
         <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
         <prop key="hibernate.show_sql">true</prop>
       </props>
    </property>

    <property name="mappingResources">
        <list>
          <value>com/yiibai/customer/hibernate/Customer.hbm.xml</value>
        </list>
    </property>

</bean>
</beans>

SpringBeans.xml – 创建一个核心 Spring 的 bean 配置文件，作为中央的 bean 管理层。

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <!-- Database Configuration -->
    <import resource="config/spring/DataSource.xml"/>
    <import resource="config/spring/HibernateSessionFactory.xml"/>

    <!-- Beans Declaration -->
    <import resource="com/yiibai/customer/spring/CustomerBean.xml"/>

</beans>

7. JSP 页面

JSP页面来显示使用 Struts2 标签的元素。

customer.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
</head>

<body>
<h1>Struts 2 + Spring + Hibernate integration example</h1>

<h2>Add Customer</h2>
<s:form action="addCustomerAction" >
  <s:textfield name="name" label="Name" value="" />
  <s:textarea name="address" label="Address" value="" cols="50" rows="5" />
  <s:submit />
</s:form>

<h2>All Customers</h2>

<s:if test="customerList.size() > 0">
<table border="1px" cellpadding="8px">
    <tr>
        <th>Customer Id</th>
        <th>Name</th>
        <th>Address</th>
        <th>Created Date</th>
    </tr>
    <s:iterator value="customerList" status="userStatus">
        <tr>
            <td><s:property value="customerId" /></td>
            <td><s:property value="name" /></td>
            <td><s:property value="address" /></td>
            <td><s:date name="createdDate" format="dd/MM/yyyy" /></td>
        </tr>
    </s:iterator>
</table>
</s:if>
<br/>
<br/>

</body>
</html>

8. 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="default" namespace="/" extends="struts-default">

        <action name="addCustomerAction"
            class="customerAction" method="addCustomer" >
            <result name="success">pages/customer.jsp</result>
        </action>

        <action name="listCustomerAction"
            class="customerAction" method="listCustomer" >
            <result name="success">pages/customer.jsp</result>
        </action>

    </package>

</struts>

9. Struts 2 + Spring

要集成Struts2和Spring，只需注册ContextLoaderListener监听器类，定义一个“contextConfigLocation”参数要求Spring容器来解析“SpringBeans.xml”，而不使用默认的“applicationContext.xml”。

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Struts 2 Web Application</display-name>

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

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/classes/SpringBeans.xml</param-value>
  </context-param>

  <listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>

</web-app>

10. 运行实例

在浏览器中打开网址 : http://localhost:8080/ssh/listCustomerAction.action

参考

Struts2 + Hibernate集成实例

Struts2 + Spring集成实例

Struts2 + Hibernate 使用 Full Hibernate Plugin插件集成

代码下载 - http://pan.baidu.com/s/1mgzt1Xm (含ssh相关类库，详见 lib 目录，文件大小约：18M)。

Struts2+Log4j集成 - Struts2教程

在本教程中，我们学习如何将log4j框架在Struts2的Web应用程序集成。所有需要做的有：

包含 log4j.jar 作为项目依赖

创建一个 log4j.properties 文件，并把它放入 classpath 的根目录-放到资源文件夹中。

相关技术和工具的使用：

Log4j 1.2.17

Struts 2.1.8

Tomcat 6

MyEclipse 10

1. 工程结构

这里我们创建一个web工程为：struts2log4j，参见下面最终的工程结构：

2. log4j.properties

创建log4j的属性文件，并把它放入资源文件夹，请参阅步骤＃1。log4j.properties

# Root logger option
log4j.rootLogger=ERROR, stdout, file

# Redirect log messages to console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

# Redirect log messages to a log file, support rolling backup file.
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=${catalina.home}/logs/mystruts2app.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

4. Struts2 Action 和 Logging

一个简单的动作返回一个页面，并显示了如何来执行 log4j 消息日志记录。WelcomeAction.java

package com.yiibai.common.action;

import org.apache.log4j.Logger;
import com.opensymphony.xwork2.ActionSupport;

public class WelcomeAction extends ActionSupport {

    private static final long serialVersionUID = 1L;

    //get log4j
    private static final Logger logger = Logger.getLogger(WelcomeAction.class);

    public String execute() throws Exception {

        // logs debug message
        if (logger.isDebugEnabled()) {
            logger.debug("execute()!");
        }

        // logs exception
        logger.error("This is Error message", new Exception("Testing"));

        return SUCCESS;

    }
}

5. Struts2配置

Struts2 的配置和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="welcome" namespace="/" extends="struts-default">

        <action name="welcome" class="com.yiibai.common.action.WelcomeAction">
            <result name="success">pages/success.jsp</result>
        </action>

    </package>

</struts>

web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">

    <display-name>Struts 2 Web Application</display-name>

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

</web-app>

pages/success.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
</head>

<body>
<h1>Struts 2 + Log4j integration example</h1>

</body>
</html>

6. 实例测试

运行Struts 2的Web应用程序，并访问welcome的动作。

在浏览器中打开 URL : http://localhost:8888/struts2log4j/welcome

6.1 所有日志消息将显示在控制台中。

Figure : Eclipse 终端

6.2 此外，日志文件将在Tomcat 的日志文件夹中被创建。

图片: C:\mystruts2app.log

下载代码 – http://pan.baidu.com/s/1nt7yVep

Struts2配置Action类的静态参数 - Struts2教程

在某些情况下，可能需要一个Action类分配一些预定义或静态的参数值。

为动作定义静态参数

在Struts2，可以在 struts.xml 文件中的通过标记进行配置，例如，

struts.xml

<struts>

   <constant name="struts.custom.i18n.resources" value="global" />
   <constant name="struts.devMode" value="true" />

   <package name="default" namespace="/" extends="struts-default">
    <action name="locale" class="com.yiibai.common.action.LocaleAction">
        <result name="SUCCESS">pages/welcome.jsp</result>
        <param name="EnglishParam">English</param>
                <param name="ChineseParam">Chinese</param>
                 <param name="FranceParam">France</param>
    </action>
   </package>
</struts>

它分配三个预定义的参数值到LocaleAction Action类。

从动作获取静态参数

要从struts.xml中获取静态参数值，Action类必须实现参数化Parameterizable接口。动作的静态参数是由staticParams拦截，其中包括在默认堆栈控制

动作的静态参数是由staticParams拦截，包括在默认堆栈 “struts-default.xml” 中控制。

1. Map属性

在操作类初始化期间，staticParams拦截器将通过动作类的setParams()方法获取预先定义的参数值。

//...
import com.opensymphony.xwork2.config.entities.Parameterizable;

public class LocaleAction implements Parameterizable{

    Map<String, String> params;
    //...
    public void setParams(Map<String, String> params) {
        this.params = params;
    }
}

2. JavaBean 属性

在动作类的初始化，如果创建了getter和setter方法得当，staticParams拦截器将设置预先定义的参数值，以对应于该“参数”的每JavaBean属性。

//...
import com.opensymphony.xwork2.config.entities.Parameterizable;

public class LocaleAction implements Parameterizable{

    String englishParam;
    String chineseParam;
    String franceParam;

    public String getEnglishParam() {
        return englishParam;
    }

    public void setEnglishParam(String englishParam) {
        this.englishParam = englishParam;
    }

    public String getChineseParam() {
        return chineseParam;
    }

    public void setChineseParam(String chineseParam) {
        this.chineseParam = chineseParam;
    }

    public String getFranceParam() {
        return franceParam;
    }

    public void setFranceParam(String franceParam) {
        this.franceParam = franceParam;
    }
    //...
}

2. 运行实例

在浏览器中打开URL：http://localhost:8080/configure-param/locale.action

代码下载(configure-param) - http://pan.baidu.com/s/1dDmGDK9

Struts2下载文件实例 - Struts2教程

这是一个Struts2的例子来说明使用定制返回类型，允许用户下载文件。web工程的文件夹结构如下所示：

1. Action

在Action类中，声明一个 InputStream 的数据类型和getter方法。

DownloadAction.java

package com.yiibai.common.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import com.opensymphony.xwork2.ActionSupport;

public class DownloadAction extends ActionSupport{

    private InputStream fileInputStream;

    public InputStream getFileInputStream() {
        return fileInputStream;
    }

    public String execute() throws Exception {
        fileInputStream = new FileInputStream(new File("C:\\file-for-download.txt")); return SUCCESS;
    }
}

2. 视图文件

一个正常的页面，有一个下载链接，用于下载文件。

downloadPage.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>

<body>
<h1>Struts 2 download file example</h1>

<s:url id="fileDownload" namespace="/" action="download" ></s:url>

<div><div class="ads-in-post hide_if_width_less_800">
<script async src="../Images///pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- 728x90 - After2ndH4 -->
<ins class="adsbygoogle hide_if_width_less_800"
     style="display:inline-block;width:728px;height:90px"
     data-ad-client="ca-pub-2836379775501347"
     data-ad-slot="3642936086"
     data-ad-region="yiibairegion"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
</div></div><h2>Download file - <s:a href="%{fileDownload}">fileABC.txt</s:a>
</h2>

</body>
</html>

3. struts.xml

定义下载文件的细节。 <param name=”inputName”> 值是从Action的InputStream属性的名称。

阅读Struts2的数据流结果文档以了解更详细信息。

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="default" namespace="/" extends="struts-default">
   <action name="show">
    <result name="success">pages/downloadPage.jsp</result>
   </action>

   <action name="download" class="com.yiibai.common.action.DownloadAction">
    <result name="success" type="stream">
      <param name="contentType">application/octet-stream</param>
      <param name="inputName">fileInputStream</param>
      <param name="contentDisposition">attachment;filename="file-for-download.txt"</param> <param name="bufferSize">1024</param>
    </result>
   </action>
</package>

</struts>

4. 执行结果

在浏览器中打开：http://localhost:8080/struts2download/

参考

http://struts.apache.org/2.x/docs/stream-result.html

http://www.iana.org/assignments/media-types/

http://www.yiibai.com/struts/struts-download-file-from-website-example.html

http://www.yiibai.com/java/how-to-download-file-from-website-java-jsp.html

http://struts.apache.org/2.x/docs/how-can-we-return-a-text-string-as-the-response.html

代码下载(struts2download) - http://pan.baidu.com/s/1jGg0Lzo

Struts2和JSON实例 - Struts2教程

在这个Struts2例子，将学习如何通过“struts2-json-plugin.jar”库将对象转换为JSON格式的数据。

1. Action (JSON)

这是一个将被转换成JSON格式的 Action 类。

package com.yiibai.common.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.opensymphony.xwork2.Action;

public class JSONDataAction{

    private String string1 = "A";
    private String[] stringarray1 = {"A1","B1"};
    private int number1 = 123456789;
    private int[] numberarray1 = {1,2,3,4,5,6,7,8,9};
    private List<String> lists = new ArrayList<String>();
    private Map<String, String> maps = new HashMap<String, String>();

    //no getter method, will not include in the JSON
    private String string2 = "B";

    public JSONDataAction(){
        lists.add("list1");
        lists.add("list2");
        lists.add("list3");
        lists.add("list4");
        lists.add("list5");

        maps.put("key1", "value1");
        maps.put("key2", "value2");
        maps.put("key3", "value3");
        maps.put("key4", "value4");
        maps.put("key5", "value5");
    }

    public String execute() {
               return Action.SUCCESS;
        }

    public String getString1() {
        return string1;
    }

    public void setString1(String string1) {
        this.string1 = string1;
    }

    public String[] getStringarray1() {
        return stringarray1;
    }

    public void setStringarray1(String[] stringarray1) {
        this.stringarray1 = stringarray1;
    }

    public int getNumber1() {
        return number1;
    }

    public void setNumber1(int number1) {
        this.number1 = number1;
    }

    public int[] getNumberarray1() {
        return numberarray1;
    }

    public void setNumberarray1(int[] numberarray1) {
        this.numberarray1 = numberarray1;
    }

    public List<String> getLists() {
        return lists;
    }

    public void setLists(List<String> lists) {
        this.lists = lists;
    }

    public Map<String, String> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, String> maps) {
        this.maps = maps;
    }

}

3. struts.xml

要输出JSON数据，需要声明一个包，它扩展“json-default”，会将结果类型转为“json”。

<?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="default" namespace="/" extends="json-default">
      <action name="getJSONResult"
           class="com.yiibai.common.action.JSONDataAction">
              <result type="json" />
      </action>
    </package>

</struts>

4. 实例

访问动作URL时，JSONDataAction属性将被转换成JSON格式。

http://localhost:8080/struts2json/getJSONResult.action

JSON 格式 …

{
   "lists":["list-1","list-2","list-3","list-4","list-5"],
   "maps":
   {
     "key4":"value4","key3":"value3","key5":"value5","key2":"value2","key1":"value1"
   },
   "number1":123456789,
   "numberarray1":[1,2,3,4,5,6,7,8,9],
   "string1":"A",
   "stringarray1":["A1","B1"]
}

希望这个简单的例子可以了解JSON插件在Struts2是如何工作的有一个总体的思路。不过，还是有很多有用的参数不包括在这里，请务必阅读 Struts2 JSON插件文档 以获取更多详细信息。下载源代码(struts2json) – http://pan.baidu.com/s/1bnv8l9X