Struct2中自定义的Filter失效问题
解决办法,把自定义的Filter配置放在struct2前:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<filter>
<filter-name>LogFilter</filter-name>
<filter-class>com.*.LogFilter</filter-class>
</filter>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>
将自定义Filter放在Struts2之后失效的源码分析:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
// 预处理请求(编码、ActionContext 等)
prepare.setEncodingAndLocale(request, response);
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
// 判断是否排除某些 URL 模式
if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response); // 放行请求到后续 Filter
} else {
// 包装请求(例如处理文件上传)
request = prepare.wrapRequest(request);
// 查找 ActionMapping
ActionMapping mapping = prepare.findActionMapping(request, response, true);
if (mapping == null) {
// 尝试处理静态资源,若失败则继续 Filter 链
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response); // 继续 Filter 链
}
} else {
// 直接执行 Action 并生成响应,不调用 chain.doFilter()
execute.executeAction(request, response, mapping);
}
}
} finally {
prepare.cleanupRequest(request);
}
}
1. 关键逻辑分析
(1)当 ActionMapping 存在时
-
如果
findActionMapping()
返回有效的ActionMapping
(即请求匹配到一个 Struts2 Action),则直接调用execute.executeAction()
方法处理请求。 -
此时不再调用
chain.doFilter()
,导致后续 Filter 链终止。
(2)当 ActionMapping 不存在时
-
若请求未被排除(
excludedPatterns
)且不是静态资源,则调用chain.doFilter()
继续执行后续 Filter。 -
若请求是静态资源(如配置的
/static
路径),则直接处理并返回响应,同样终止 Filter 链。
2. 源码中的设计意图
Struts2 的核心过滤器通过以下设计控制请求流程:
-
优先处理 Action 请求:一旦匹配到 Action,直接处理并返回响应,无需后续 Filter 参与。
-
静态资源处理:直接响应静态资源(如 JS、CSS),避免无关 Filter 执行。
-
拦截器链替代 Filter 链:Struts2 的拦截器(Interceptor)机制替代了传统 Filter 链的职责,因此核心 Filter 可能在处理完成后主动终止 Filter 链。