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); }
相关推荐
ActionProxy创建一个ActionInvocation实例,同时ActionInvocation通过代理模式调用Action。但在调用之前,ActionInvocation会根据配置加载Action相关的所有Interceptor(拦截器)。 一旦Action执行完毕,...
答:Struts1和Struts2是两个完全不同的框架,Struts1以ActionServlet作为核心控制器,由ActionServlet负责拦截用户的所有请求。Struts2以核心控制器FilterDispatcher为基础,包含了框架内部的控制流程和处理机制。 ...
05 MVC模式和MTV模式 06 django的一个简单应用 07 django静态文件之static 08 django的url控制系统 09 django的urlConf补充 第50章 01 django之视图函数的介绍 02 django视图之redirec 03 django模板之变量 04 ...
从内存方面来看, Stateful Session Bean 与 Stateless Session Bean 比较, Stateful Session Bean 会消耗 J2EE Server 较多的内存,然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。 9、...
从内存方面来看, Stateful Session Bean 与 Stateless Session Bean 比较, Stateful Session Bean 会消耗 J2EE Server 较多的内存,然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。 12、...
{1.9}流程控制}{31}{section.1.9} {1.9.1}\texttt {if\ldots esle\ldots }}{31}{subsection.1.9.1} {1.9.2}\texttt {switch}}{31}{subsection.1.9.2} {1.9.3}\texttt {while}}{32}{subsection.1.9.3} {1.9.4}\...