非核心内容分析
继续上节,我们继续分析ActionServlet.process中的关键组件RequestProcessor的process方法。
processMultipart的目的就是包装一个可以处理以multipart-data形式发送的表单数据,多用于文件上传。相关内容请参考http://commons.apache.org/fileupload/和http://www.ietf.org/rfc/rfc2388.txt。
processPath,返回一个路径,之后会利用该路径找个一个匹配的ActionMapping,ActionMapping属于一种不可见的关键性组件,它负责组织path,Action,ActionForm,forward并让它们协作。这里的处理包括模块与非模块部分。
processLocale,这个比较有意思,从下面代码以及对应的JavaDoc说明可以得知,Struts的Locale是可以通过配置来决定是否可以自动为客户端选择语言类型。
语言相关内容请参考http://www.openinternetlexicon.com/HowTo/HowToServe.html,它描述了如何用浏览器发送带有指定语言的HTTP请求。当一个页面需要表现多种语言时,我们就可以像下面代码这样在页面的不同区域切换不同语言,虽然这样的场景不多,但确实存在,我就不走运碰到过~~~
至于processContent、processNoCache,没什么好说的,HTTP头相关处理。
processPreprocess,一个没有意义的实现,之所以留有这个方法就是允许我们扩展ActionServlet来定义自己的ActionServlet实现,然后覆盖掉这个方法来添加一些自定义的内容。如果不想写自己的ActionServlet,那这个方法基本上是作废了,没什么使用价值。到此为止,与Struts核心功能组件不相关的内容就结束了~~~(processCachedMessages,看样子是清理Struts框架中的消息,节省资源,但什么时候用过,还真不知道:)
ActionMapping
负责把ActionForm、Action和ActionForward组织起来,让它们协同工作。之前所说的processPath就是帮助我们返回一个可以标识唯一的ActionMapping关键字,这个定位操作就是由processMapping完成的。而接下来的processRoles,则是服务器安全校验,相关内容请参考《Core Servlets and JavaServer Pages, Volume 2: Advanced Technologies, Second Edition》第三章、第四章,此书已有中文版。
ActionForm
processActionForm,创建一个ActionForm并根据对应的ActionMapping中配置信息放入session或reqeust中。processPopulate,这个方法值得一看,其中心内容就是BeanUtils.populate(bean, properties),如何利用一个Map类型对象为一个JavaBean填充数据,具体内容请参考BeanUtils文档。processValidate,先调用form.validate的方法,如果返回内容空或没有错误,则将控制权返回给上层代码,否则返回失败标识并执行跳转动作,以下这些跳转动作都是值得关注的:
- response.sendError
- response.sendRedirect
- getServletContext().getRequestDispatcher(uri).forward(request, response);
Action
processForward和processInclude分别处理ForwardAction和IncludeAction,对应实现分别为doForward和doInclude,这两个实现技巧都非常有用,可以查看具体代码以加深印象!
processActionCreate是用于Action创建的,Struts中所有的Action都是统一管理,且每个定义只有一个实例存在,即单态。因为Servlet是以多线程形式相应客户端,而Action又作为共享资源存在,这里就会有多线程安全问题,所以在创建Action的时候,共享变量actions是被synchronized块所包围的。
有了Action,就可以调用processActionPerform了,这里的设计模式属于模板方法,直接调用我们最熟悉的Action.execute。现在打开/struts1/struts-1.3.10/src/extras/src/main/java下的org.apache.struts.actions,里面罗列了许多Action的实现,对于有些Action的特殊用法,小秘密都集中在execute方法中:)
- apache/struts/actions/ActionDispatcher.java
- apache/struts/actions/BaseAction.java
- apache/struts/actions/DispatchAction.java
- apache/struts/actions/DownloadAction.java
- apache/struts/actions/EventActionDispatcher.java
- apache/struts/actions/EventDispatchAction.java
- apache/struts/actions/ForwardAction.java
- apache/struts/actions/IncludeAction.java
- apache/struts/actions/LocaleAction.java
- apache/struts/actions/LookupDispatchAction.java
- apache/struts/actions/MappingDispatchAction.java
- apache/struts/actions/SwitchAction.java
ActionForward
最后一步就是processForwardConfig,执行跳转或转发操作,之前已经说过,这里就不再重复。
异常控制
如果在struts-config.xml中定义了异常控制句柄,在form.validate或action.execute发生异常时就会调用processException,该方法又会根据异常类型来自动选择异常句柄,主要是利用getClass方法一层层向上查找看是否有合适的处理句柄。
结束语
分析过程虽然粗糙(实在没那么多时间和精力),但主线过程基本都光顾到了,如有遗漏还望指出。
推荐几个参考文档:
《Prentice Hall - Core Servlets and JavaServer Pages, Volume 1 Core Technologies, 2nd Edition》
《Prentice Hall - Core Servlets and JavaServer Pages, Volume 2: Advanced Technologies》
《McGraw-Hill - Struts: The Complete Reference》