无线&移动互联网技术研发

换位思考·····
posts - 19, comments - 53, trackbacks - 0, articles - 283
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

回顾Struts2 工作流

Posted on 2010-05-28 23:33 Gavin.lee 阅读(756) 评论(0)  编辑  收藏 所属分类: SSH2 --Struts2
Struts2 处理流程概要:
一个请求在Struts2框架中的处理大概分为以下几个步骤
1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)
3 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action
4 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
5 ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
6 ActionProxy创建一个ActionInvocation的实例。
7 ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2框架中继承的标签。在这个过程中需要涉及到ActionMapper,在上述过程中所有的对象(Action,Results,Interceptors,等)都是通过ObjectFactory来创建的。

过滤器介绍(Filter)
FilterDispatcher(注:我所使用的2.1.8版本中过滤器也升级到了StrutsPrepareAndExecuteFilter)
org.apache.struts2.dispatcher.FilterDispatcher的四个功能(必须)
struts2.0的主要Filter,负责四个方面的功能。具体:
(1)执行Actions
过滤器通过ActionMapper对象,来判断是否应该被映射到Action.如果mapper对象指示他应该被映射,过滤链将会被终止,然后Action被调用。这一点非常重要,如果同时使用SiteMesh filter,则SiteMesh filter应该放到该过滤器前,否则Action的输出将不会被装饰。
(2)清除ActionContext
过滤器为了确保内存溢出,会自动的清除ActionContext。这可能会存在一些问题,在和其它的框架集成时,例如SiteMesh。ActionContextCleanUp提供了怎么处理这些问题的一些信息。
(3)维护静态内容
过滤器也会维护在Struts2中使用的一些公共的静态的内容,例如JavaScript文件,CSS文件等。搜索/struts/*范围内的请求,然后将/struts/后面的值映射到一些struts的公共包中,也可以在你的类路径中搜索。
(4)清除ActionContext中的内容。
Finally{ActionContextCleanUp.cleanUp(req);}

ActionContextCleanUp
org.apache.struts2.dispatcher.ActionContextCleanUp(可选)
可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin。该过滤器用来与FilterDispatcher协同工作以便于集成SiteMesh. 通常, 排列过滤器并保证SiteMesh排在第一位, 而让FilterDispatcher排在第二位看起来是最佳方案. 然而, 你可能希望在SiteMesh修饰器中使用WebWork的特性, 包括value stack, 但由于FilterDispatcher将清除ActionContext, 因此修饰器就访问不到想要的数据了.

WEB.XML配置顺序
在WebWork的架构中, 标准的过滤器链(filter-chain)一般以 ActionContextCleanUp 开始, 后面跟着其他需要的过滤器. 最后, 由 FilterDispatcher 处理请求, 通常是将请求传递给ActionMapper. ActionContextCleanUp 的首要用途是为集成SiteMesh服务的. 他会通知FilterDispatcher在正确的时间清除请求. 否则, ActionContext将在SiteMesh修饰器访问数据之前被清除.
在不使用SiteMesh的时候,为了使用WebWork,我们只需要在web.xml配置FilterDispatcher一个过滤器即可,阅读一下FilterDispatcher的JavaDoc和源码,我们可以看到它调用了:
finally {   ActionContextCleanUp.cleanUp(req); }
而且JavaDoc中也提到看ActionContextCleanUp的文档,那我们就去看吧(我没看所以...)
在ActionContextCleanUp中,有这样的代码:
req.setAttribute(CLEANUP_PRESENT, Boolean.TRUE);
如果FilterDispatcher检测到这个属性,就不会清除ActionContext中的内容了,而由ActionContextCleanUp后续的代码来清除,保证了一系列的Filter访问正确的ActionContext.文档中提到,如果用到SiteMesh的Filter或者其他类似Filter,那么设置顺序是:
1 ActionContextCleanUp filter
2 SiteMesh filter
3 FilterDispatcher

Struts 2 中使用的模式--CHAIN OF RESPONSIBILITY(职责链)
  适用性:
  1.有多个对象可以处理统一请求,但是,那个对象处理要到运行时刻决定。
  2.希望在不明确接收者的情况下,向多个对象中的一个提交一个请求。
  3.可处理一个请求的对象集合应该被动态指定。
  思考:
  既然要向未知的接收者提交请求,那么就需要统一的提交界面,也就是说,所有接收者应该实现一个公共接口,来接收请求,当然Delegate可以改变这一状况。一个典型的应用环境就是GUI系统中的事件处理方法。例如,我们可以定义一个OnClick的界面,然后OnClick可以是实际接收对象的一个方法代理:
  OnClick = someObj.doClick;
  最重要的是,OnClick和someObj.doClick之间的关系是可以动态改变的。另外,这个doClick可以向一个对象集合分发该事件,该集合也是可以动态变化的,这时它的静态结构和观察员模式很相似,但是职责链模式并不需要将事件递交给每一个接收者。观察员模式关心的是如何观察到模型的变化,职责链模式关心的是如何递交出事件。这两者还都需要关心如何接收到相应的事件,尽管接收的行为并不一样。
  职责链模式需要关心每一个事件都应该被合适的一个或多个接收者处理(HOOK模式)。例如,在一个消息分派的过程中,我们需要考虑如何增减消息处理过程,以处理相关的消息,通常这些处理过程都是各不相同的行为,并且反过来可能对发送者有影响。观察员模式一般而言,应该是无扰的。
  接收者常常是通过Composite模式来组织的。
  COMMAND(命令)
  适用性:
  1.Command模式是回调函数的一个面向对象的替代品。
  2.Command对象可以有和初始请求无关的生存期
  3.支持取消操作
  4.支持修改日志
  5.用构建在原语操作上的高层操作构造一个系统。
  思考:
  COMMAND模式总是会关联到一个触发者。通常,它提供的是一个非常简单的接口。COMMAND对象一般而言是一个相对高级的对象,他通常可以完成一个相对完整的概念操作,好像是完成了一个事务一样。因为COMMAND比较高级,那么其内部可以安排一些相对底层的支持,例如日志活动。很多COMMAND对象也是同时提供撤销操作。
  如果COMMAND应用于事务系统,并且,一个COMMAND对象对应于一个事务的话,要小心撤销语意。一般而言,不应该撤销一个事务系统中已经完成的事务。而是通过另一个反向的事务来冲抵。例如一个帐务系统,对于错误的记帐流水事务,在向系统提交以前,可以简单撤销(这可以在Command对象的撤销操作中实现,也可以简单放弃)。对于提交以后,则应该提供一个反向的撤销流水事务(不建议在撤销操作中实现),这样系统最终记录两个事务,并且后一个事务可以冲销前一个事务。进一步,如果发现历史帐务流水记录有错,一般的财务逻辑是需要用红字冲正,就更不应该采用撤销的手段了。
  职责链的接收者,可以实现为COMMAND对象,当然,这并不必要。

只有注册用户登录后才能发表评论。


网站导航: