struts2源码分析1(part2)

转: http://blog.csdn.net/accpsz/archive/2010/12/31/6108917.aspx

//  this is needed because the result will be executed, then control will return to the Interceptor, which will
            
//  return above and flow through again
             if  ( ! executed) {
                        
// 在Result返回之前调用preResultListeners
                 if  (preResultListeners  !=   null ) {
                    
for  (Iterator iterator  =  preResultListeners.iterator();
                        iterator.hasNext();) {
                        PreResultListener listener 
=  (PreResultListener) iterator.next();
                        
                        String _profileKey
= " preResultListener:  " ;
                        
try  {
                            UtilTimerStack.push(_profileKey);
                            listener.beforeResult(
this , resultCode);
                        }
                        
finally  {
                            UtilTimerStack.pop(_profileKey);
                        }
                    }
                }

                
//  now execute the result, if we're supposed to
                 if  (proxy.getExecuteResult()) {
                    executeResult();
                }

                executed 
=   true ;
            }

            
return  resultCode;
        }
        
finally  {
            UtilTimerStack.pop(profileKey);
        }
    }
    看程序中的if(interceptors.hasNext())语句,当然,interceptors里存储的是interceptorMapping列表(它包括一个Interceptor和一个name),所有的截拦器必须实现Interceptor的intercept方法,而该方法的参数恰恰又是ActionInvocation,在intercept方法中还是调用invocation.invoke(),从而实现了一个Interceptor链的调用。当所有的Interceptor执行完,最后调用invokeActionOnly方法来执行Action相应的方法。
     protected  String invokeAction(Object action, ActionConfig actionConfig)  throws  Exception {
        String methodName 
=  proxy.getMethod();
        String timerKey 
=   " invokeAction:  " + proxy.getActionName();
        
try  {
            UtilTimerStack.push(timerKey);
            
            
boolean  methodCalled  =   false ;
            Object methodResult 
=   null ;
            Method method 
=   null ;
            
try  {
                
// 获得需要执行的方法
                method  =  getAction().getClass().getMethod(methodName,  new  Class[ 0 ]);
            } 
catch  (NoSuchMethodException e) {
                
// 如果没有对应的方法,则使用do+Xxxx来再次获得方法
                 try  {
                    String altMethodName 
=   " do "   +  methodName.substring( 0 1 ).toUpperCase()  +  methodName.substring( 1 );
                    method 
=  getAction().getClass().getMethod(altMethodName,  new  Class[ 0 ]);
                } 
catch  (NoSuchMethodException e1) {
                    
//  well, give the unknown handler a shot
                     if  (unknownHandler  !=   null ) {
                        
try  {
                            methodResult 
=  unknownHandler.handleUnknownActionMethod(action, methodName);
                            methodCalled 
=   true ;
                        } 
catch  (NoSuchMethodException e2) {
                            
//  throw the original one
                             throw  e;
                        }
                    } 
else  {
                        
throw  e;
                    }
                }
            }
            
            
if  ( ! methodCalled) {
                methodResult 
=  method.invoke(action,  new  Object[ 0 ]);
            }
            
// 根据不同的Result类型返回不同值
            
// 如输出流Result
             if  (methodResult  instanceof  Result) {
                
this .explicitResult  =  (Result) methodResult;
                
return   null ;
            } 
else  {
                
return  (String) methodResult;
            }
        } 
catch  (NoSuchMethodException e) {
            
throw   new  IllegalArgumentException( " The  "   +  methodName  +   " () is not defined in action  "   +  getAction().getClass()  +   "" );
        } 
catch  (InvocationTargetException e) {
            
//  We try to return the source exception.
            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);
        }
    }
    好了,action执行完了,还要根据ResultConfig返回到view,也就是在invoke方法中调用executeResult方法。
     private   void  executeResult()  throws  Exception {
        
// 根据ResultConfig创建Result
        result  =  createResult();
        String timerKey 
=   " executeResult:  " + getResultCode();
        
try  {
            UtilTimerStack.push(timerKey);
            
if  (result  !=   null ) {
                
// 这儿正式执行:)
                
// 可以参考Result的实现,如用了比较多的ServletDispatcherResult,ServletActionRedirectResult,ServletRedirectResult
                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);
        }
    }
    
public  Result createResult()  throws  Exception {
        
if  (explicitResult  !=   null ) {
            Result ret 
=  explicitResult;
            explicitResult 
=   null ;;
            
return  ret;
        }
        ActionConfig config 
=  proxy.getConfig();
        Map results 
=  config.getResults();
        ResultConfig resultConfig 
=   null ;
        
synchronized  (config) {
            
try  {
                
// 根据result名称获得ResultConfig,resultCode就是result的name
                resultConfig  =  (ResultConfig) results.get(resultCode);
            } 
catch  (NullPointerException e) {
            }
            
if  (resultConfig  ==   null ) {
                
// 如果找不到对应name的ResultConfig,则使用name为*的Result
                resultConfig  =  (ResultConfig) results.get( " * " );
            }
        }
        
if  (resultConfig  !=   null ) {
            
try  {
                
// 参照StrutsObjectFactory的代码
                Result result  =  objectFactory.buildResult(resultConfig, invocationContext.getContextMap());
                
return  result;
            } 
catch  (Exception e) {
                LOG.error(
" There was an exception while instantiating the result of type  "   +  resultConfig.getClassName(), e);
                
throw   new  XWorkException(e, resultConfig);
            }
        } 
else   if  (resultCode  !=   null   &&   ! Action.NONE.equals(resultCode)  &&  unknownHandler  !=   null ) {
            
return  unknownHandler.handleUnknownResult(invocationContext, proxy.getActionName(), proxy.getConfig(), resultCode);
        }
        
return   null ;
    }
    
// StrutsObjectFactory
     public  Result buildResult(ResultConfig resultConfig, Map extraContext)  throws  Exception {
        String resultClassName 
=  resultConfig.getClassName();
        
if  (resultClassName  ==   null )
            
return   null ;
        
// 创建Result,因为Result是有状态的,所以每次请求都新建一个
        Object result  =  buildBean(resultClassName, extraContext);
        
// 这句很重要,后面将会谈到,reflectionProvider参见OgnlReflectionProvider;
        
// resultConfig.getParams()就是result配置文件里所配置的参数<param></param>
        
// setProperties方法最终调用的是Ognl类的setValue方法
        
// 这句其实就是把param名值设置到根对象result上
        reflectionProvider.setProperties(resultConfig.getParams(), result, extraContext);
        
if  (result  instanceof  Result)
            
return  (Result) result;
        
throw   new  ConfigurationException(result.getClass().getName()  +   "  does not implement Result. " );
    }
    最后补充一下,Struts2的查找值和设置值都是使用Ognl来实现的。关于Ognl的介绍可以到其官方网站查看http://www.ognl.org/,我在网上也找到另外一篇http://www.iteye.com/topic/254684http://www.iteye.com/topic/223612。完了来看下面这段小测试程序(其它的Ognl的测试可以自己添加)。
public   class  TestOgnl {
    
    
private  User user;
    
private  Map context;
    
    @Before
    
public   void  setUp()  throws  Exception {
    
    }

    @Test
    
public   void  ognlGetValue()  throws  Exception {
    reset();
    Assert.assertEquals(
" myyate " , Ognl.getValue( " name " , user));
    Assert.assertEquals(
" cares " , Ognl.getValue( " dept.name " , user));
    Assert.assertEquals(
" myyate " , Ognl.getValue( " name " , context, user));
    Assert.assertEquals(
" contextmap " , Ognl.getValue( " #name " , context, user));
    Assert.assertEquals(
" parker " , Ognl.getValue( " #pen " , context, user));
    }
    
    @Test
    
public   void  ognlSetValue()  throws  Exception {
    reset();
    Ognl.setValue(
" name " , user,  " myyateC " );
    Assert.assertEquals(
" myyateC " , Ognl.getValue( " name " , user));
    
    Ognl.setValue(
" dept.name " , user,  " caresC " );
    Assert.assertEquals(
" caresC " , Ognl.getValue( " dept.name " , user));
    
    Assert.assertEquals(
" contextmap " , Ognl.getValue( " #name " , context, user));
    Ognl.setValue(
" #name " , context, user,  " contextmapC " );
    Assert.assertEquals(
" contextmapC " , Ognl.getValue( " #name " , context, user));
    
    Assert.assertEquals(
" parker " , Ognl.getValue( " #pen " , context, user));
    Ognl.setValue(
" #name " , context, user,  " parkerC " );
    Assert.assertEquals(
" parkerC " , Ognl.getValue( " #name " , context, user));
    }
    
    
public   static   void  main(String[] args)  throws  Exception {
    JUnitCore.runClasses(TestOgnl.
class );
    }
    
    
private   void  reset() {
    user 
=   new  User( " myyate " new  Dept( " cares " ));
    context 
=   new  OgnlContext();
    context.put(
" pen " " parker " );
    context.put(
" name " " contextmap " );
    }
}

class  User {
    
public  User(String name, Dept dept) {
    
this .name  =  name;
    
this .dept  =  dept;
    }
    String name;
    
private  Dept dept;
    
public  Dept getDept() {
        
return  dept;
    }
    
public  String getName() {
        
return  name;
    }
    
public   void  setDept(Dept dept) {
        
this .dept  =  dept;
    }
    
public   void  setName(String name) {
        
this .name  =  name;
    }
}

class  Dept {
    
public  Dept(String name) {
    
this .name  =  name;
    }
    
private  String name;
    
public  String getName() {
        
return  name;
    }
    
public   void  setName(String name) {
        
this .name  =  name;
    }
}
    这样,一个Struts2的请求流程基本上就结束了。其实我觉得做项目把Struts2参考文档看两遍就可以了,

你可能感兴趣的:(Blog)