Struts请求处理过程简要描述

第一个环节是FilterDispatcher,过滤、包装请求,调用dispatcher的serviceAction方法。主要代码如下:

 1 UtilTimerStack.push(timerKey);
 2             request  =  prepareDispatcherAndWrapRequest(request, response);
 3             ActionMapping mapping;
 4              try   {
 5                mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());
 6            }
  catch  (Exception ex)  {
 7                LOG.error("error getting ActionMapping", ex);
 8                dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
 9                return;
10            }

11
12              if  (mapping  ==   null {
13                // there is no action in this request, should we look for a static resource?
14                String resourcePath = RequestUtils.getServletPath(request);
15
16                if ("".equals(resourcePath) && null != request.getPathInfo()) {
17                    resourcePath = request.getPathInfo();
18                }

19
20                if (serveStatic && resourcePath.startsWith("/struts")) {
21                    String name = resourcePath.substring("/struts".length());
22                    findStaticResource(name, request, response);
23                }
 else {
24                    // this is a normal request, let it pass through
25                    chain.doFilter(request, response);
26                }

27                // The framework did its job here
28                return;
29            }

30
31             dispatcher.serviceAction(request, response, servletContext, mapping);

可以看到这里面调用actionMapper找到了当前请求对应的actionMapping。然后就是dispatcher.serviceAction这个方法了。可以想象肯定是找到对应的Action类,执行相应的action方法。Dispatcher类的serviceAction方法主要代码如下:

 1 UtilTimerStack.push(timerKey);
 2             String namespace  =  mapping.getNamespace();
 3             String name  =  mapping.getName();
 4             String method  =  mapping.getMethod();
 5
 6             Configuration config  =  configurationManager.getConfiguration();
 7             ActionProxy proxy  =  config.getContainer().getInstance(ActionProxyFactory. class ).createActionProxy(
 8                     namespace, name, extraContext,  true false );
 9             proxy.setMethod(method);
10             request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
11
12              //  if the ActionMapping says to go straight to a result, do it!
13              if  (mapping.getResult()  !=   null {
14                Result result = mapping.getResult();
15                result.execute(proxy.getInvocation());
16            }
  else   {
17                proxy.execute();
18            }

19
20              //  If there was a previous value stack then set it back onto the request
21              if  (stack  !=   null {
22                request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
23            }

可以看到,其中从configurationManager中找到config,在利用config,通过ActionProxyFactory创建了合适的ActionProxy对象。后面就是判断如果当前的mapping存在result,那么直接返回result的执行结果,否则执行proxy.execute。前者的含义我猜是处理某些不需要Action的请求的时候用到的。具体要调用最后的Action中的什么方法也是在这个时候确定的(proxy.setMethod(....))。

上面的代码中,实际上是使用StrutsActionProxyFactory类的createActionProxy方法来创建ActionProxy的。这个方法如下:

1  ActionProxy proxy  =   new  StrutsActionProxy(namespace, actionName, extraContext, executeResult, cleanupContext);
2         container.inject(proxy);
3         proxy.prepare();
4          return  proxy;

可以看到创建proxy之后,调用了proxy的prepare方法,于是看DefaultActionProxy类的prepare方法中有这样的代码:

1 invocation  =   new  DefaultActionInvocation(objectFactory, unknownHandler,  this , extraContext,  true , actionEventListener);

实际上是创建了这个proxy中的invocation对象,这个对象很重要,后面是顺着这个对象的invoke方法去执行我们写的Action中的具体方法的。

回头再去看上面第二段代码中,创建proxy之后,调用了proxy的execute方法,这个里面写得很简单:

 1      public  String execute()  throws  Exception  {
 2        ActionContext previous = ActionContext.getContext();
 3        ActionContext.setContext(invocation.getInvocationContext());
 4        try {
 5            return invocation.invoke();
 6        }
 finally {
 7            if (cleanupContext)
 8                ActionContext.setContext(previous);
 9        }

10    }

就是执行了invocation的invoke方法。而这个invocation是哪里来的,我们也已经很清楚了。这个invocation类实际上是DefaultActionInvocation类的一个实例。其invoke方法如下:

 1 if  (executed)  {
 2                throw new IllegalStateException("Action has already executed");
 3            }

 4
 5              if  (interceptors.hasNext())  {
 6                final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
 7                UtilTimerStack.profile("interceptor: "+interceptor.getName(), 
 8                        new UtilTimerStack.ProfilingBlock<String>() {
 9                            public String doProfiling() throws Exception {
10                                resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
11                                return null;
12                            }

13                }
);
14            }
  else   {
15                resultCode = invokeActionOnly();
16            }

17
18              //  this is needed because the result will be executed, then control will return to the Interceptor, which will
19              //  return above and flow through again
20              if  ( ! executed)  {
21                if (preResultListeners != null{
22                    for (Iterator iterator = preResultListeners.iterator();
23                        iterator.hasNext();) {
24                        PreResultListener listener = (PreResultListener) iterator.next();
25                        
26                        String _profileKey="preResultListener: ";
27                        try {
28                            UtilTimerStack.push(_profileKey);
29                            listener.beforeResult(this, resultCode);
30                        }

31                        finally {
32                            UtilTimerStack.pop(_profileKey);
33                        }

34                    }

35                }

36
37                // now execute the result, if we're supposed to
38                if (proxy.getExecuteResult()) <
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值