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

//returnaboveandflowthroughagain

if(!executed){

//在Result返回之前调用preResultListeners

if(preResultListeners!=null){

for(Iteratoriterator=preResultListeners.iterator();

iterator.hasNext();){

PreResultListenerlistener=(PreResultListener)iterator.next();

String_profileKey="preResultListener:";

try{

UtilTimerStack.push(_profileKey);

listener.beforeResult(this,resultCode);

}

finally{

UtilTimerStack.pop(_profileKey);

}

}

}

//nowexecutetheresult,ifwe'resupposedto

if(proxy.getExecuteResult()){

executeResult();

}

executed=true;

}

returnresultCode;

}

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 {

StringmethodName=proxy.getMethod();

StringtimerKey="invokeAction:"+proxy.getActionName();

try{

UtilTimerStack.push(timerKey);

booleanmethodCalled=false;

ObjectmethodResult=null;

Methodmethod=null;

try{

//获得需要执行的方法

method=getAction().getClass().getMethod(methodName,newClass[0]);

}catch(NoSuchMethodExceptione){

//如果没有对应的方法,则使用do+Xxxx来再次获得方法

try{

StringaltMethodname="do"+methodName.substring(0,1).toUpperCase()+methodName.substring(1);

method=getAction().getClass().getMethod(altMethodName,newClass[0]);

}catch(NoSuchMethodExceptione1){

//well,givetheunknownhandlerashot

if(unknownHandler!=null){

try{

methodResult=unknownHandler.handleUnknownActionMethod(action,methodName);

methodCalled=true;

}catch(NoSuchMethodExceptione2){

//throwtheoriginalone

throwe;

}

}else{

throwe;

}

}

}

if(!methodCalled){

methodResult=method.invoke(action,newObject[0]);

}

//根据不同的Result类型返回不同值

//如输出流Result

if(methodResultinstanceofResult){

this.explicitResult=(Result)methodResult;

returnnull;

}else{

return(String)methodResult;

}

}catch(NoSuchMethodExceptione){

thrownewIllegalArgumentException("The"+methodName+"()isnotdefinedinaction"+getAction().getClass()+"");

}catch(InvocationTargetExceptione){

//Wetrytoreturnthesourceexception.

Throwablet=e.getTargetException();

if(actionEventListener!=null){

Stringresult=actionEventListener.handleException(t,getStack());

if(result!=null){

returnresult;

}

}

if(tinstanceofException){

throw(Exception)t;

}else{

throwe;

}

}finally{

UtilTimerStack.pop(timerKey);

}

    }
    好了,action执行完了,还要根据ResultConfig返回到view,也就是在invoke方法中调用executeResult方法。
    private void executeResult() throws Exception {

//根据ResultConfig创建Result

result=createResult();

StringtimerKey="executeResult:"+getResultCode();

try{

UtilTimerStack.push(timerKey);

if(result!=null){

//这儿正式执行:)

//可以参考Result的实现,如用了比较多的ServletDispatcherResult,ServletActionRedirectResult,ServletRedirectResult

result.execute(this);

}elseif(resultCode!=null&&!Action.NONE.equals(resultCode)){

thrownewConfigurationException("Noresultdefinedforaction"+getAction().getClass().getName()

+"andresult"+getResultCode(),proxy.getConfig());

}else{

if(LOG.isDebugEnabled()){

LOG.debug("Noresultreturnedforaction"+getAction().getClass().getName()+"at"+proxy.getConfig().getLocation());

}

}

}finally{

UtilTimerStack.pop(timerKey);

}

}

publicResultcreateResult()throwsException{

if(explicitResult!=null){

Resultret=explicitResult;

explicitResult=null;;

returnret;

}

ActionConfigconfig=proxy.getConfig();

Mapresults=config.getResults();

ResultConfigresultConfig=null;

synchronized(config){

try{

//根据result名称获得ResultConfig,resultCode就是result的name

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

}catch(NullPointerExceptione){

}

if(resultConfig==null){

//如果找不到对应name的ResultConfig,则使用name为*的Result

resultConfig=(ResultConfig)results.get("*");

}

}

if(resultConfig!=null){

try{

//参照StrutsObjectFactory的代码

Resultresult=objectFactory.buildResult(resultConfig,invocationContext.getContextMap());

returnresult;

}catch(Exceptione){

LOG.error("Therewasanexceptionwhileinstantiatingtheresultoftype"+resultConfig.getClassName(),e);

thrownewXWorkException(e,resultConfig);

}

}elseif(resultCode!=null&&!Action.NONE.equals(resultCode)&&unknownHandler!=null){

returnunknownHandler.handleUnknownResult(invocationContext,proxy.getActionName(),proxy.getConfig(),resultCode);

}

returnnull;

}

//StrutsObjectFactory

publicResultbuildResult(ResultConfigresultConfig,MapextraContext)throwsException{

StringresultClassName=resultConfig.getClassName();

if(resultClassName==null)

returnnull;

//创建Result,因为Result是有状态的,所以每次请求都新建一个

Objectresult=buildBean(resultClassName,extraContext);

//这句很重要,后面将会谈到,reflectionProvider参见OgnlReflectionProvider;

//resultConfig.getParams()就是result配置文件里所配置的参数<param></param>

//setProperties方法最终调用的是Ognl类的setValue方法

//这句其实就是把param名值设置到根对象result上

reflectionProvider.setProperties(resultConfig.getParams(),result,extraContext);

if(resultinstanceofResult)

return(Result)result;

thrownewConfigurationException(result.getClass().getName()+"doesnotimplementResult.");

    }
    最后补充一下,Struts2的查找值和设置值都是使用Ognl来实现的。关于Ognl的介绍可以到其官方网站查看http://www.ognl.org/,我在网上也找到另外一篇http://www.iteye.com/topic/254684和http://www.iteye.com/topic/223612。完了来看下面这段小测试程序(其它的Ognl的测试可以自己添加)。
public class TestOgnl {

privateUseruser;

privateMapcontext;

@Before

publicvoidsetUp()throwsException{

}

@Test

publicvoidognlGetValue()throwsException{

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

publicvoidognlSetValue()throwsException{

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));

}

publicstaticvoidmain(String[]args)throwsException{

JUnitCore.runClasses(TestOgnl.class);

}

privatevoidreset(){

user=newUser("myyate",newDept("cares"));

context=newOgnlContext();

context.put("pen","parker");

context.put("name","contextmap");

}

}

classUser{

publicUser(Stringname,Deptdept){

this.name=name;

this.dept=dept;

}

Stringname;

privateDeptdept;

publicDeptgetDept(){

returndept;

}

publicStringgetName(){

returnname;

}

publicvoidsetDept(Deptdept){

this.dept=dept;

}

publicvoidsetName(Stringname){

this.name=name;

}

}

classDept{

publicDept(Stringname){

this.name=name;

}

privateStringname;

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

}
    这样,一个Struts2的请求流程基本上就结束了。其实我觉得做项目把Struts2参考文档看两遍就可以了,

相关推荐