读书人

struts2实施过程浅析

发布时间: 2013-08-04 18:26:16 作者: rapoo

struts2执行过程浅析
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的执行过程,具体的细节和详细的步骤暂不讨论!

读书人网 >编程

热点推荐