转struts2的ActionInvocation分析(action调度者)
Posted day1day1up
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转struts2的ActionInvocation分析(action调度者)相关的知识,希望对你有一定的参考价值。
一个ActionInvocation实例代表一个action的执行状态,持有拦截器和将要执行的action的实例。
defaultActionInvocation是其默认实现。下面是定义在该类中的部分成员变量
1 public class DefaultActionInvocation implements ActionInvocation 2 protected Object action; 3 protected ActionProxy proxy; 4 protected List<PreResultListener> preResultListeners; 5 protected ActionContext invocationContext; 6 protected Iterator<InterceptorMapping> interceptors; 7 protected String resultCode; 8
成员变量的含义:
action:用于接收一次请求中含有本次请求的处理逻辑的类。就是对应的struts.xml配置文件中的action对应的class类的对象。比如struts.xml中有<action name="login" class="com.xxx.LoginAction"></action>这个 配置片段。如果请求的action的name为login,那么defaultActionInvocation中的action成员变量将持有 一个com.xxx.LoginAction的实例。
proxy:action的执行环境,持有action执行所需的所有信息。
preResultListeners:一个监听器集合。这些监听器会在action执行完毕且Result执行之前调用。
invocationContext:action执行的环境,包含action执行需要的session,parameters,locale等 信息。
interceptors:ActionInvocation的重要的部分。包含了action执行过程中的所有拦截器,用于对action 进行预处理和后处理。拦截器的调用方式采用责任链模式,和Servlet中的过滤器的执行过程相似。
resultCode:action调用execute等方法处理完相应的逻辑后的返回值。比如success,login等。
下面分析defaultActionInvocation中的重要方法:invokeActionOnly,invokeAction和invoke方法
首先是invokeActionOnly方法,如下
public String invokeActionOnly() throws Exception return invokeAction(getAction(), proxy.getConfig());
该方法先通过getAction方法获取实际请求的action实例,并通过proxy获取构建ActionProxy对象的
ActionConfig实例。ActionConfig包含了一个action在struts.xml文件中的相关的配置信息。
接着是invokeAction方法,该方法只保留了源码中的一些关键部分,并不是完整的
1 protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception 2 3 //通过getMethod获取在action配置文件中配置的要执行的方法 4 String methodName = proxy.getMethod(); 5 6 try 7 boolean methodCalled = false; 8 Object methodResult = null; 9 Method method = null; 10 try 11 //getAction方法获取实际的action对象,然后获得它的 12 //Class对象,在通过getMethod方法,以反射的方式获得 13 //将要执行的方法 14 method = getAction().getClass().getMethod(methodName, EMPTY_CLASS_ARRAY); 15 16 catch (NoSuchMethodException e) 17 try 18 String altMethodName = "do" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1); 19 method = getAction().getClass().getMethod(altMethodName, EMPTY_CLASS_ARRAY); 20 catch (NoSuchMethodException e1) 21 ... 22 23 25 26 //如果该方法还未执行过,那么通过反射调用该方法 27 if (!methodCalled) 28 methodResult = method.invoke(action, new Object[0]); 29 30 ... 31
最后是最重要的invoke方法,保留了完整的代码,并加入了自己的理解注释(责任链模式)。如下
1 public String invoke() throws Exception 2 String profileKey = "invoke: "; 3 try 4 UtilTimerStack.push(profileKey); 5 6 if (executed) 7 throw new IllegalStateException("Action has already executed"); 8 9 10 //当前还有拦截器,则取出拦截器执行intercept方法 11 if (interceptors.hasNext()) 12 //取出当前要执行的拦截器 13 final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next(); 14 String interceptorMsg = "interceptor: " + interceptor.getName(); 15 UtilTimerStack.push(interceptorMsg); 16 try 17 //执行拦截方法intercept,回去返回结果。传入DefaultActionInvocation.this 18 //参数是因为拦截器本身会调用ActionInvocation的invoke方法,因为实际类型是 19 //defaultActionInvocation,根据多态性,执行流程又会回到 20 //defaultActionInvocation的invoke方法,因为是同一个defaultActionInvocation 21 //那么就会取之前拦截器的下一个拦截器继续执行intercept方法 22 resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this); 23 24 finally 25 UtilTimerStack.pop(interceptorMsg); 26 27 else //当前没有拦截器,那么调用请求的action中的处理方法 28 resultCode = invokeActionOnly(); 29 30 31 //PreResultListener会在action执行完后,Result执行之前执行,且只 32 //执行一次。使用了一个boolean类型的标志,若没有执行,则执行这些 33 //监听器。因为是在同一个ActionInvocation的实例中,所以当executed 34 //成员变量变为true后,之后的if判断通不过,就不在执行了 35 if (!executed) 36 if (preResultListeners != null) 37 for (Object preResultListener : preResultListeners) 38 PreResultListener listener = (PreResultListener) preResultListener; 39 String _profileKey = "preResultListener: "; 40 try 41 UtilTimerStack.push(_profileKey); 42 listener.beforeResult(this, resultCode); 43 44 finally 45 UtilTimerStack.pop(_profileKey); 46 47 48 49 50 //可以看到PreResultListener的执行是在action执行后,Result执行前 51 if (proxy.getExecuteResult()) 52 executeResult(); 53 54 executed = true; //设置为true,保证PreResultListener不再执行 55 56 57 return resultCode; //返回action执行完毕后的返回值 58 59 finally 60 UtilTimerStack.pop(profileKey); 61 62
Action的调用者使用以上三个方法来完成请求的拦截和相应的action方法的执行。成员变量中最重要的就是表示实际Action类的action和拦截器的集合interceptors。interceptors持有所有对action请求进行拦截的拦截器引用,而action成员变量持有对请求进行实际处理的类的对象。
转载:https://blog.csdn.net/ikaraide/article/details/17719823。
以上是关于转struts2的ActionInvocation分析(action调度者)的主要内容,如果未能解决你的问题,请参考以下文章
深入struts2.0--ActionInvocation接口以及3DefaultActionInvocation类