Struts学习笔记(启动过程)

     最近学习了一下Struts2,之前用过1,大致了解这个框架是什么东西,但是很少用到,现在有时间,正好学学它。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这一点跟1完全不一样,而且以职责链模式设计的拦截器可谓Struts2的基石,异常处理,国际化等等处理都在拦截器的实现中完成了。

     Struts2支持多种表达式语言(OGNL,JSTL,Groovy还有Velocity,第一种是默认),印象中1中取值让人很头大,jsp中的代码也是乱的不行,到了2的时候,OGNL相当方便,一句<s:property value="xx" />就足矣了,然后再弄明白#、%和$这仨符号在什么情况下用,表达式这块就ok了,剩下不会的用到的时候看官方文档。

     专注看了下拦截器的过程,一个请求首先经由应用服务器(本人用的是resin)的分配,根据web.xml中配置filter发到StrutsPrepareAndExecuteFilter.doFilter()中,然后方法中设置编码和国际化,创建上下文,分配派发线程,准备Action映射等一系列初始化操作之后,来到了要执行下一步的地方。

 

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        try {
            prepare.setEncodingAndLocale(request, response);
            prepare.createActionContext(request, response);
            prepare.assignDispatcherToThread();
            if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
                chain.doFilter(request, response);
            } else {
                request = prepare.wrapRequest(request);
                ActionMapping mapping = prepare.findActionMapping(request, response, true);
                if (mapping == null) {
                    boolean handled = execute.executeStaticResourceRequest(request, response);
                    if (!handled) {
                        chain.doFilter(request, response);
                    }
                } else {
                    execute.executeAction(request, response, mapping); // 这里将要执行下一步过程
                }
            }
        } finally {
            prepare.cleanupRequest(request);
        }
    }

接下来在Dispatcher.serviceAction()中,会调用StrutsActionProxy.execute(),在这里面会调用DefaultActionInvocation.invoke(),此时就该拦截器出场了。

    public String invoke() throws Exception {
        String profileKey = "invoke: ";
        try {
            UtilTimerStack.push(profileKey);

            if (executed) {
                throw new IllegalStateException("Action has already executed");
            }

            if (interceptors.hasNext()) {
                final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack.push(interceptorMsg);
                try {
                    // interceptors是一个有序的拦截器列表,如果没有遍历完这个列表,程序将不会往下走,而是继续调用下一个拦截器的处理过程
                    // 在拦截器的intercept()方法中,会回调invocation.invoke()回到这个方法开始的时候,继续寻找下一个拦截器
                    resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
                }
                finally {
                    UtilTimerStack.pop(interceptorMsg);
                }
            } else {
                resultCode = invokeActionOnly();
            }

            // this is needed because the result will be executed, then control will return to the Interceptor, which will
            // return above and flow through again
            if (!executed) {
                if (preResultListeners != null) {
                    for (Object preResultListener : preResultListeners) {
                        PreResultListener listener = (PreResultListener) preResultListener;

                        String _profileKey = "preResultListener: ";
                        try {
                            UtilTimerStack.push(_profileKey);
                            listener.beforeResult(this, resultCode);
                        }
                        finally {
                            UtilTimerStack.pop(_profileKey);
                        }
                    }
                }

                // now execute the result, if we're supposed to
                if (proxy.getExecuteResult()) {
                    executeResult();
                }

                executed = true;
            }

            return resultCode;
        }
        finally {
            UtilTimerStack.pop(profileKey);
        }
    }

就像Struts2文档中的图一样,一层层的拦截器包围着待调用的action,等action返回之后,再一层层突破,实现双向拦截。

overview

 

在debug过程中打上断点,可以清楚地看到整个过程

image

 

这就是一个请求被拦截器层层过滤的大致过程,同样也是一个典型的职责链模式的精巧实现

转载于:https://www.cnblogs.com/Cratical/archive/2012/09/09/2677433.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值