struts2 通过源码了解action生命周期过程

通过一个简单的项目,使用debug模式,了解struts2action的处理过程。

首先看下struts2 的组织结构


通过上图,在Struts2中一个请求的生存周期包括:

1.    用户发送请求 : 用户为访问资源向服务器发送请求.

2.    FilterDispatcher决定适当的action : FilterDispatcher接受请求然后决定调用适当的action

3.    调用拦截器 : 配置拦截器来应用常用的功能如工作流,验证,文件上传等,都是自动应用于请求的.

4.    action的执行 : 然后action将被执行来调用诸如存储数据、检索数据之类的数据库相关操作.

5.    呈递输出 : 结果呈递到输出

6.    返回请求 : 请求通过拦截器按照相反的顺序返回,返回的请求可以允许我们执行一些清理或额外的处理

7.    向用户展示结果 : 控制权最终回归到输出结果至用户浏览器的Servlet容器


下面具体对源码进行了解:

一个http请求传过来,struts首先会调用FilterDispatcher类的doFilter()方法,通过它匹配一个request到action的映射关系,然后把action的处理委派给Dispatcher类的serviceAction()方法。

 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        showDeprecatedWarning();

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        ServletContext servletContext = getServletContext();

        String timerKey = "FilterDispatcher_doFilter: ";
<span style="white-space:pre">		</span>//找到映射关系
            dispatcher.serviceAction(request, response, mapping);

        }
    }
在Dispatcher类的serviceAction()中会载入action类并调用相应的方法执行。具体步骤:

1. 创建action的长下文环境

2. 通过action的名字和命名空间创建ActionProxy代理

3. 执行action的方法


 public void serviceAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping)
            throws ServletException {
<span style="white-space:pre">	</span>
       //创建上下文环境
        Map<String, Object> extraContext = createContextMap(request, response, mapping);

        // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
        ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
        boolean nullStack = stack == null;
        if (nullStack) {
            ActionContext ctx = ActionContext.getContext();
            if (ctx != null) {
                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();
            /创建action的代理
            ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                    namespace, name, method, extraContext, true, false);

            request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

            // if the ActionMapping says to go straight to a result, do it!
            if (mapping.getResult() != null) {
                Result result = mapping.getResult();
                result.execute(proxy.getInvocation());
            } else {//执行action的方法
                proxy.execute();
            }
        } 
    }

在创建代理的过程中,有一些准备工作,如通过配置文件会得到具体调用那个方法,初始化invocation的一些内容,包括:

1.  得到上下文环境Actioncontext

2. 通过反射机制,创建action类。

3. 通过配置文件获取拦截器。

public void init(ActionProxy proxy) {
        this.proxy = proxy;
        Map<String, Object> contextMap = createContextMap();

        // Setting this so that other classes, like object factories, can use the ActionProxy and other
        // contextual information to operate
        ActionContext actionContext = ActionContext.getContext();

        if (actionContext != null) {
            actionContext.setActionInvocation(this);
        }
        //创建action
        createAction(contextMap);

        if (pushAction) {
            stack.push(action);
            contextMap.put("action", action);
        }

        invocationContext = new ActionContext(contextMap);
        invocationContext.setName(proxy.getActionName());
         、、
        // get a new List so we don't get problems with the iterator if someone changes the list
        List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());
        interceptors = interceptorList.iterator();
    }

proxy.execute()的实现,主要是通过调用代理类invocation的invoke方法来完成的,这里就包括了一次调用各个拦截器,然后是action,result等。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值