教程的示例项目:点击转到Github

本文原文为英文教程Struts 2 + Spring integration example,我对这篇教程进行了翻译。
另外原教程使用 Eclipse 开发,示例项目下载地址也失效了,我对失效的示例项目使用 IDEA 进行了重新编写与上传。

项目结构

教程完成后的项目结构。

1

新建项目

新建一个 Maven 项目,不使用原型。

2

编辑 pom.xml

导入 Spring 和 Struts2 的依赖。

这些依赖的版本在不断更新,下面代码中给出的版本是此教程发布时的最新版本。查询最新版本号可以点击此处

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>SSDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- Struts 2 -->
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-core</artifactId>
            <version>2.5.27</version>
        </dependency>

        <!-- Spring framework -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.13</version>
        </dependency>


        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.3.13</version>
        </dependency>

        <!-- Struts 2 + Spring plugins -->
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-spring-plugin</artifactId>
            <version>2.5.27</version>
        </dependency>
    </dependencies>
</project>

为项目添加 Web 框架支持并配置服务器软件

此部分在本博客文章如何使用idea创建javaweb项目并解决各种乱码问题中写过,不再赘述,请跳转查看“改为 JavaWeb 项目”以及之后的部分。

请按本文开头的项目结构创建对应目录

user.jsp 文件仅用于展示这个程序如何显示网页。内容可以随便写。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>测试页</title>
</head>
<body>
在控制台输出:printUser() is executed...
</body>
</html>

配置 Struts2 过滤器和 Spring 监听器

修改 web.xml 文件以声明程序使用 Struts2 和 Spring 框架。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

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

        <!--配置struts2过滤器-->
        <filter>
            <filter-name>struts2</filter-name>
            <filter-class>
                org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
            </filter-class>
        </filter>

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

        <!--配置springframework过滤器-->
        <listener>
            <listener-class>
                org.springframework.web.context.ContextLoaderListener
            </listener-class>
        </listener>
</web-app>

编辑使用到的类与接口

UserBo

我觉得原作者是想模拟一个 DAO 层接口,但毕竟不是持久化操作有 DAO 不太好,使用写作 Bo。

package com.chiyu.user.bo;

public interface UserBo {
    public void printUser();
}

UserBoImpl

上一个接口类的具体实现。

package com.chiyu.user.bo.Impl;

import com.chiyu.user.bo.UserBo;

public class UserBoImpl implements UserBo {
    public void printUser(){
        System.out.println("printUser() is executed...");
    }
}

UserAction

package com.chiyu.user.action;

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

// 这是一个 Struts2 的 Action。
public class UserAction extends ActionSupport {
    //这个有Get与Set方法的变量不需要赋值,他的值在Spring配置文件中对应的bean定义
    UserBo userBo;

    public UserBo getUserBo() {
        return userBo;
    }

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

    public String execute() throws Exception {
        //正如所见,我们没有为它赋值,但我们可以使用它。
        userBo.printUser();
        return SUCCESS;

    }
}

UserAnotherAction

package com.chiyu.user.action;

import com.chiyu.user.bo.UserBo;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

// 这是一个 Struts2 的 Action。
public class UserAnotherAction extends ActionSupport {

    public String execute() throws Exception {
        //使用 Spring 的通用WebApplicationContextUtils类直接获取 Spring 的 bean。
        WebApplicationContext context =
                WebApplicationContextUtils.getRequiredWebApplicationContext(
                        ServletActionContext.getServletContext()
                );
        UserBo userBo1 = (UserBo)context.getBean("userBo");
        userBo1.printUser();

        return SUCCESS;

    }
}

UserSpringAction

package com.chiyu.user.action;

import com.chiyu.user.bo.UserBo;

// 这是一个 Spring 的 Bean。
public class UserSpringAction {
    //这个有Get与Set方法的变量不需要赋值,他的值在Spring配置文件中对应的bean定义
    UserBo userBo;

    public UserBo getUserBo() {
        return userBo;
    }

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

    public String execute() throws Exception {
        //正如所见,我们没有为它赋值,但我们可以使用它。
        userBo.printUser();
        return "success";

    }
}

创建 Spring 配置文件 applicationContext.xml

3

如果右上角出现“配置应用程序上下文”提示,点击提示,然后确认。

注意
此文件一般应该放在 resource 文件夹中,但需要另外配置一些东西,这里为了方便以及尊重原作,依然放在这里。

在 applicationContext.xml 文件中注册所有 Spring 的 Bean ,Spring 监听器会自动定位到这个 xml 文件。

<?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.xsd">

    <bean id="userBo" class="com.chiyu.user.bo.Impl.UserBoImpl" />

    <bean id="userSpringActionBean" class="com.chiyu.user.action.UserSpringAction">
        <property name="userBo" ref="userBo" />
    </bean>
</beans>

配置 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">
        <!--Struts2 与 Spring 集成方式1:在 Struts 2 Action 类中访问 Spring 的 bean。
        默认情况下,Spring 侦听器启用“通过匹配 bean 名称自动装配”。
        因此,它会自动通过setUserBo()将 Spring 的“ userBo ” bean传递到 UserAction 中。-->
        <action name="userAction"
                class="com.chiyu.user.action.UserAction" >
            <result name="success">pages/user.jsp</result>
        </action>

        <!--Struts2 与 Spring 集成方式2:使用 Spring 的通用WebApplicationContextUtils类直接获取 Spring 的 bean。-->
        <action name="userAnotherAction"
                class="com.chiyu.user.action.UserAnotherAction" >
            <result name="success">pages/user.jsp</result>
        </action>

        <!--Struts2 与 Spring 集成方式3:让SpringBean充当Struts 2 Action类,访问的是Spring的bean。
        在本例中,userSpringAction充当 Struts 2 Action 类,您可以使用普通 Spring 的方式DI Spring 的userBo bean。-->
        <action name="userSpringAction"
                class="userSpringActionBean" >
            <result name="success">pages/user.jsp</result>
        </action>

    </package>

</struts>

解决 ClassNotFoundException 问题

如果现在直接启动,大概率出现以下错误:
java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener

参考本博客另一篇教程:解决 IDEA Web 项目报错:java.lang.ClassNotFoundException

演示

Struts2 与 Spring 集成方式1:在 Struts 2 Action 类中访问 Spring 的 bean

默认情况下,Spring 侦听器启用“通过匹配 bean 名称自动装配”。

因此,它会自动通过setUserBo()将 Spring 的“ userBo” bean传递到 UserAction 中。

对应配置文件中以下部分以及 UserAction 类:

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

//applicationContext.xml
<bean id="userBo" class="com.chiyu.user.bo.Impl.UserBoImpl" />

要访问此操作,请使用 URL:http://localhost:8080/Example/userSpringAction

上方 URL 需要根据实际修改
localhost:[端口号]/[配置Tomcat时的应用程序上下文]/[struts.xml中action标签的name属性值]

Struts2 与 Spring 集成方式2:使用 Spring 的通用WebApplicationContextUtils类直接获取 Spring 的 bean

对应配置文件中以下部分以及 UserAnotherAction 类:

//struts.xml
<action name="userAnotherAction" class="com.chiyu.user.action.UserAnotherAction" >
	<result name="success">pages/user.jsp</result>
</action>

//applicationContext.xml
<bean id="userBo" class="com.chiyu.user.bo.Impl.UserBoImpl" />

要访问此操作,请使用 URL:http://localhost:8080/Example/userAnotherAction

Struts2 与 Spring 集成方式3:让SpringBean充当Struts 2 Action类,访问的是Spring的bean

在本例中,userSpringAction充当 Struts 2 Action 类,您可以使用普通 Spring 的方式DI Spring 的userBo bean。

对应配置文件中以下部分以及 UserAnotherAction 类:

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

//applicationContext.xml
<bean id="userBo" class="com.chiyu.user.bo.Impl.UserBoImpl" />
<bean id="userSpringActionBean" class="com.chiyu.user.action.UserSpringAction">
	<property name="userBo" ref="userBo" />
</bean>

要访问此操作,请使用 URL:http://localhost:8080/Example/userSpringAction。