Board logo

标题: Struts2 内核之我见(3) [打印本页]

作者: look_w    时间: 2018-9-23 12:53     标题: Struts2 内核之我见(3)

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);
         }
     }
}






欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0