标签:
在说到Struts1与Strus2的区别之前,不得不先提到MVC。MVC是一个种设计模式,代表了一种多层的应用程序的实现方式。处理过程为:首先控制器接受了用户的请求,并决定应该调用哪个模型来处理,然后模型处理了用户的请求后返回数据,最后控制器确定用相应的视图将模型返回的数据呈献给用户。
说完了MVC,再说一下为什么要用Struts框架。JSP、Servlet、JavaBean技术的出现给我们构建了强大的企业应用系统提供了可能,但这些技术构建的系统非常繁乱,所以在此基础上我们需要一些规则,一个把这些技术组织起来的规则,这就是框架,Struts便应运而生了。
【Struts1】
下面说Struts1,它是MVC设计模式的一个优秀实现,Struts定义了一个通用的Controller,通过配置文件隔离了Model和View,以Action的概念对用户请求做了封装。它是以ActionServlet作为核心控制器,由ActionServlet负责拦截用户的所有请求。
下面这张图很好的说明了Struts1是如何实现MVC模式的。
Struts1框架的三个重要组成部分:Action、ActionForm(必须实现ActionForm的基类)、ActionForward.
Struts1的工作原理:
【Struts2】
Struts2是以WebWork优秀的设计思想为核心,它只是吸收了Struts框架的部分优点,提供了一个更加整洁的MVC设计模式实现的web应用程序框架,而说它是Struts1的升级产品不过是我们臆想出来的,其实是错误的。它其实算是WbeWork的升级产品。
Struts2由三大部分组成,核心控制器FilterDispatcher、业务控制器Action、用户实现的企业业务逻辑组件。
Struts2的调用流程:
基本的调用流程为:客户端浏览器发出HTTP请求,根据web.xml配置,该请求被FilterDispatcher接收,根据struts.xml配置,找到需要调用的Action类方法,并通过IOC方式,将值注入给Action。Action调用业务逻辑组件处理业务逻辑,这一步包含表单认证。Action执行完毕,根据struts.xml的配置找到对应的返回结果result,并跳转至相应的页面,返回HTTP响应到客户端页面。
举个例子吧,说的怪抽象的。先回忆一个例子,我们平时做项目的时候,拿一个最简单的WelcomeJava例子来说,我们都做了什么呢?首先在web.xml中配置Struts2的过滤器,然后写一个Action类,名称为WelcomeJavaAction,最后在struts.xml配置文件中配置Action的这个类,为它指定返回哪个页面。最后再写一个JSP。那么在浏览器中输入一个地址的时候,Struts2的内部是怎么运作的呢?现在我们就来剖析一下。
首先,在浏览器中输入URL地址:"http://localhost:4545/WelcomeJava/WelcomeJavaAction.action",该请求会被Tomcat或Jboss等服务器接收到,服务器会根据请求URL中的web上下文,也就是"/WelcomeJava"来选择处理这个请求的web应用,那就是由WelcomeJava这个web工程来处理这个请求,也就是我们项目的web项目,也就是我们的项目名。然后,web容器会读取这个WelcomeJava工程的web.xml,在web.xml配置文件中进行匹配,发现后缀为".action"的请求,由Struts2这个过滤器来处理,根据Filter的配置,找到实际的类为FilterDispatcher。web容器会获取FilterDispatcher这个类的实例,然后回调doFilter方法,进行真正的处理,FilterDispatcher作为前端控制器,是整个Struts2的调度中心。
Struts2的工作机制:
继续细剖析Struts2的内部工作机制。在上面的架构图上,我们可以看到三个过滤器层次,其中ActionContextCleanUp和FilterDispatcher是Struts2的过滤器,而SiteMesh等其他过滤器不是Struts2的过滤器。下面,来系统的理一下Struts2的工作机制。
第一步、首先FilterDispatcher将请求转发给ActionMapper,ActionMapper负责识别当前的请求是否需要Struts2处理。
第二步、ActionMapper告诉FilterDispatcher需要处理这个请求,FilterDispatcher会停止过滤器链以后的部分,所以在通常情况下,FilterDispatcher应该出现在过滤器链的最后。然后创建一个ActionProxy对象,这个对象作为Action与xwork之间的中间层,会代理Action的运行过程。
第三步、ActionProxy对象刚被创建出来的时候,并不知道要运行哪个Action,它手里只有从FilterDispatcher中拿到的请求的URL,这时候,它去向ConfigurationManager询问到底要运行哪个Action。回忆一下,某个特定的URL由哪个Action响应由谁负责?定义在什么地方?没错,在struts.xml配置文件中。而ConfigurationManager就是负责读取并管理struts.xml的,可以简单的理解为ConfigurationManager是struts.xml在内存中的映像,在服务器启动的时候,ConfigurationManager会一次性的把struts.xml中的所有信息读到内存里缓存起来,以保证ActionProxy拿来访问的URL向它询问运行哪个Action的时候,就可以直接匹配、查询并回答了。
第四步、ActionProxy拿到了运行了哪个Action,相关的拦截器以及所有可能使用的result信息,就可以着手建立ActionInvocation对象了,ActionInvocation对象描述了Action运行的整个过程。注意:Action运行绝对不仅仅是运行Action的execute方法这么简单,还包括其他部分,完整的调用过程由ActionInvocation对象负责。
第五步、拦截器的运行被分为两个部分,一部分是在Action之前运行,一部分是在result之后运行,而且顺序正好是反过来的,也就是在Action之前的执行顺序是这样的:比如拦截器1,2,3,那么在result之后,再次运行拦截器的时候,顺序变成了拦截器3,2,1.总之,ActionInvocation对象执行的时候比较复杂,会做很多事情。
第六步、然后执行Action中的execute方法。
第七步、然后根据execute方法返回的结果,也就是result,在struts.xml中匹配选择下一个页面。
第八步、找到页面后,由于现在的页面一般都是模板页面,在页面上可以通过struts2自带的标签库来访问需要的数据,并最终生成页面。
第九步、最后,ActionInvocation对象再按照拦截器的引用顺序的倒序依次执行各个拦截器的后置部分。
第十步、ActionInvocation对象执行完毕后,实际上已经得到了响应对象,也就是HttpServletResponse对象,最后按与过滤器配置定义相反的顺序依次经过过滤器,向用户展示出响应的结果。
【比较】:
1、从Action继承的是接口还是类的方面比较:
Struts1被要求Action类继承一个抽象基类,Struts1的一个具体问题是使用抽象类编程而不是接口,Struts1的一个普遍问题是使用抽象类编程而不是接口。Struts2的Action类可以实现一个Action接口,也可以实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类去实现常用的接口,Action接口不是必须的,任何有execute标识的POJO对象都可作为Struts2的Action对象。
2、线程安全方面比较:
Strtus1的Action是单例模式,而且必须是线程安全的。因为仅有Action的一个实例来处理所有的请求。Struts2的Action对象为每一个请求产生一个实例,因此Struts2没有线程安全问题。
3、Servlet的依赖问题
Struts1的Action依赖于ServletAPI,因为当一个Action被调用时,HttpServletRequest和HttpServletResponse被传递给execute方法。Strtus2的Action不依赖于容器,允许Action脱离容器单独被测试.
Struts1和Struts2的比较就先总结到这里,Struts1现在都不大用了,但是本着学习的态度还是要总结总结,这样比较着学习才知道Struts1和Struts2的区别,有了这样的总结可不要再说Struts2是Struts1的升级产品了,那可就太丢人了,好了,下篇博客我们继续回顾Java基础的相关内容。
标签:
原文地址:http://blog.csdn.net/gaoying_blogs/article/details/45152531