zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    HDU——1061Rightmost Digit(高次方,找规律)
    HDU——1019Least Common Multiple(多个数的最小公倍数)
    HDU——1013Digital Roots(九余数定理)
    HDU——1020Encoding(水题,string过)
    HDU——2093考试排名(string类及其函数的运用以及istringstream)
    廖雪峰Java3异常处理-2断言和日志-4使用Log4j
    廖雪峰Java3异常处理-2断言和日志-3使用Commons Logging
    廖雪峰Java3异常处理-2断言和日志-2使用JDK Logging
    廖雪峰Java3异常处理-2断言和日志-1使用断言
    Charles问题
  • 原文地址:https://www.cnblogs.com/Cratical/p/2677433.html
Copyright © 2011-2022 走看看