Struts2历史Word文档格式.docx
- 文档编号:8562785
- 上传时间:2023-05-11
- 格式:DOCX
- 页数:9
- 大小:194.43KB
Struts2历史Word文档格式.docx
《Struts2历史Word文档格式.docx》由会员分享,可在线阅读,更多相关《Struts2历史Word文档格式.docx(9页珍藏版)》请在冰点文库上搜索。
Struts1的程序运行流程如图1.7所示。
图1.7
Struts1的程序运行流程
下面就Struts1程序流程具体分析MVC中的三个角色。
(1)Model部分
Struts1的Model部分主要由底层的业务逻辑组件充当,这些业务逻辑组件封装了底层数据库访问、业务逻辑方法实现。
实际上,对于一个成熟的企业应用而言,Model部分也不是一个简单的JavaBean所能完成的,它可能是一个或多个EJB组件,可能是一个WebService服务。
总之,Model部分封装了整个应用的所有业务逻辑,但整个部分并不是由Struts1提供的,Struts1也没有为实现Model组件提供任何支持。
(2)View部分
Struts1的View部分采用JSP实现。
Struts1提供了丰富的标签库,通过这些标签库可以最大限度地减少脚本的使用。
这些自定义的标签库可以输出控制器的处理结果。
虽然Struts1提供了与Ties框架的整合,但Struts1所支持的表现层技术非常单一:
既不支持FreeMarker、Velocity等模板技术,也不支持
JasperReports等报表技术。
(3)Controller部分
Struts1的Controller由两个部分组成。
—系统核心控制器:
由Struts1框架提供,就是系统中的ActionServlet。
—业务逻辑控制器:
由Struts1框架提供,就是用户自己实现的Action实例。
Struts1的核心控制器对应图1.7中的核心控制器(ActionServlet)。
该控制器由Struts1框架提供,继承HttpServlet类,因此可以配置成一个标准的Servlet,该控制器负责拦截所有HTTP请求,然后根据用户请求决定是否需要调用业务逻辑控制器,如果需要调用业务逻辑控制器,则将请求转发给
Action处理,否则直接转向请求的JSP页面。
业务逻辑控制器负责处理用户请求,但业务逻辑控制器本身并不具有处理能力,而是调用Model来完成处理。
Struts1提供了系统所需要的核心控制器,也为实现业务逻辑控制器提供了许多支持。
因此,控制器部分就是Struts1框架的核心。
有时候,我们直接将MVC层称为控制器层。
提示
对于任何的MVC框架而言,其实只实现了C(控制器)部分,但它负责用控制器调用业务逻辑组件,并负责控制器与视图技术(JSP、FreeMarker和Velocity等)的整合。
对于Struts1框架而言,因为它与JSP/Servlet耦合非常紧密,因而导致了许多不可避免的缺陷,随着Web应用的逐渐扩大,这些缺陷逐渐变成制约
Struts1发展的重要因素——这也是Struts2出现的原因。
下面具体分析
Struts1中存在的种种缺陷。
(1)支持的表现层技术单一
Struts1只支持JSP作为表现层技术,不提供与其他表现层技术,例如
Velocity、FreeMarker等技术的整合。
这一点严重制约了Struts1框架的使用,对于目前的很多JavaEE应用而言,并不一定使用JSP作为表现层技术。
虽然Struts1处理完用户请求后,并没有直接转到特定的视图资源,而是返回一个ActionForward对象(可以理解ActionForward是一个逻辑视图名),在struts-config.xml文件中定义了逻辑视图名和视图资源之间的对应关系,当ActionServlet得到处理器返回的ActionForword对象后,可以根据逻辑视图名和视图资源之间的对应关系,将视图资源呈现给用户。
从上面的设计来看,不得不佩服Struts1的设计者高度解耦的设计:
控制器并没有直接执行转发请求,而仅仅返回一个逻辑视图名——实际的转发放在配置文件中进行管理。
但因为Struts1框架出现的年代太早了,那时候还没有
FreeMarker、Velocity等技术,因而没有考虑与这些FreeMarker、Velocity等视图技术的整合。
Struts1已经通过配置文件管理逻辑视图名和实际视图之间的对应关系,只是没有做到让逻辑视图名可以支持更多的视图技术。
虽然Struts1有非常优秀的设计,但由于历史原因,它没有提供与更多视图技术的整合,这严重限制了Struts1的使用。
(2)与ServletAPI严重耦合,难于测试
因为Struts1框架是在Model2的基础上发展起来的,因此它完全是基于
ServletAPI的,所以在Struts1的业务逻辑控制器内,充满了大量的
ServletAPI。
看下面的Action代码片段:
//业务逻辑控制器必须继承Struts1提供的Action类
publicclassLoginActionextendsAction
{
//处理用户请求的execute方法
publicActionForwardexecute(ActionMappingmapping,ActionFormform,
HttpServletRequestrequest,HttpServletResponseresponse)throwsAuctionException
//获取封装用户请求参数的ActionForm对象
//将其强制类型转换为登录用的ActionForm
LoginFormloginForm=(LoginForm)form;
//当用户名为scott,密码为tiger时返回成功
if("
scott"
.equals(loginForm.getUsername()&
&
"
tiger"
.equals(loginForm.getPassword())
//处理成功,返回一个ActionForward对象
returnmapping.findForward("
success"
);
}
else
//处理失败,返回一个ActionForward对象
当我们需要测试上面Action类的execute方法时,该方法有4个参数:
ActionMapping、ActionForm、HttpServletRequest和HttpServletResponse,初始化这4个参数比较困难,尤其是HttpServletRequest和
HttpServletResponse两个参数,通常由Web容器负责实例化。
因为HttpServletRequest和HttpServletResponse两个参数是
ServletAPI,严重依赖于Web服务器。
因此,一旦脱离了Web服务器,Action的测试非常困难。
(3)代码严重依赖于Struts1API,属于侵入式设计
正如从上面代码片段中所看到的,Struts1的Action类必须继承Struts1的Action基类,实现处理方法时,又包含了大量Struts1API:
如
ActionMapping、ActionForm和ActionForward类。
这种侵入式设计的最大弱点在于,一旦系统需要重构时,这些Action类将完全没有利用价值,成为一堆废品。
可见,Struts1的Action类这种侵入式设计导致了较低的代码复用。
WebWork简介
WebWork虽然没有Struts1那样赫赫有名,但也是出身名门,WebWork来自另外一个优秀的开源组织:
opensymphony,这个优秀的开源组织同样开发了大量优秀的开源项目,如Qutarz、OSWorkFlow等。
实际上,WebWork的创始人则是另一个Java领域的名人:
RickardOberg(他就是JBoss和XDoclet的作者)。
相对于Struts1存在的那些先天性不足而言,WebWork则更加优秀,它采用了一种更加松耦合的设计,让系统的Action不再与ServletAPI耦合。
使单元测试更加方便,允许系统从B/S结构向C/S结构转换。
相对于Struts1仅支持JSP表现层技术的缺陷而言,WebWork支持更多的表现层技术,如Velocity、FreeMarker和XSLT等。
WebWork可以脱离Web应用使用,这一点似乎并没有太多优势,因为,一个应用通常开始已经确定在怎样的环境下使用。
WebWork有自己的控制反转
(InversionofControl)容器,通过控制反转,可以让测试变得更简单,测试中设置实现服务接口的Mock对象完成测试,而不需要设置服务注册。
WebWork2使用OGNL这个强大的表达式语言,可以访问值栈。
OGNL对集合和索引属性的支持非常强大。
WebWork建立在XWork之上,使用ServletDispatcher作为该框架的核心控制器,处理HTTP的响应和请求。
从处理流程上来看,WebWork与Struts1非常类似,它们的核心都由控制器组成,其中控制器都由两个部分组成:
—核心控制器ServletDispatcher,该控制器框架提供。
—业务逻辑控制器Action,该控制器由程序员提供。
相对Struts1的Action与ServletAPI紧紧耦合的弱点来说,WebWork的Action则完全与ServletAPI分离,因而该Action更容易测试。
WebWork的Action可以与ServletAPI分离,得益于它灵巧的设计,它使用一个拦截器链,负责将用户请求数据转发到Action,并负责将Action的处理结果转换成对用户的响应。
当用户向Web应用发送请求时,该请求经过ActionContextCleanUp、
SiteMesh等过滤器过滤,由WebWork的核心控制器拦截,如果用户请求需要
WebWork的业务逻辑控制器处理,该控制器则调用Action映射器,该映射器将用户请求转发到对应的业务逻辑控制器。
值得注意的是,此时的业务逻辑控制器并不是开发者实现的控制器,而是WebWork创建的控制器代理。
创建控制器代理时,WebWork需要得到开发者定义的xwork.xml配置文件,控制器代理以用户实现的控制器作为目标,以拦截器链中的拦截器作为处理
(Advice)。
WebWork中创建控制器代理的方式,就是一种AOP(面向切面编程)编程方式,只是这种AOP中的拦截器由系统提供,因此无需用户参与。
如果读者需要获取更多关于AOP编程的知识,请参阅AOP相关资料,或笔者所著的《Spring2.0宝典》一书的第6章。
开发者自己实现的业务逻辑控制器只是WebWork业务控制器的目标——这就是为什么开发者自己实现的Action可以与ServletAPI分离的原因。
当开发者自己的Action处理完HTTP请求后,该结果只是一个普通字符串,该字符串将对应到指定的视图资源。
指定的试图资源经过拦截器链的处理后,生成对客户端的响应输出。
上面整个过程的数据流图如图1.8所示。
与前面的Struts1框架对比,不难发现WebWork在很多地方确实更优秀。
相对Struts1的种种缺点而言,WebWork存在如下优点:
图1.8
WebWork的数据流图
(1)Action无需与ServletAPI耦合,更容易测试
相对于Struts1框架中的Action出现了大量ServletAPI而言,WebWork的Action更像一个普通Java对象,该控制器代码中没有耦合任何ServletAPI。
看下面的WebWork的Action示例:
publicclassLoginActionimplementsAction
//该字符串常量将作为Action的返回值
privatefinalstaticStringLOGINFAIL="
loginfail"
;
//该Action封装的两个请求参数
privateStringpassword;
privateStringusername;
//password请求参数对应的getter方法
publicStringgetPassword()
returnpassword;
//password请求参数对应的setter方法
publicvoidsetPassword(Stringpassword)
this.password=password;
//username请求参数对应的getter方法
publicStringgetUsername()
returnusername;
//username请求参数对应的setter方法
publicvoidsetUsername(Stringusername)
this.username=username;
publicStringexecute()throwsException
yeeku"
.equalsIgnoreCase(getUsername())&
password"
.equals(getPassword()))
ActionContextctx=ActionContext.getContext();
//将当前登录的用户名保存到Session
Mapsession=ctx.getSession();
session.put("
username"
getUsername());
returnSUCCESS;
returnLOGINFAIL;
在上面的Action代码中,我们看不到任何的ServletAPI,当系统需要处理两个请求参数:
username和password时,Action并未通过
HttpServletRequest对象来获得请求参数,而是直接调用访问该Action的
username和password成员属性——这两个属性由Action拦截器负责初始化,以用户请求参数为其赋值。
即使Action中需要访问HTTPSession对象,依然没有在代码中直接出现
HttpSessionAPI,而是以一个Map对象代表了HTTPSession对象。
当我们将WebWork的Action和Struts1的Action进行对比时,不难发现
Struts1的Action确实太臃肿了,确实不如WebWork的Action那么优雅。
如果需要测试上面的Action代码,测试用例的书写将非常容易,因为
execute方法中没有包含任何ServletAPI,甚至没有WebWork的API。
(2)Action无需与WebWork耦合,代码重用率高
在上面的Action代码中,不难发现WebWork中的Action其实就是一个
POJO,该Action仅仅实现了WebWork的Action接口,包含了一个execute方法。
Struts1中的Action类需要继承Struts1的Action类。
我们知道,实现一个接口和继承一个类是完全不同的概念:
实现一个接口对类的污染要小得多,该类也可以实现其他任意接口,还可以继承一个父类;
但一旦已经继承一个父类,则意味着该类不能再继承其他父类。
除此之外,Struts1中Action也包含了一个execute方法,但该方法需要4个参数,类型分别是ActionMapping、ActionForm、HttpServletRequest和
HttpServletResponse,一个包含了这4个参数的方法,除了在Struts1框架下有用外,笔者难以想象出该代码还有任何复用价值。
但WebWork的execute方法则完全不同,该方法中没有出现任何ServletAPI,也没有出现任何
WebWorkAPI,这个方法在任何环境下都有重用的价值。
得益于WebWork灵巧的设计,WebWork中的Action无需与任何ServletAPI、WebWorkAPI耦合,从而具有更好的代码重用率。
(3)支持更多的表现层技术,有更好的适应性
正如从图1.8所见到的,WebWork对多种表现层技术:
JSP、Velocity和
FreeMarker等都有很好的支持,从而给开发更多的选择,提供了更好的适应性。
Struts2起源
经过五年多的发展,Struts1已经成为一个高度成熟的框架,不管是稳定性还是可靠性,都得到了广泛的证明。
但由于它太“老”了,一些设计上的缺陷成为它的硬伤。
面对大量新的MVC框架蓬勃兴起,Struts1也开始了血液的更新。
目前,Struts已经分化成两个框架:
第一个框架就是传统Struts1和
WebWork结合后的Struts2框架。
Struts2虽然是在Struts1的基础上发展起来的,但实质上是以WebWork为核心,Struts2为传统Struts1注入了
WebWork的设计理念,统一了Struts1和WebWork两个框架,允许Struts1和WebWork开发者同时使用Struts2框架。
Struts分化出来的另外一个框架是Shale,这个框架远远超出了Struts1原有的设计思想,它与原有的Struts1的关联很少,它使用全新的设计思想。
Shale更像一个新的框架,而不是Struts的升级。
Shale在很多方面与Struts存在不同之处,其中有两点最为突出:
—
Struts与JSF集成,而Shale则是建立在JSF之上。
Struts实质上是一个巨大的、复杂的请求处理器;
而Shale则是一组能以任何方式进行组合的服务,简单地说,Shale是一种SOA(面向服务架构)架构。
在后面的介绍中,我们会发现,Struts2非常类似于WebWork框架,而不像Struts1框架,因为Struts2是以WebWork为核心,而不是以Struts1为核心的。
正因为此,许多WebWork开发者会发现,从WebWork过渡到Struts2是一件非常简单的事情。
当然,对于传统的Struts1开发者,Struts2也提供了很好的向后兼容性,Struts2可与Struts1有机整合,从而保证Struts1开发者能平稳过渡到
Struts2。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Struts2 历史