首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

struts2源码分析一(part2)

2012-08-29 
struts2源码分析1(part2)转:?http://blog.csdn.net/accpsz/archive/2010/12/31/6108917.aspx//?this?is?ne

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>struts2源码分析一(part2)</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/254684和http://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参考文档看两遍就可以了,

热点排行