`

WebWork执行流程

阅读更多
com.opensymphony.webwork下有两个类:public class ServletActionContext extends ActionContext implements WebWorkStatics;
这个类是静态工具类,其内的方法均依赖com.opensymphony.xwork.ActionContext类,而这个类提供了Action类的执行上下文.我们跟踪这个上下文的生命周期:

客户请求发送到Webserver,它将请求转发到Servlet容器,容器匹配一个Sertlet,然后调用其sevice()方法.在WebWork中这个servlet是ServletDispatcher,其中的serviceAction方法通过代理模式从WebWork进入到XWork对象世界,在那里对客户请求数据对象执行处理,通过执行根据配置上下文和执行上下文设置的Action和result把响应数据发回客户端,发回的动作可能发生在Result中,也可能发生在Interceptor中.开始代码之旅.

下面是serviceAction代码:



















public void serviceAction(HttpServletRequest request, HttpServletResponse response, String namespace, String actionName, Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap) {
        HashMap extraContext = createContextMap(requestMap, parameterMap, sessionMap, applicationMap, request, response, getServletConfig());
        extraContext.put(SERVLET_DISPATCHER, this);



















        // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
        OgnlValueStack stack = (OgnlValueStack) request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY);
        if (stack != null) {
            extraContext.put(ActionContext.VALUE_STACK,new OgnlValueStack(stack));
        }
        try {
            ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
            request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack());
            proxy.execute();
            // If there was a previous value stack then set it back onto the request
            if (stack != null){
                request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY,stack);
            }
        } catch (ConfigurationException e) {
            log.error("Could not find action", e);
            sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e);
        } catch (Exception e) {
            log.error("Could not execute action", e);
            sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
        }
    }



















方法createContextMap执行数据的包装:



















    public static HashMap createContextMap(Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap, HttpServletRequest request, HttpServletResponse response, ServletConfig servletConfig) {
        HashMap extraContext = new HashMap();
        extraContext.put(ActionContext.PARAMETERS, parameterMap);
        extraContext.put(ActionContext.SESSION, sessionMap);
        extraContext.put(ActionContext.APPLICATION, applicationMap);
        extraContext.put(ActionContext.LOCALE, (locale == null) ? request.getLocale() : locale);



















        extraContext.put(HTTP_REQUEST, request);
        extraContext.put(HTTP_RESPONSE, response);
        extraContext.put(SERVLET_CONFIG, servletConfig);
        extraContext.put(ComponentInterceptor.COMPONENT_MANAGER, request.getAttribute(ComponentManager.COMPONENT_MANAGER_KEY));



















        // helpers to get access to request/session/application scope
        extraContext.put("request", requestMap);
        extraContext.put("session", sessionMap);
        extraContext.put("application", applicationMap);
        extraContext.put("parameters", parameterMap);



















        AttributeMap attrMap = new AttributeMap(extraContext);
        extraContext.put("attr", attrMap);



















        return extraContext;
    }




















众所周知,不仅WebWork能使用XWork,而且还可以有类似的FtpWork,MailWork,JMSWork能够替代WebWork来使用Xwork,为什么能够这样,因为Xwork的使用方式.在上面的serviceAction方法中:



















ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
            request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack());
            proxy.execute();
这些代码就是这种方式的体现:动作代理-动作调用-具体的动作.为使客户代码不绑定到特定代理,XWork使用了一个工厂模式,提供工厂类 ActionProxyFactory.



















方法createActionProxy实际调用导致一个ActionProxy接口的缺省实现DefaultActionProxy被实例化:



















它的构造器是:



















    protected ActionInvocation invocation;



















    protected DefaultActionProxy(String namespace, String actionName, Map extraContext, boolean executeResult) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Creating an DefaultActionProxy for namespace " + namespace + " and action name " + actionName);
        }

        this.actionName = actionName;
        this.namespace = namespace;
        this.executeResult = executeResult;
        this.extraContext = extraContext;

        config = ConfigurationManager.getConfiguration().getRuntimeConfiguration().getActionConfig(namespace, actionName);

        if (config == null) {
            String message;

throw new ConfigurationException(message);
        }

        prepare();
    }



















    protected void prepare() throws Exception {



















        //创建ActionInvocation 实例化的仍然是由代理工厂类的工厂方法进行,实例化该接口的缺省         实现DefaultActionInvocation.



















        invocation = ActionProxyFactory.getFactory().createActionInvocation(this, extraContext);
    }



















下面是proxy.execute()的细节:

    public String execute() throws Exception {
        ActionContext nestedContext = ActionContext.getContext();
        ActionContext.setContext(invocation.getInvocationContext());

        String retCode = null;

        try {

            retCode = invocation.invoke();
        } finally {

            ActionContext.setContext(nestedContext);
        }

        return retCode;

    }

最后,看看这个类: DefaultActionInvocation类的invoke方法是如何处理extraContext,先看初始化过程,从构造器开始:

    protected DefaultActionInvocation(ActionProxy proxy, Map extraContext, boolean pushAction) throws Exception {

        this.proxy = proxy;

        this.extraContext = extraContext;

        this.pushAction = pushAction;

        init();

}

方法init定义,把extraContext转换到invocationContext中,并获得拦截器清单.



















    private void init() throws Exception {

        Map contextMap = createContextMap();

        createAction();



















        if (pushAction) {

            stack.push(action);

        }

        invocationContext = new ActionContext(contextMap);

        invocationContext.setName(proxy.getActionName());

        List interceptorList = new ArrayList(proxy.getConfig().getInterceptors());

        interceptors = interceptorList.iterator();

}

在下面这个方法中获得动作上下文contextMap,并把extraContext包含其中.

    protected Map createContextMap() {

        Map contextMap;

    if ((extraContext!=null)&& (extraContext.containsKey(ActionContext.VALUE_STACK))) {

            // In case the ValueStack was passed in

            stack = (OgnlValueStack) extraContext.get(ActionContext.VALUE_STACK);

            if (stack == null) {

                throw new IllegalStateException("There was a null Stack set into the extra params.");

            }

            contextMap = stack.getContext();

        } else {

            // create the value stack

            // this also adds the ValueStack to its context

            stack = new OgnlValueStack();

            // create the action context

            contextMap = stack.getContext();

        }

        // put extraContext in

        if (extraContext != null) {

            contextMap.putAll(extraContext);

        }

        //put this DefaultActionInvocation into the context map

        contextMap.put(ActionContext.ACTION_INVOCATION, this);

        return contextMap;

    }

    protected void createAction() {

        // load action

        try {

            action = ObjectFactory.getObjectFactory().buildAction(proxy.getConfig());

        } catch (InstantiationException e) {

            throw new XworkException("Unable to intantiate Action!", e);

        } catch (IllegalAccessException e) {

            throw new XworkException("Illegal access to constructor, is it public?", e);

        } catch (ClassCastException e) {

            throw new XworkException("Action class " + proxy.getConfig().getClassName() + " does not implement " + Action.class.getName(), e);

        } catch (Exception e) {

            String gripe = "";


            if (proxy == null) {

                gripe = "Whoa!  No ActionProxy instance found in current ActionInvocation.  This is bad ... very bad";

            } else if (proxy.getConfig() == null) {

                gripe = "Sheesh.  Where'd that ActionProxy get to?  I can't find it in the current ActionInvocation!?";

            } else if (proxy.getConfig().getClassName() == null) {

                gripe = "No Action defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'";

            } else {

                gripe = "Unable to instantiate Action, " + proxy.getConfig().getClassName() + ",  defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'";

            }


            gripe += (((" -- " + e.getMessage()) != null) ? e.getMessage() : " [no message in exception]");

            throw new XworkException(gripe, e);

        }

    }

初始化结束了, 接下来看看invocation.invoke()到底做了什么:



















    public String invoke() throws Exception {

        if (executed) {

            throw new IllegalStateException("Action has already executed");

        }

        if (interceptors.hasNext()) {

            Interceptor interceptor = (Interceptor) interceptors.next();

                     在这个类中,并没有调用getResult(),因为这个方法是由某些拦截器调用的,例如: ExecuteAndWaitInterceptor, TokenSessionStoreInterceptor,如果自己需要,也可以创建自己的拦截器,并在其中访问它.



















通过Interceptor接口中的String intercept(ActionInvocation invocation) throws Exception可以看到, 参数invocation已经携带了所有能处理的数据了.



















            resultCode = interceptor.intercept(this);



















        } else {

            resultCode = invokeAction(getAction(), proxy.getConfig());



















        }

        if (!executed) {

            if (preResultListeners != null) {

                for (Iterator iterator = preResultListeners.iterator();

                     iterator.hasNext();) {

                    PreResultListener listener = (PreResultListener) iterator.next();

                    listener.beforeResult(this, resultCode);

                }

            }

            now execute the result, if we're supposed to,如果不期望执行Result,那么在代理中设置proxy.getExecuteResult(false)即可,有时候是需要这样的,如TokenSessionStoreInterceptor;



















            if (proxy.getExecuteResult()) {

                executeResult();



















            }

            executed = true;



















        }

        return resultCode;

}


在这个方法中,调用了Result接口的方法execute(ActionInvocation),当该方法返回时一个请求响应回合就完成了.



















private void executeResult() throws Exception {

        result = createResult();

        if (result != null) {

            result.execute(this);



















        } else if (!Action.NONE.equals(resultCode)) {

            LOG.warn("No result defined for action " + getAction().getClass().getName() + " and result " + getResultCode());

        }

    }

public Result createResult() throws Exception {

        Map results = proxy.getConfig().getResults();

        ResultConfig resultConfig = (ResultConfig) results.get(resultCode);

        Result newResult = null;


        if (resultConfig != null) {

            try {

                newResult = ObjectFactory.getObjectFactory().buildResult(resultConfig);

            } catch (Exception e) {

                LOG.error("There was an exception while instantiating the result of type " + resultConfig.getClassName(), e);

                throw e;

            }

        }

        return newResult;

}


public Result getResult() throws Exception {

        Result returnResult = result;

        // If we've chained to other Actions, we need to find the last result

        while (returnResult instanceof ActionChainResult) {

            ActionProxy aProxy = ((ActionChainResult) returnResult).getProxy();

            if (aProxy != null) {

                Result proxyResult = aProxy.getInvocation().getResult();

                if ((proxyResult != null) && (aProxy.getExecuteResult())) {

                    returnResult = proxyResult;

                } else {

                    break;

                }

            } else {

                break;

            }

        }

        return returnResult;

}


protected String invokeAction(Action action, ActionConfig actionConfig) throws Exception {

        if (proxy.getConfig().getMethodName() == null) {

            return getAction().execute();

        } else {

            if (LOG.isDebugEnabled()) {

                LOG.debug("Executing action method = " + actionConfig.getMethodName());

            }

            try {

                Method method = actionConfig.getMethod(action.getClass());

                if (action instanceof Proxy) {

                    try {

                        return (String) Proxy.getInvocationHandler(action).invoke(action, method, new Object[0]);

                    } catch (Throwable throwable) {

                        throwable.printStackTrace();

                        throw new Exception("Error invoking on proxy: " + throwable.getMessage());

                    }

                } else {

                    return (String) method.invoke(action, new Object[0]);

                }

            } catch (NoSuchMethodException e) {

                throw new IllegalArgumentException("Method '" + actionConfig.getMethodName() + "()' is not defined in action '" + getAction().getClass() + "'");

            } catch (InvocationTargetException e) {

                // We try to return the source exception.

                Throwable t = e.getTargetException();

                if (t instanceof Exception) {

                    throw (Exception) t;

                } else {

                    throw e;

                }

            }

        }

    }

}


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/keepeye/archive/2005/06/16/390257.aspx
分享到:
评论

相关推荐

    webwork的工作流程

    WebWork 的工作流程主要涉及以下几个关键组件: 1. **Action**: - Action 类是业务逻辑的载体,负责处理用户请求并返回结果。Action 类通常会实现一个特定的接口,如`com.opensymphony.xwork2.ActionSupport`,并...

    WebWork_开发指南

    - **Web 应用部署结构**:为了演示 WebWork2 的工作流程,选择了一个典型的登录流程为例。虽然这个例子简单,但它涵盖了 WebWork 框架的许多关键技术点。 #### 三、WebWork 工作流程解析 - **MVC 架构解析**:...

    WebWork深入浅出.doc

    5. 页面流程管理:WebWork的Action链和ActionForward可以管理页面流程。 6. 模块化管理:Action和视图的分离使得Web应用能够模块化。 7. 灵活可扩展性:支持多种展现技术,易于与其他业务层或数据层框架集成。 8. ...

    WebWork2.0讲解说明

    WebWork2.0是一款基于Java的企业级Web应用框架,它为开发者提供了强大的MVC(Model-View-Controller)架构支持,旨在简化Web应用程序的开发流程,提高代码的可维护性和可扩展性。本讲解将围绕WebWork2.0的核心概念、...

    webwork

    在深入研究WebWork源码时,开发者可以了解其内部的工作原理,包括请求处理流程、模型绑定、拦截器链的执行、异常处理机制等,这对于提高编程技能和理解MVC框架的设计模式非常有帮助。此外,查看`displaytag-1.0`源码...

    webwork资源

    WebWork的执行流程涉及到ActionProxy和ActionInvocation两个概念。ActionProxy负责管理Action的生命周期,包括创建和执行Action。而ActionInvocation则代表了Action执行的状态,它持有Action实例和一系列Interceptor...

    webwork源码底层实现

    4. **Interceptors(拦截器)**:WebWork引入了拦截器的概念,它们在Action执行前后执行,可以实现通用的功能,如权限检查、日志记录等。在源码中,你会看到这些拦截器的实现。 5. **Value Stack(值栈)**:...

    webwork2开发指南

    1. 动作拦截器(Interceptors):拦截器可以对动作执行前后的流程进行增强,如权限检查、日志记录等。通过配置,可以灵活地组合和应用拦截器。 2. 数据验证(Validation):WebWork2提供了强大的数据验证机制,可以...

    webwork详细讲解.doc

    WebWork的工作流程主要包含以下几个步骤: 1. **接收HTTP请求**:当用户通过浏览器发送HTTP请求时,请求首先被服务器接收。 2. **请求解析**:服务器将请求传递给WebWork的`ServletDispatcher`,`ServletDispatcher...

    WebWork 教程

    通过构建这个简单的示例,开发者不仅能够理解WebWork的基本工作流程,还能接触到Action、ActionContext、ResultType等关键概念。Action是业务逻辑的主要承载者,ActionContext则负责管理Action的执行上下文,...

    webwork.pdf

    WebWork 2.0引入了Action驱动模式,这一模式允许开发者定义不同的Action来处理不同的用户请求,每个Action可以执行特定的业务逻辑并返回相应的结果。与传统的Servlet模型相比,Action驱动模式提供了更清晰的代码结构...

    webwork中文参考手册

    3. **拦截器(Interceptor)**:类似于AOP(面向切面编程),WebWork允许开发者定义拦截器来处理共性任务,如日志记录、事务管理、权限检查等,这些任务可以在动作执行前后自动进行。 4. **强大的表单处理**:...

    webwork 2.2.4开发指南

    2. Action与ActionForm:Action是WebWork中的控制器组件,处理用户的请求,执行相应的业务逻辑,并将结果传递给视图。ActionForm则用于封装请求参数,作为模型与控制器之间的数据载体。 二、WebWork架构 1. 请求...

    webwork2.1.7

    3. **拦截器(Interceptors)**:WebWork引入了拦截器的概念,允许在Action执行前后插入自定义逻辑,如日志、事务管理等,增强了可扩展性。 4. **OGNL(Object-Graph Navigation Language)**:WebWork使用OGNL作为...

    webwork的api

    这些配置可以控制Action的执行流程,如错误处理、国际化等。 7. **ActionForm**:虽然在WebWork 2.x版本中,ActionForm的概念已经被弱化,但在早期版本中,ActionForm用于封装表单数据并传递到Action中。现在,可以...

    WebWork入门教程[创建你第一个WebWork action]

    让我们深入探讨WebWork的核心概念、Action的创建以及如何实现基本的流程控制。 **WebWork核心概念** 1. **Action**: 在WebWork中,Action是业务逻辑的主要载体。它负责接收来自视图层(如JSP)的请求,处理业务...

    webwork2官方文档中文版

    1. **动作映射(Action Mapping)**:WebWork2通过配置文件定义动作映射,将URL请求映射到特定的Java类方法,简化了请求处理流程。 2. **强大的拦截器(Interceptor)机制**:拦截器可以在动作执行前后执行预处理和...

    webwork中文文档

    **结果类型**:WebWork支持多种结果类型,如dispatcher、redirect、stream等,用于控制请求的处理流程和响应的方式。 ### WebWork框架的特点 - **灵活性**:WebWork提供了丰富的配置选项和插件系统,使得开发者...

    webwork2实例源代码

    4. **Interceptor(拦截器)**:拦截器是WebWork2的一个重要特性,它们是可复用的代码片段,可以插入到Action执行流程中,实现如日志记录、权限检查、事务管理等功能。通过配置,可以灵活地调整拦截器链。 5. **...

    webwork简单例子

    WebWork是一个基于Java的MVC(Model-View-Controller)框架,它在早期的Web开发中扮演了...通过研究这个MyEclipse项目,你可以深入理解WebWork的生命周期、数据绑定和控制流程,为后续的Java EE开发打下坚实的基础。

Global site tag (gtag.js) - Google Analytics