分析范围
仅仅对Struts的基本运行原理进行分析,不包括实现细节以及标签库、插件等非主流程内容的分析,分析流程大致如下
request -> ActionServlet -> ActionForm -> Action -> Forward -> JSP/other rescources
请求 -> 中心应用控制器 -> 数据包装 -> 业务控制器 -> 跳转 -> JSP/其它资源
目录结构分析
源码部分:struts-1.3.10/src/apps/cookbook/src/main/java
运行部分(含*部分的内容在分析范围内):
/struts1/web-app
/struts1/web-app/css
/struts1/web-app/images
/struts1/web-app/jsp
/struts1/web-app/WEB-INF
/struts1/web-app/WEB-INF/lib
/struts1/web-app/WEB-INF/src
/struts1/web-app/WEB-INF/chain-config.xml *
/struts1/web-app/WEB-INF/struts-config-Wildcard.xml *
/struts1/web-app/WEB-INF/struts-config.xml *
/struts1/web-app/WEB-INF/validation.xml *
/struts1/web-app/WEB-INF/web.xml *
/struts1/web-app/index.jsp
/struts1/web-app/source.jsp
基本概念
ActionServlet - Struts中核心组件,用于管理与调度ActionForm、Action等组件,随着应用服务器启动而启动
ActionForm - 对客户端请求时所携带的数据进行包装,并能提供验证功能
Action - 对被请求的内容进行业务控制,执行业务选择与视图派发
Exception - 对Action执行时所发生的异常进行控制
Forward - 提供跳转相关信息
ActionMapping - 对应Struts配置文件,可视为配置文件的内存表现形式
web.xml
注意load-on-startup标签,代表ActionServlet会随着servlet容器启动而启动,也就是说,Struts的核心组件是ActionServlet,一切配置信息都是通过ActionServlet的启动而装载的。看下面代码会更清晰一些。
Struts配置文件struts-config.xml
Struts配置文件内容大致可以分析以下几个内容:
- form-beans
- global-exceptions
- global-forwards
- action-mappings
- message-resources
- plug-in
至于各个部分的配置说明,请参考《Struts - The Complete Reference》与Struts的JavaDoc。
Struts初始化
现在就打开ActionServlet源码,位置是/struts1/struts-1.3.10/src/core/src/main/java/org/apache/struts/action/ActionServlet.java。
init与destory就不看了,大致就是配置信息的初始化校验等,不过init中值得注意的是下面这句:
假如JSP画面中一个checkbox的value值为“是”或“否”,想对应ActionForm中的一个布尔型属性,我们就可以仿照initOther来注册我们自己的转换器,至于怎么用自己查吧:)
处理请求
接下来我们来看看doGet和doPost的方法实现,二者步调一致,统一指向了process方法。如果说ActionServlet是Struts的核心组件,那么RequestProcessor则是ActionServlet的核心,因为从请求发起至完成响应,RequestProcessor负责了全部的调度工作。
接下来进入RequestProcessor的process方法中,代码如下:
现在我们粗略的分析一下在整个请求过程中,各个Struts组件是如何被组织调用的。从代码中可以看出,整个process方法内部是由若干个processXXX方法组成,每条语句都执行一个特别处理,先是processMultipart,处理与文件上传相关的内容;processPath,根据request中的信息来选择映射路径,以便后来选择合适的ActionMapping组件;processLocale,处理本地化信息;processContent、processNoCache,处理与HTML头相关的信息(contentType和缓存的使用);processPreprocess,该方法为模板方法,如果我们通过继承ActionServlet来定义自己的ActionServlet,可以覆盖此方法以达到预先处理请求内容的目的;processCachedMessages,清理session中的缓存消息;processMapping,通过之前查找到的path来确定可用的ActionMapping对象;processRoles,有点ACL的意思,还真没用过,主要是确认当前用户的角色是否有访问当前的资源。
剩下的内容将在下节进行细节分析。
- processActionForm // 根据ActionMapping提供的信息生成ActionForm
- processPopulate // 利用request中携带的请求信息填写ActionForm中定义的每个字段
- processValidate // 调用ActionForm的validate方法来做数据验证
- processException // 处理异常,对应struts-config.xml中Exception部分
- processForward // 处理ForwardAction
- processInclude // 处理IncludeAction
- processActionCreate // 根据ActionMapping提供的信息生成Action,每个Action只有一个实例存在
- processActionPerform // 调用Action的execute方法
- processForwardConfig // 根据Action.execute方法返回的ActionForward来决定接下来的URL切换动作(跳转或转发)