接下来看看DefaultActionInvocation 的invoke方法。
public void init(ActionProxy proxy) { this.proxy = proxy; Map contextMap = createContextMap(); // Setting this so that other classes, like object factories, can use the ActionProxy and other // contextual information to operate ActionContext actionContext = ActionContext.getContext(); if(actionContext != null) { actionContext.setActionInvocation(this); } //创建Action,可Struts2里是每次请求都新建一个Action createAction(contextMap); if (pushAction) { stack.push(action); contextMap.put("action", action); } invocationContext = new ActionContext(contextMap); invocationContext.setName(proxy.getActionName()); // get a new List so we don't get problems with the iterator if someone changes the list List interceptorList = new ArrayList(proxy.getConfig().getInterceptors()); interceptors = interceptorList.iterator(); } protected void createAction(Map contextMap) { // load action String timerKey = "actionCreate: "+proxy.getActionName(); try { UtilTimerStack.push(timerKey); //这儿默认建立Action是StrutsObjectFactory,实际中我使用的时候都是使用Spring创建的Action,这个时候使用的是SpringObjectFactory action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap); } .. } finally { UtilTimerStack.pop(timerKey); } if (actionEventListener != null) { action = actionEventListener.prepare(action, stack); } } //接下来看看DefaultActionInvocation 的invoke方法。 public String invoke() throws Exception { String profileKey = "invoke: "; try { UtilTimerStack.push(profileKey); if (executed) { throw new IllegalStateException("Action has already executed"); } //先执行interceptors if (interceptors.hasNext()) { final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next(); UtilTimerStack.profile("interceptor: "+interceptor.getName(), new UtilTimerStack.ProfilingBlock<String>() { public String doProfiling() throws Exception { resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this); return null; } }); } else { //interceptor执行完了之后执行action resultCode = invokeActionOnly(); } // 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的请求流程基本上就结束了。