具体分析了创建action,并且执行action,返回结果result,现在在详细的分析 result是怎么执行的?请看流程图:
1、DefaultActionInvocation的invoke()执行了action,并且返回来resultCode,后面调用executeResult()执行结果
回来再看看DefaultActionInvocation中executeResult()方法:
private void executeResult() throws Exception { result = createResult(); String timerKey = "executeResult: " + getResultCode(); try { UtilTimerStack.push(timerKey); if (result != null) { 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); } }注释:(1)result = createResult()创建result对象
(2)result.execute(this)执行这个方法
2、createResult()方法:
public Result createResult() throws Exception { if (explicitResult != null) { Result ret = explicitResult; explicitResult = null; return ret; } ActionConfig config = proxy.getConfig(); Map<String, ResultConfig> results = config.getResults(); ResultConfig resultConfig = null; synchronized (config) { try { resultConfig = results.get(resultCode); } catch (NullPointerException e) { // swallow } if (resultConfig == null) { // If no result is found for the given resultCode, try to get a wildcard '*' match. resultConfig = results.get("*"); } } if (resultConfig != null) { try { return objectFactory.buildResult(resultConfig, invocationContext.getContextMap()); } 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) && unknownHandlerManager.hasUnknownHandlers()) { return unknownHandlerManager.handleUnknownResult(invocationContext, proxy.getActionName(), proxy.getConfig(), resultCode); } return null; }注释:(1)判断explicitResult是否为空,不为空直接返回,前面也解释了 explicitResult值是什么
(2) proxy.getConfig()获取前面相应action的配置对象
(3) config.getResults()获取action标签下面的result标签的配置信息,请看
gaokao-struts2-init_Traditio...加载struts.xml文件
(4)results.get(resultCode)根据action的执行结果resultCode查找相应result的配置
(5)objectFactory.buildResult()根据上面获得result的配置,创建Result对象
3、buildResult代码:
public Result buildResult(ResultConfig resultConfig, Map<String, Object> extraContext) throws Exception { String resultClassName = resultConfig.getClassName(); Result result = null; if (resultClassName != null) { result = (Result) buildBean(resultClassName, extraContext); Map<String, String> params = resultConfig.getParams(); if (params != null) { for (Map.Entry<String, String> paramEntry : params.entrySet()) { try { reflectionProvider.setProperty(paramEntry.getKey(), paramEntry.getValue(), result, extraContext, true); } catch (ReflectionException ex) { if (LOG.isErrorEnabled()) LOG.error("Unable to set parameter [#0] in result of type [#1]", ex, paramEntry.getKey(), resultConfig.getClassName()); if (result instanceof ReflectionExceptionHandler) { ((ReflectionExceptionHandler) result).handle(ex); } } } } } return result; }注释:(1)resultConfig.getClassName()就是result标签属性type对应的实现类。例如:type= dispatcher实现类就是class="org.apache.struts2.dispatcher.ServletDispatcherResult"
(2)result = (Result) buildBean(resultClassName, extraContext)通过反射机制创建result对象。
4、result 对象已经创建好了,现在就调用result.execute(this)执行方法,现在看看org.apache.struts2.dispatcher.ServletDispatcherResult:
public class ServletDispatcherResult extends StrutsResultSupport { public ServletDispatcherResult() { super(); } public ServletDispatcherResult(String location) { super(location); } public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { 。。。 } }怎么没有 execute方法,有什么猫腻呢?看看他的父类StrutsResultSupport
public abstract class StrutsResultSupport implements Result, StrutsStatics { public void execute(ActionInvocation invocation) throws Exception { lastFinalLocation = conditionalParse(location, invocation); doExecute(lastFinalLocation, invocation); } protected abstract void doExecute(String finalLocation, ActionInvocation invocation) throws Exception; }原来是这样啊!父类 StrutsResultSupport中实现了 execute()方法,并且在其中调用了抽象方法doExecute(),而自雷子类ServletDispatcherResult就可以实现doExecute()方法,这样利于扩展。