流程说明:
1.客户端浏览器(Client)向服务器发送一个 http 请求(HttpServletRequest)
2.Container(容器) 通过 web.xml 映射请求,并获得控制器(Controller)的名字
3.Container 调用控制器(StrutsPrepareAndExecuteFilter 或 FilterDispatcher)。在Struts 2.1.3 以前调用 FilterDispatcher,Struts 2.1.3以后调用 StrutsPrepareAndExecuteFilter。
4.Controller 调用 ActionMapper,ActionMapper 返回 ActionMapping 对象。
5.Controller 将请求的控制权委派给 ActionProxy,并把请求数据传给 ActionProxy
6.ActionProxy 调用配置管理器(ConfigurationManager) 读取配置文件的信息(struts.xml)
7.ActionProxy 拿到 Action、Interceptor等相关数据后,调用 ActionInvocation,并把 Action、Interceptor 等相关数据及请求数据传递给 ActionInvocation。
8.ActionInvocation 调用前置拦截器,把 request 请求里面的参数封装到 ActionContext 对象中的 ValueStack 对象中的值栈对象里面。
如果 Action 的属性名与 ValueStack 对象中的值栈对象的属性名相同(即与 request 请求里的参数相同),则将 ValueStack 对象中的值栈对象的属性值赋给对应的 Action 属性。
9.根据 Action 的配置信息,调用 Result 组件。
11.Result 信息返回给 ActionInvocation。将结果信息封装到 HttpServletResponse 对象中
12.容器将 HttpServletResponse 对象中信息打成响应数据包发送给客户端。
有疑问:
听说特定请求映射到特定 Action的相关信息存储在 ActionMapping 对象中,这就奇怪了,确定执行哪个 Action 不是由 ConfigurationManager 干的吗?如果 ActionMapper 就确定了哪个 Action,那后面调 ConfigurationManager 读取配置文件岂不是多余了?
ActionMapping 对象中刚开始时是空的,ConfigurationManager 对象去解析 struts.xml 后,将请求与 Action 的映射关系封装到 ActionMapping 对象中。