action的整个执行流程使用的就是动态代理模式。关于动态代理模式的原理可以看这篇文章:
http://tiro-li.iteye.com/blog/1901678
Action:真实角色,这是动态改变的;
ActionSupport:抽象角色,Action实现的接口;
ActionProxy:动态代理角色。相当于Proxy动态生成的$Proxy0类,有以下三点信息需要我们明确。
(1).它在Dispatcher的executeAction方法中由ActionProxyFactory类创建;
(2).通过持有ConfigurationManager的引用获取到Action中要执行的方法(默认为execute),这相当于间接实现了ActionSupport接口;
(3).同时它持ActionInvocation的引用,把Action的执行委托给ActionInvocation处理;
ActionInvocation:相当于在动态代理模型中InvocationHandler的实现类,持有Action的引用,通过反射调用Action的执行方法。
以JSP页面提交login.action为例。下面为一个精略的代码流程。其中,ActionMapping为action的映射,用来保存actionName、namespace、method、result等信息。
//PrepareOperations是执行前准备的所有操作的包装类
PrepareOperations prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
//ExecuteOperations是执行Action过程所有操作的包装类
ExecuteOperations execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
//包装request为StrutsRequestWrapper对象
request = prepare.wrapRequest(request);
//创建ActionMapping对象
ActionMapping mapping = prepare.findActionMapping(request, response, true);*
/*
ActonMapping
{
name = "login",
extension = "action",
namespace = "/",
result = "null",
method = "null";
}
*/
//执行Action
execute.executeAction(request, response, mapping);
//在executeAction中调用Dispatcher的serviceAction方法
public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException
{
dispatcher.serviceAction(request, response, servletContext, mapping);
}
//在Dispatcher的serviceAction方法创建ActionProxy对象
public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,ActionMapping mapping) throws ServletException
{
Map<String, Object> extraContext = createContextMap(request, response, mapping, context);
String namespace = mapping.getNamespace(); // "/"
String name = mapping.getName(); // "login"
String method = mapping.getMethod(); // "null"
//获取得配置文件的Configuration对象
Configuration config = configurationManager.getConfiguration();
//利用ActionProxy的工厂类ActionProxyFactory创建StrutsActionProxy对象
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method, extraContext, true, false);
/*
ActionProxy
{
actionName = "login",
method = "execute", //由configurationManager解析配置文件获取
invocation = DefaultActionInvocation
{
Action:LoginAction, //由configurationManager解析配置文件获取
interceptors:Iterator<InterceptorMapping> //defaultStack中Interceptor
});
}
*/
proxy.execute();
}
//在ActionProxy的execute方法调用invocation的invoke方法
public String execute() throws Exception
{
return invocation.invoke();
}
//ActionInvocation的invoke方法
public String invoke() throws Exception
{
//循环应用defaultStack中的拦截器
if (interceptors.hasNext())
{
final InterceptorMapping interceptor = interceptors.next();
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
else
{
//Invokes only the Action (not Interceptors or Results),result the resultCode.
resultCode = invokeActionOnly();
}
}
//ActionInvocation的invokeActionOnly方法
public String invokeActionOnly() throws Exception
{
return invokeAction(getAction(), proxy.getConfig());
}
}
//ActionInvocation的 invokeAction方法
protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception
{
String methodName = proxy.getMethod();
//使用反射调用execute方法
Method method = getAction().getClass().getMethod(altMethodName, new class[]{});
String methodResult = method.invoke(action, new Object[]{});
return saveResult(actionConfig, methodResult);
}