教程的示例项目:点击转到Github
本文原文为英文教程Struts 2 + Spring integration example,我对这篇教程进行了翻译。
另外原教程使用 Eclipse 开发,示例项目下载地址也失效了,我对失效的示例项目使用 IDEA 进行了重新编写与上传。
项目结构
教程完成后的项目结构。
新建项目
新建一个 Maven 项目,不使用原型。
编辑 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
如果右上角出现“配置应用程序上下文”提示,点击提示,然后确认。
注意
此文件一般应该放在 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。