`
翟健
  • 浏览: 3479 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
社区版块
存档分类
最新评论

struts2执行过程浅析

    博客分类:
  • java
阅读更多
struts2的执行过程
1.首先进入StrutsPrepareAndExecuteFilter这个filter,执行doFilter方法
public void doFilter(ServletRequest req,ServletResponse res, FilterChain chain) 
throws IOException, ServletException {
   HttpServletRequest request = (HttpServletRequest) req;
   HttpServletResponse response = (HttpServletResponse) res;
        try {
			  //设置Encoding和Locale
            prepare.setEncodingAndLocale(request, response);
            prepare.createActionContext(request, response);
			 //将dispatcher绑定到当前线程
            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);
        }
    }

2.做完所有准备工作之后,初始化后的ExecuteOperations执行executeAction
public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException {
        dispatcher.serviceAction(request, response, servletContext, mapping);}

3.ExecuteOperations实际上是个代理类,内部调用dispatcher的serviceAction方法
在这个方法中首先拿到当前线程(ActionContext维护一个ThreadLocal),并且得到valueStack,接着得到映射中的信息(namespace,method,name),根据这些信息创建代理对象
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,
                              ActionMapping mapping) throws ServletException {
        Map<String, Object> extraContext = createContextMap(request, response, mapping, context);
        ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
        boolean nullStack = stack == null;
        if (nullStack) {
			  //得到当前线程的ActionContext
            ActionContext ctx = ActionContext.getContext();
            if (ctx != null) {
				  //得到ValueStack
                stack = ctx.getValueStack();
            }
        }
        if (stack != null) {
            extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
        }
        String timerKey = "Handling request from Dispatcher";
        try {
            UtilTimerStack.push(timerKey);
			  //得到映射中的信息
            String namespace = mapping.getNamespace();
            String name = mapping.getName();
            String method = mapping.getMethod();

            Configuration config = configurationManager.getConfiguration();
			 //创建一个代理对象
            ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                    namespace, name, method, extraContext, true, false);request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
            if (mapping.getResult() != null) {
                Result result = mapping.getResult();
                result.execute(proxy.getInvocation());
            } else {
				  //开始执行
                proxy.execute();
            }
            if (!nullStack) {
  request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
            }
        } catch (ConfigurationException e) {
        	if(devMode) {
                String reqStr = request.getRequestURI();
                if (request.getQueryString() != null) {
                    reqStr = reqStr + "?" + request.getQueryString();
                }
                LOG.error("Could not find action or result\n" + reqStr, e);
            }
        	else {
                    if (LOG.isWarnEnabled()) {
        		LOG.warn("Could not find action or result", e);
                    }
        	}
            sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
        } catch (Exception e) {
            sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
        } finally {
            UtilTimerStack.pop(timerKey);
        }
}

4.以下是具体创建代理对象和ActionInvocation的过程
DefaultActionProxyFactory(createActionProxy())
public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext) {
        //创建ActionInvocation
        ActionInvocation inv = new DefaultActionInvocation(extraContext, true);
        container.inject(inv);
        return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
    }
    public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) {
        //创建proxy
        StrutsActionProxy proxy = new StrutsActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);
        container.inject(proxy);
        proxy.prepare();
        return proxy;
}

4.1.代理对象的准备工作 DefaultActionProxy(prepare())
protected void prepare() {
        String profileKey = "create DefaultActionProxy: ";
        try {
            UtilTimerStack.push(profileKey);
            config = configuration.getRuntimeConfiguration().getActionConfig(namespace, actionName);
            if (config == null && unknownHandlerManager.hasUnknownHandlers()) {
                config = unknownHandlerManager.handleUnknownAction(namespace, actionName);
            }
            if (config == null) {
                throw new ConfigurationException(getErrorMessage());
            }
            resolveMethod();
            if (!config.isAllowedMethod(method)) {
                throw new ConfigurationException("Invalid method: " + method + " for action " + actionName);
            }
			  //actionInvocation的初始化
            invocation.init(this);
        } finally {
            UtilTimerStack.pop(profileKey);
        }
    }


4.2.proxy会初始化actionInvocation,其中包括上下文环境,值栈,以及拦截器
 DefaultActionInvocation(init()) 
public void init(ActionProxy proxy) {
        this.proxy = proxy;
        Map<String, Object> contextMap = createContextMap();
        ActionContext actionContext = ActionContext.getContext();
        if (actionContext != null) {
			  //将actionInvocation放入上下文环境中
            actionContext.setActionInvocation(this);
        }
        createAction(contextMap);
        if (pushAction) {
			 //将action置于valueStack中
            stack.push(action);
            contextMap.put("action", action);
        }
		 //创建invocationContext上下文
        invocationContext = new ActionContext(contextMap);
        invocationContext.setName(proxy.getActionName());
		 //初始化拦截器
        List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());
        interceptors = interceptorList.iterator();
    }

5.当所有的准备工作都做好之后,回到ExecuteOperations中,执行proxy.execute()方法,实际执行的是StrutsActionProxy的execute()方法
public String execute() throws Exception {
      ActionContext previous = ActionContext.getContext();               
     ActionContext.setContext(invocation.getInvocationContext());
        try {
	//生成的actionInvocation开始执行
            return invocation.invoke();
        } finally {
            if (cleanupContext)            
                ActionContext.setContext(previous);
        }
    }

6.此时actionInvocation开始执行。
public String invoke() throws Exception {
        String profileKey = "invoke: ";
        try {
            UtilTimerStack.push(profileKey);
            if (executed) {
                throw new IllegalStateException("Action has already executed");
            }
	//依次执行每个拦截器 actionInvocation相当于一个中转站,每个拦截器执
//行完,又返回actionInvocation执行    
         if (interceptors.hasNext()) {
                final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack.push(interceptorMsg);
                try {
                   resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
                            }
                finally {
                    UtilTimerStack.pop(interceptorMsg);
                }
	} else {
                //所有拦截器执行完之后调用invokeActionOnly方法
                resultCode = invokeActionOnly();
            }
            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);
                        }
                    }
                }
                if (proxy.getExecuteResult()) {
                    //根据得到的字符串跳转到对应的页面
                    executeResult();
                }
                executed = true;
            }
            return resultCode;
        }
        finally {
            UtilTimerStack.pop(profileKey);
        }
}

7.1.所有拦截器执行完之后调用invokeActionOnly
public String invokeActionOnly() throws Exception {
        return invokeAction(getAction(), proxy.getConfig());
    }
protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception {
		 //得到action类中调用方法的名称
        String methodName = proxy.getMethod();
        if (LOG.isDebugEnabled()) {
            LOG.debug("Executing action method = " + actionConfig.getMethodName());
        }
        String timerKey = "invokeAction: " + proxy.getActionName();
        try {
            UtilTimerStack.push(timerKey);
            boolean methodCalled = false;
            Object methodResult = null;
            Method method = null;
            try {
                method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY);
            } catch (NoSuchMethodException e) {
                try {
                    String altMethodName = "do" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
		//构成Method对象
                    method = getAction().getClass().getMethod(altMethodName, EMPTY_CLASS_ARRAY);
                } catch (NoSuchMethodException e1) {
                    if (unknownHandlerManager.hasUnknownHandlers()) {
                        try {
                            methodResult = unknownHandlerManager.handleUnknownMethod(action, methodName);
                            methodCalled = true;
                        } catch (NoSuchMethodException e2) {
                            throw e;
                        }
                    } else {
                        throw e;
                    }
                }
            }
            if (!methodCalled) {
		//执行方法得到返回对对象(实际是字符串)
                methodResult = method.invoke(action, EMPTY_OBJECT_ARRAY);
            }
            return saveResult(actionConfig, methodResult);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("The " + methodName + "() is not defined in action " + getAction().getClass() + "");
        } catch (InvocationTargetException e) {
            Throwable t = e.getTargetException();
            if (actionEventListener != null) {
                String result = actionEventListener.handleException(t, getStack());
                if (result != null) {
                    return result;
                }
            }
            if (t instanceof Exception) {
                throw (Exception) t;
            } else {
                throw e;
            }
        } finally {
            UtilTimerStack.pop(timerKey);
        }
}
//保存后面要用到的字符串,否则返回
protected String saveResult(ActionConfig actionConfig, Object methodResult) {
        if (methodResult instanceof Result) {
            this.explicitResult = (Result) methodResult;
            container.inject(explicitResult);
            return null;
        } else {
            return (String) methodResult;
        }
    }

8.得到result对象并跳转到相应页面
private void executeResult() throws Exception {
        result = createResult();

        String timerKey = "executeResult: " + getResultCode();
        try {
            UtilTimerStack.push(timerKey);
            if (result != null) {
	     //封装的result执行
                result.execute(this);
            } else if (resultCode != null && !Action.NONE.equals(resultCode)) {
                throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()
                        + " and result " + getResultCode(), proxy.getConfig());
            } else {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("No result returned for action " + getAction().getClass().getName() + " at " + proxy.getConfig().getLocation());
                }
            }
        } finally {
            UtilTimerStack.pop(timerKey);
        }
    }

根据字符串跳转到相应的页面 StrutsResultSupport(execute())
public void execute(ActionInvocation invocation) throws Exception {
        lastFinalLocation = conditionalParse(location, invocation);
        doExecute(lastFinalLocation, invocation);
    }
ServletDispatcherResult(doExecute())
public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Forwarding to location " + finalLocation);
        }
        PageContext pageContext = ServletActionContext.getPageContext();
        if (pageContext != null) {
            pageContext.include(finalLocation);
        } else {
            HttpServletRequest request = ServletActionContext.getRequest();
            HttpServletResponse response = ServletActionContext.getResponse();
            RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);
            if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) {
                String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
                Map<String, Object> parameters = getParameters(invocation);
                Map<String, Object> queryParams = urlHelper.parseQueryString(queryString, true);
                if (queryParams != null && !queryParams.isEmpty())
                    parameters.putAll(queryParams);
            }
            if (dispatcher == null) {
                response.sendError(404, "result '" + finalLocation + "' not found");
                return;
            }
            Boolean insideActionTag = (Boolean) ObjectUtils.defaultIfNull(request.getAttribute(StrutsStatics.STRUTS_ACTION_TAG_INVOCATION), Boolean.FALSE);
            if (!insideActionTag && !response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) {
   request.setAttribute("struts.view_uri", finalLocation);
                request.setAttribute("struts.request_uri", request.getRequestURI());
                dispatcher.forward(request, response);
            } else {
                dispatcher.include(request, response);
            }
        }
    }

注:本文仅涉及struts2的执行过程,具体的细节和详细的步骤暂不讨论!
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics