具體分析了建立action,而且執行action,返回結果result,如今在詳細的分析 result是怎麼執行的?請看流程圖: java
一、DefaultActionInvocation的invoke()執行了action,而且返回來resultCode,後面調用executeResult()執行結果 apache
回來再看看DefaultActionInvocation中executeResult()方法: ide
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)執行這個方法 ui
二、createResult()方法: this
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的配置對象 spa
(3) config.getResults()獲取action標籤下面的result標籤的配置信息,請看 .net
gaokao-struts2-init_Traditio...加載struts.xml文件 debug
(4)results.get(resultCode)根據action的執行結果resultCode查找相應result的配置 code
(5)objectFactory.buildResult()根據上面得到result的配置,建立Result對象 orm
三、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對象。
四、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()方法,這樣利於擴展。