Java Struts 教程:从入门到实践
目录
- 什么是 Struts?
- Struts 2 的核心优势
- 环境准备
- 创建第一个 Struts 2 应用:Hello World
- 1 创建 Web 项目
- 2 添加 Struts 2 依赖
- 3 配置
web.xml - 4 创建 Action 类
- 5 创建视图(JSP)
- 6 配置 Struts 2 (
struts.xml) - 7 部署与运行
- 深入理解 Struts 2 架构
- 1 核心组件:FilterDispatcher (Struts 2.5+) / StrutsPrepareAndExecuteFilter
- 2 核心组件:Action
- 3 核心组件:Interceptor (拦截器)
- 4 核心组件:Result (结果)
- 5 核心组件:ValueStack (值栈)
- 常用功能详解
- 1 数据封装 (接收表单数据)
- 2 OGNL 表达式
- 3 拦截器配置与使用
- 4 文件上传
- 总结与资源
什么是 Struts?
Struts 是一个开源的、用于创建企业级 Java Web 应用程序的 MVC (Model-View-Controller) 框架,它的主要目的是将应用程序的不同部分(业务逻辑、数据、展示)解耦,使开发更加模块化和可维护。

- Struts 1:早期的经典框架,曾是 Java Web 开发的霸主,但其设计(如基于 FormBean)在今天看来有些过时。
- Struts 2:目前的主流版本。需要特别注意的是,Struts 2 并非 Struts 1 的升级版,它是在另一个名为 WebWork 的框架基础上发展而来的,因此其架构和设计理念与 Struts 1 有很大不同。
本教程将专注于 Struts 2。
Struts 2 的核心优势
- 清晰的 MVC 架构:严格分离了业务逻辑、数据模型和用户界面。
- 强大的拦截器机制:通过拦截器,可以轻松实现如日志、权限验证、数据预处理等横切关注点,无需在 Action 中编写重复代码。
- 简单易用的 Action 开发:Action 不需要继承任何父类,只需实现一个方法(通常是
execute),或者使用 POJO (Plain Old Java Object) 作为 Action,非常灵活。 - 强大的 OGNL 表达式语言:在视图中可以直接访问 Action 的属性、调用方法,操作集合和 Map,使页面与后端交互非常方便。
- 丰富的标签库:提供了大量 JSP 标签(如
<s:form>,<s:textfield>,<s:if>),简化了页面的开发。 - 插件化:拥有大量成熟的插件,如用于 REST 开发、Convention Plugin(约定优于配置)、JSON 插件等。
环境准备
在开始之前,请确保你已经安装并配置好了以下环境:
- JDK: 版本 8 或更高版本。
- Web 服务器: 如 Apache Tomcat 9.x 或更高版本。
- IDE: Eclipse for Enterprise Java and Web Developers 或 IntelliJ IDEA。
- 构建工具 (推荐): Maven 或 Gradle,用于管理项目依赖。
创建第一个 Struts 2 应用:Hello World
我们将创建一个简单的 Web 应用,用户通过输入姓名,点击提交后,页面会显示 "Hello, [姓名]!"。
1 创建 Web 项目
在你的 IDE 中,创建一个新的 Dynamic Web Project (在 Maven 中,可使用 maven-archetype-webapp 模板)。

2 添加 Struts 2 依赖
最简单的方式是使用 Maven,在 pom.xml 文件中添加以下依赖:
<dependencies>
<!-- Struts 2 核心依赖 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.5.33</version> <!-- 建议使用较新版本 -->
</dependency>
<!-- 用于整合 JSP 的依赖 -->
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-junit-plugin</artifactId>
<version>2.5.33</version>
<scope>test</scope>
</dependency>
<!-- JSP 和 Servlet API (Tomcat 提供的版本不满足,可以显式添加) -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
如果你不使用 Maven,需要手动下载 struts2-core-2.x.x.jar 以及其依赖的 JAR 包,并放入项目的 WEB-INF/lib 目录下。
3 配置 web.xml
web.xml 是 Web 应用的部署描述符,我们需要在这里配置一个 Filter 来拦截所有请求,并将其交给 Struts 2 框架处理。
在 src/main/webapp/WEB-INF/web.xml 中添加以下内容:

<?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">
<!-- Struts 2 的核心 Filter -->
<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>
</web-app>
4 创建 Action 类
Action 是 Struts 2 的核心,它处理用户请求并返回一个结果字符串,框架根据这个字符串来决定渲染哪个视图。
在 src/main/java 下创建一个包,com.example.action,然后创建 HelloWorldAction.java:
package com.example.action;
public class HelloWorldAction {
private String name;
private String message;
// 这是默认执行的方法
public String execute() {
this.message = "Hello, " + this.name + "!";
return "success"; // 返回一个逻辑视图名
}
// Getter 和 Setter 方法 (必须提供,用于 OGNL 访问和值栈注入)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
5 创建视图
视图负责展示数据,我们在 src/main/webapp 下创建 hello.jsp。
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>Struts 2 Hello World</title>
</head>
<body>
<h2>Hello World</h2>
<!-- 使用 Struts 2 的表单标签 -->
<s:form action="hello">
<s:textfield name="name" label="Your Name" />
<s:submit value="Submit" />
</s:form>
<!-- 显示从 Action 传来的消息 -->
<s:property value="message" />
</body>
</html>
注意:<%@ taglib prefix="s" uri="/struts-tags" %> 是引入 Struts 2 的标签库。
6 配置 Struts 2 (struts.xml)
struts.xml 是 Struts 2 的核心配置文件,它定义了 Action 如何与 URL 映射,以及 Action 的返回结果对应哪个 JSP 页面。
在 src/main/resources 目录下创建 struts.xml 文件(这个目录会自动被部署到 WEB-INF/classes 下)。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- 开发模式下,会重新加载配置文件,方便调试 -->
<constant name="struts.devMode" value="true" />
<!-- package 用于组织 Action,name 是包名,extends="struts-default" 表示继承 Struts 2 的核心功能 -->
<package name="hello" namespace="/" extends="struts-default">
<!-- 定义一个 Action,name="hello" 将作为 URL 的一部分 -->
<action name="hello" class="com.example.action.HelloWorldAction">
<!-- 定义结果,name="success" 对应 Action execute() 方法的返回值 -->
<!-- type="dispatcher" 表示使用 RequestDispatcher 转发,默认值 -->
<result name="success">/hello.jsp</result>
</action>
</package>
</struts>
7 部署与运行
- 将你的 Web 项目部署到 Tomcat 服务器。
- 启动 Tomcat。
- 在浏览器中访问
http://localhost:8080/你的项目名/hello.action。 - 在输入框中输入你的名字,"Struts",然后点击 Submit。
- 页面会跳转到
hello.jsp,并显示 "Hello, Struts!"。
至此,你的第一个 Struts 2 应用就成功运行了!
深入理解 Struts 2 架构
1 核心组件:FilterDispatcher (Struts 2.5+)
在 web.xml 中配置的 StrutsPrepareAndExecuteFilter 是整个框架的入口,它像一个总指挥,负责拦截请求,并根据 struts.xml 的配置,将请求分发给相应的 Action。
2 核心组件:Action
Action 是业务逻辑的载体,它是一个普通的 Java 类,不需要继承任何类,当请求到达时,Struts 2 会使用反射创建 Action 的实例,然后调用其 execute() 方法(或者你通过 method 属性指定的方法)。
Action 的返回值(如 "success", "error")并不直接代表一个页面,而是逻辑视图名,由 struts.xml 中的 <result> 标签来决定最终渲染哪个物理页面。
3 核心组件:Interceptor (拦截器)
拦截器是 Struts 2 最强大的功能之一,它是一个可以在 Action 执行前后插入代码的 AOP (面向切面编程) 实现。
- 工作流程:请求 -> 拦截器链 -> Action -> 拦截器链 -> 结果
- 内置拦截器:Struts 2 提供了大量功能强大的内置拦截器,如:
params: 负责将请求参数注入到 Action 的属性中(数据封装)。modelDriven: 将请求参数直接注入到 Model 对象中。validation: 负责执行输入验证。prepare: 在 Action 执行前做一些准备工作。
- 自定义拦截器:你可以轻松编写自己的拦截器来复用通用逻辑,如用户登录验证、日志记录等。
4 核心组件:Result (结果)
<result> 定义了 Action 执行完成后,下一步要做什么,Struts 2 支持多种 Result 类型:
dispatcher(默认): 服务器端转发,用于跳转到 JSP。redirect: 客户端重定向,可以防止表单重复提交。redirectAction: 重定向到另一个 Action。stream: 用于下载文件。json: 用于返回 JSON 数据,常用于 AJAX 请求。
5 核心组件:ValueStack (值栈)
值栈是 Struts 2 的数据核心,是一个数据存储区域,它是一个栈结构,存放了 Action 的实例以及 Action 的所有属性。
- OGNL:OGNL (Object-Graph Navigation Language) 是 Struts 2 默认的表达式语言,它通过访问值栈来获取和设置数据。
- JSP 中的访问:在 JSP 页面中,
<s:property value="name"/>会自动从值栈的栈顶开始查找name属性,在 Action 中设置的name和message属性都可以被直接访问。
常用功能详解
1 数据封装
Struts 2 提供了非常方便的数据封装机制,可以将表单数据自动填充到 Action 的属性中,这主要依靠 params 拦截器实现。
- 属性驱动:如我们上面的例子,在 Action 中提供属性的 getter/setter。
- 模型驱动:如果你的 Action 需要接收一个复杂的对象,可以实现
ModelDriven接口。
// Action 类
public class UserAction implements ModelDriven<User> {
private User user = new User(); // 必须手动实例化
@Override
public User getModel() {
return user;
}
public String execute() {
// user 对象已经被填充了表单数据
System.out.println("Username: " + user.getUsername());
return "success";
}
}
对应的 JSP 表单:
<s:form action="user">
<s:textfield name="username" label="Username" /> <!-- name 必须与 User 对象的属性名一致 -->
<s:password name="password" label="Password" />
<s:submit />
</s:form>
2 OGNL 表达式
OGNL 是 Struts 2 的灵魂,在 JSP 中通过 、、 符号来使用。
- 访问属性:
<s:property value="user.name" /> - 调用方法:
<s:property value="user.toUpperCaseName()" /> - 访问静态方法:
<s:property value="@com.example.utils.DateUtils@formatNow()" /> - 访问集合/Map:
<s:iterator value="users" var="u"> <s:property value="#u.name" /> </s:iterator> - 符号:用于访问上下文对象,如
#request,#session,#application。 - 符号:在属性值中强制解析 OGNL。
- 符号:在国际化或配置文件中解析值。
3 拦截器配置与使用
你可以在 struts.xml 中为某个 Action 或整个 Package 指定拦截器。
<package name="myPackage" extends="struts-default">
<!-- 定义拦截器栈 -->
<interceptors>
<interceptor name="myLoggingInterceptor" class="com.example.interceptor.LoggingInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"/> <!-- 必须包含默认拦截器栈 -->
<interceptor-ref name="myLoggingInterceptor"/>
</interceptor-stack>
</interceptors>
<!-- 设置默认的拦截器栈 -->
<default-interceptor-ref name="myStack"/>
<action name="admin" class="com.example.action.AdminAction">
<interceptor-ref name="myStack"/>
<result name="success">/admin.jsp</result>
</action>
</package>
4 文件上传
Struts 2 内置了强大的文件上传功能。
- Action 类:使用
File类型接收文件,String类型接收文件名。private File upload; private String uploadContentType; private String uploadFileName; // ... getter/setter
- JSP 表单:
<s:file>标签,并设置enctype="multipart/form-data"。<s:form action="upload" method="post" enctype="multipart/form-data"> <s:file name="upload" label="Select a File" /> <s:submit /> </s:form> struts.xml:需要配置一个允许上传文件大小的常量。<constant name="struts.multipart.maxSize" value="10485760" /> <!-- 10MB -->
总结与资源
Struts 2 是一个成熟、功能强大且设计优雅的 MVC 框架,虽然近年来 Spring MVC 和其他框架(如 Play, Micronaut)的兴起使其市场份额有所下降,但 Struts 2 的核心思想(尤其是拦截器和值栈)对后来的框架产生了深远影响。
优点
- 解耦度高:MVC 分层清晰。
- 扩展性强:拦截器和插件机制非常灵活。
- 开发效率高:标签库和 OGNL 大大简化了视图层开发。
缺点
- 学习曲线:概念较多(值栈、拦截器栈等),需要时间掌握。
- 配置繁琐:相比 Spring MVC 的注解驱动,XML 配置略显繁琐(但可通过 Convention Plugin 改善)。
- 历史包袱:曾曝出过严重的安全漏洞(如 CVE-2025-5638),虽然已修复,但影响了声誉。
推荐资源
- 官方文档:Apache Struts 2 Documentation (最权威、最全面的资料)
- Struts 2 教程 (W3Cschool):https://www.w3cschool.cn/struts_2/
- Struts 2 教程 (Runoob):https://www.runoob.com/struts_2/struts2-tutorial.html
希望这份教程能帮助你顺利入门 Struts 2!
