FilterDispatcher 的工作流程前面讲过 Struts2 的核心控制器为 filter,对于一个控制器,核心的生命周期方法有 3 个。
清单 2. 过滤器生命周期方法1
2
3
4
5
6
7
| // 初始化,加载资源
public void init(FilterConfig filterConfig) throws ServletException
// 销毁,回收资源
public void destroy()
// 过滤
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException
|
分别讲解 FilterDispatcher 3 个方法
init 方法:初始化过滤器,创建默认的 dispatcher 对象并且设置静态资源的包。
清单 3. init 方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| public void init(FilterConfig filterConfig) throws ServletException {
try {
this.filterConfig = filterConfig;
// 初始化日志器
initLogging();
dispatcher = createDispatcher(filterConfig);
dispatcher.init();
dispatcher.getContainer().inject(this);
staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));
} finally {
ActionContext.setContext(null);
}
}
|
destory 方法:核心业务是调用 dispatcher.cleanup() 方法。cleanup 释放所有绑定到 dispatcher 实例的资源,包括销毁所有的拦截器实例,本方法在后面有源代码讨论。
清单 4. destory 方法1
2
3
4
5
6
7
8
9
10
11
| public void destroy() {
if (dispatcher == null) {
log.warn("something is seriously wrong, Dispatcher is not initialized (null) ");
} else {
try {
dispatcher.cleanup();
} finally {
ActionContext.setContext(null);
}
}
}
|
doFilter 方法:doFilter 方法的出口有 3 个分支。
首先过滤器尝试把 request 匹配到一个 Action mapping(action mapping 的解释见最后的总结)。若有匹配,执行 path1。否则执行 path2 或者 3。
path 1调用 dispatcher. serviceAction() 方法处理 Action 请求
如果找到了 mapping,Action 处理被委托给 dispatcher 的 serviceAction 方法。如果 Action 处理失败了,doFilter 将会通过 dispatcher 创建一个错误页。
path 2处理静态资源
如果请求的是静态资源。资源被直接拷贝到 response 对象,同时设置对应的头信息。
path 3无处理直接通过过滤器,访问过滤器链的下个资源。
清单 5. doFilter 方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
| public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
ServletContext servletContext = getServletContext();
String timerKey = "FilterDispatcher_doFilter: ";
try {
//1 处理前的准备
//1.1 创建值栈对象,值栈包含 object stack 和 context map 两个部分。
ValueStack stack =
dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
//1.2 创建 actionContext。
ActionContext ctx = new ActionContext(stack.getContext());
ActionContext.setContext(ctx);
UtilTimerStack.push(timerKey);
//1.3 准备和包装 request
request = prepareDispatcherAndWrapRequest(request, response);
ActionMapping mapping;
//2 根据请求路径查找 actionMapping
try {
mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());
} catch (Exception ex) {
log.error("error getting ActionMapping", ex);
dispatcher.sendError(request, response, servletContext,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
return;
}
//3 当请求路径没有对应的 actionMapping,走第 2 和第 3 个出口
if (mapping == null) {
String resourcePath = RequestUtils.getServletPath(request);
if ("".equals(resourcePath) && null != request.getPathInfo()) {
resourcePath = request.getPathInfo();
}
if (staticResourceLoader.canHandle(resourcePath)) {
staticResourceLoader.findStaticResource(resourcePath, request, response);
} else {
chain.doFilter(request, response);
}
// 如果是第 2 和第 3 个出口 ,action 的处理到此结束。
return;
}
//3.1 路径 1,委托 dispatcher 的 serviceAction 进行处理
dispatcher.serviceAction(request, response, servletContext, mapping);
} finally {
try {
//4 清除 ActionContext
ActionContextCleanUp.cleanUp(req);
} finally {
UtilTimerStack.pop(timerKey);
}
}
}
|
|