Struts2 配置文件的核心就是 struts.xml 与 web.xml 两个文件:前者管 Action 映射和结果跳转,后者管过滤器入口,二者路径和加载顺序错一个,项目就起不来。很多人卡在“代码明明写对了却 404”,十有八九是文件放错了位置,或者常量被后面的配置覆盖了。
Struts2 配置文件到底由哪几个文件组成
别把“配置文件”想成一个文件,Struts2 的配置是分层叠加的,从框架自带到你手写,一共叠了好几层。
struts.xml:核心路由与结果映射的集散地
这是你最常改的文件,它负责三件事:定义包(package)、声明 Action、指定结果视图(result)。
一个最小可跑的骨架长这样:
<struts>
<constant name="struts.devMode" value="false"/>
<package name="default" extends="struts-default" namespace="/user">
<action name="login" class="com.demo.LoginAction" method="execute">
<result name="success">/WEB-INF/jsp/welcome.jsp</result>
<result name="error">/WEB-INF/jsp/login.jsp</result>
</action>
</package>
</struts>
extends="struts-default" 这行不能省,它把拦截器栈继承过来,省了就得自己一个个配。
struts.properties 与 struts-default.xml 的分工
struts-default.xml 是框架包里的默认值,你不动它,只覆盖。struts.properties 是纯键值对文件,适合放常量,但更推荐写在 struts.xml 的 <constant> 标签里,因为一个项目里配置分散在多个文件,排查时容易漏。
web.xml 里那个 Filter 才是真正的入口
Struts2 靠一个 Servlet Filter 拦截请求,Struts 2.5 之后类名换成了 org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter,老教程里写的 FilterDispatcher 早在 2.1 就废弃了,照抄旧文会直接报 ClassNotFound。
<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>

url-pattern 写 还是 .action,会影响静态资源是否被拦,生产环境建议只拦 .action,或者配 struts.action.excludePattern。
struts2配置文件放在哪个目录才生效
答案很干脆:源码目录的根,也就是 classpath 根。
- Maven 项目:
src/main/resources/struts.xml - 普通 Web 项目:
src/struts.xml - 编译后必须出现在
WEB-INF/classes/struts.xml
编译后 classpath 路径的验证方法
别猜,直接看,打完包后进 target/classes/ 或解压 war:
unzip -l demo.war | grep struts.xml
看到 WEB-INF/classes/struts.xml 才算对,如果你放进了 WEB-INF/ 根目录,框架根本扫不到,启动时只会给一句“Unable to load configuration”,非常不友好。
想换路径也行,在 web.xml 里加:
<init-param> <param-name>config</param-name> <param-value>struts-default.xml,struts-plugin.xml,/WEB-INF/conf/struts.xml</param-value> </init-param>
自定义路径后,加载顺序完全由这个参数决定,漏写 struts-default.xml 就会丢掉拦截器栈。
配置文件的加载顺序
按优先级从低到高:
struts-default.xml(框架自带)struts-plugin.xml(各插件自带)struts.xml(你写的)struts.propertiesweb.xml里的<init-param>
规律很简单:后加载的覆盖先加载的,所以同一个常量在两处都写,web.xml 赢,有人把 struts.devMode 在 struts.xml 里设成 false,却在 web.xml 里留了 true,上线后页面疯狂打印调试信息,就是这么来的。
struts2配置文件详解:标签怎么用才不出错
package、action、result 三段式写法
<package>:逻辑分组,namespace决定 URL 前缀,extends决定继承谁<action>:name是 URL 里的名字,class是全限定类名,method指定调用哪个方法<result>:name对应 Action 返回的字符串,标签体是跳转目标

跳转类型别乱选,选错会导致参数丢失或地址栏不变:
| result type | 行为 | 典型场景 |
|---|---|---|
| dispatcher | 服务器端转发,地址栏不变 | 展示 JSP |
| redirect | 302 重定向,地址栏变 | 提交后防重复刷新 |
| redirectAction | 重定向到另一个 Action | 流程跳转 |
| chain | Action 链,共享值栈 | 少用,副作用多 |
| stream | 输出二进制流 | 文件下载 |
业内共识是 chain 尽量别用,它会让拦截器执行多次,排查问题时非常痛苦。
通配符与动态方法调用的取舍
通配符能省大量重复配置:
<action name="user_" class="com.demo.UserAction" method="{1}">
<result>/WEB-INF/jsp/user_{1}.jsp</result>
</action>
但 method="{1}" 相当于把方法名交给 URL 决定,攻击面变大,行业共识认为,开放动态方法调用(DMI)是历史漏洞的重要来源,Struts 2.3.15.1 起默认关闭,2.5 之后改用 <global-allowed-methods> 白名单方式。
<global-allowed-methods>execute,save,list</global-allowed-methods>
只列你能接受被调用的方法,多一个都别加。
struts2和Spring MVC配置文件有什么本质区别
这是迁移时最常见的纠结点,一句话概括:Struts2 是“配置驱动”,Spring MVC 是“注解驱动”。
- Struts2:一个 Action 对应一个类,URL 靠 struts.xml 里的
name映射,改路径要改配置 - Spring MVC:
@RequestMapping直接贴在方法上,路径跟代码在一起 - 参数接收:Struts2 用 Action 的 setter 接收,Spring MVC 用方法参数绑定
- 单例问题:Struts2 Action 每次请求新建实例(多例),Spring MVC Controller 默认单例
正因为是多例,Struts2 的 Action 可以放心把请求参数存成员变量,而 Spring MVC 里这么写就是线程安全问题,业内专家指出,不少从 Struts2 迁过来的老项目,第一波线上故障就是照搬了成员变量写法。
struts2 漏洞配置文件安全加固清单

如果这个项目还要继续跑,下面几条是硬性要求,改完再上线。
struts.devMode设为false,否则异常堆栈、OGNL 表达式会直接暴露给浏览器- 升级到 Struts 2.5.33 或 2.3.37 之后的版本,
struts.enable.DynamicMethodInvocation保持 false - 显式开启严格方法调用(SMI),并配置
global-allowed-methods白名单 struts.action.excludePattern排除/static/、/upload/等静态路径,减少过滤器攻击面- 文件上传的
struts.multipart.maxSize别留默认值,按业务上限收窄 - 关闭
struts.i18n.reload、struts.configuration.xml.reload这类热加载开关
改完用这条命令确认生效文件:
grep -r "devMode" WEB-INF/classes/ struts.xml
顺带提醒,<result> 指向 WEB-INF 下的 JSP 是正确做法,直接放 webapp 根目录反而能被绕过 Action 直接访问。
配置这件事,本质就是搞清楚“谁覆盖谁”和“谁先加载”,把 struts.xml 放在 classpath 根、web.xml 只配一个 Filter、常量只在一处定义,八成问题会自动消失。
struts2配置文件的常见问题
问:struts.xml 改了没生效,重启也没用,怎么办?
先确认改的是源码目录还是编译产物,Tomcat 跑的是 WEB-INF/classes 里的副本,直接改 src 下那份不重新编译当然没用,另外检查 web.xml 的 config 参数有没有把路径指到别处。
问:一个项目能有多个 struts.xml 吗?
可以,用 <include file="struts-user.xml"/> 拆模块,但注意被 include 的文件里不能再写 <constant>,只能放 <package>,常量写在主文件里,否则加载顺序会让你怀疑人生。
问:Struts2 配置文件的加载顺序到底谁说了算?
由 struts.configuration.files 常量和 web.xml 的 config 初始化参数共同决定,默认顺序是 struts-default.xml、struts-plugin.xml、struts.xml、struts.properties,后加载的覆盖先加载的,官方配置参考文档(Apache 软件基金会)里有完整清单。
