Struts2 从入门到放弃?不,这些核心知识你依然需要掌握

一、写在前面

Struts2 曾是 Java Web 开发的事实标准之一,尤其是在 2010 年左右,几乎是企业级 SSH(Struts2 + Spring + Hibernate)框架中的"门面担当"。随着 Spring MVC 和 Spring Boot 的崛起,Struts2 逐渐退出主流技术栈,但你仍然可能在许多传统企业的系统中与它"狭路相逢"。

了解 Struts2,未必是为了追赶潮流,而是为了在生产环境出现问题时,能够从容应对。

二、Struts2 核心架构

1. 请求处理流程

text

markdown 复制代码
HttpServletRequest 
    → FilterDispatcher(StrutsPrepareAndExecuteFilter)
    → ActionProxy 
    → ActionInvocation 
    → Interceptor(拦截器链)
    → Action 
    → Result
    → HttpServletResponse
  • 核心控制器StrutsPrepareAndExecuteFilter(早期版本为 FilterDispatcher
  • Action:业务逻辑处理单元,返回逻辑视图名
  • Result:视图渲染(JSP、FreeMarker、JSON 等)

2. 一个简单的 Action 示例

java

scala 复制代码
public class LoginAction extends ActionSupport {
    private String username;
    private String password;

    public String execute() {
        if ("admin".equals(username) && "123456".equals(password)) {
            return SUCCESS;
        }
        return ERROR;
    }
    // getters / setters...
}

对应的 struts.xml

xml

ini 复制代码
<action name="login" class="com.demo.LoginAction">
    <result name="success">/welcome.jsp</result>
    <result name="error">/login.jsp</result>
</action>

三、OGNL 与 ValueStack

这是 Struts2 最"迷人"也最"伤人"的部分。

1. ValueStack(值栈)

  • 存放 Action 对象、模型对象、临时变量
  • 使用 OGNL 表达式访问值栈中的数据

2. OGNL 表达式示例

jsp

xml 复制代码
<s:property value="username" />          <!-- 调用 getUsername() -->
<s:property value="#session.userId" />   <!-- 访问 Session 域 -->
<s:set name="myVar" value="'hello'" />   <!-- 创建临时变量 -->

也正是 OGNL 强大的表达式能力 + 参数自动填充机制,让 Struts2 历史上爆发过大量远程代码执行漏洞(S2-xxx)。

四、拦截器(Interceptor)

拦截器是 Struts2 的 AOP 实现,用于实现权限校验、日志、输入校验、文件上传等横切关注点。

自定义拦截器:

java

scala 复制代码
public class AuthInterceptor extends AbstractInterceptor {
    public String intercept(ActionInvocation invocation) throws Exception {
        Map<String, Object> session = invocation.getInvocationContext().getSession();
        if (session.get("user") == null) {
            return "login";
        }
        return invocation.invoke();
    }
}

struts.xml 中配置拦截器栈:

xml

ini 复制代码
<interceptors>
    <interceptor name="auth" class="com.demo.AuthInterceptor"/>
    <interceptor-stack name="myStack">
        <interceptor-ref name="defaultStack"/>
        <interceptor-ref name="auth"/>
    </interceptor-stack>
</interceptors>

五、常见漏洞与安全提醒

Struts2 相对出名(或者说"出名")的一点就是频繁的 RCE 漏洞。

漏洞编号 触发点 修复方式
S2-045 Content-Type 头解析 升级至 2.3.32 / 2.5.10.1
S2-057 namespace 配置不当 升级至 2.5.16 / 2.3.35
S2-061 OGNL 沙盒绕过 升级至 2.5.26+

安全建议

  • 始终使用最新稳定版的 Struts2(目前 2.5.x 及以上)
  • 避免直接使用 altSyntax、通配符 action 配置不当
  • 对用户输入进行严格校验
  • 使用 struts2-security 插件或增加安全拦截器

六、和 Spring MVC 的对比

特性 Struts2 Spring MVC
核心设计 基于类拦截,每个请求都会创建一个 Action 实例 基于方法拦截,Controller 是单例
参数绑定 基于 OGNL + 属性驱动 基于方法参数 + @RequestParam
视图技术 JSP + 标签库 更灵活,支持 Thymeleaf、JSON 等
性能 稍差(值栈、OGNL 解析开销) 更优
安全性 历史上漏洞较多 相对较少

七、维护老项目的小技巧

如果你们系统仍然使用 Struts2,建议:

  1. 升级到允许范围内的最新版本(如 2.5.33)
  2. 将 JSP 中的 <s:property> 替换为 EL 表达式(降低 OGNL 触发风险)
  3. 关闭动态方法调用 <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
  4. 避免使用通配符映射 action="*_*" class="{1}Action" method="{2}"
  5. 考虑逐步迁移到 Spring Boot + Spring MVC

八、结语

Struts2 就像一位"老将军",虽然已不复当年之勇,但在很多战场上依然坚守岗位。如果你是一名企业级开发人员,不求精通,但至少应当理解它的请求流转、值栈原理以及常见漏洞。

学 Struts2,不是为了跟随潮流,而是为了"优雅地维护"------你总会在某个客户现场,和这位老熟人重逢。

相关推荐
北城以北888826 分钟前
RocketMQ简介
java·spring boot·后端·rocketmq
折哥的程序人生 · 物流技术专研8 小时前
Java面试85题图解版 · 特别篇:2026后端高频面试题复盘(算法底层逻辑+高并发架构设计全解析,附Java实战代码)
java·网络·数据库·算法·面试
一条泥憨鱼8 小时前
【Redis】数据类型和常用命令
java·数据库·redis·后端·缓存
云烟成雨TD8 小时前
Spring AI Alibaba 1.x 系列【78】沙箱(Sandbox)
java·人工智能·spring
程序员二叉8 小时前
【Java】 异常高频面试题精讲 | 易错点+对比总结
java·开发语言·面试
周航宇JoeZhou9 小时前
JB3-9-SpringAI(二)
java·ai·agent·多智能体·调度·智能体·观察
好家伙VCC9 小时前
Web Components主题热切换方案揭秘
java·前端
慕木沐9 小时前
Google ADK Java 1.0版本 核心机制与实战 Demo
java·开发语言·python
焦虑的说说10 小时前
秒杀系统设计方案
java
许彰午10 小时前
30_Java Stream流操作全解
java·windows·python