Struts 1简介及存在的问题_转载自李刚《Struts 2.1权威指南》

 

1.2.1  Struts 1简介及存在的问题

从过去的岁月来看,Struts 1是所有MVC框架中不容辩驳的胜利者,不管是市场占有率,还是所拥有的开发人群,Struts 1都拥有其他MVC框架不可比拟的优势。Struts 1的成功得益于它丰富的文档、活跃的开发群体。当然,Struts 1是世界上第一个发布的MVC框架:Struts 1.0在2001年6月发布,这一点可能是使它得到如此广泛拥戴的主要原因。

为了使读者可以明白Struts 1的运行机制,下面将简要介绍Struts 1的基本框架。

Struts 1框架以ActionServlet作为核心控制器,整个应用由客户端请求驱动。当客户端向Web应用发送请求时,请求将被Struts 1的核心控制器ActionServlet拦截,ActionServlet根据请求决定是否需要调用业务逻辑控制器处理用户请求(实际上,业务逻辑控制 器还是控制器,它只是负责调用模型来处理用户请求),当用户请求处理完成后,其处理结果通过JSP呈现给用户。

对于整个Struts 1框架而言,控制器就是它的核心,Struts 1的控制器由两个部分组成:核心控制器和业务逻辑控制器。其中核心控制器就是ActionServlet,由Struts 1框架提供;业务逻辑控制就是用户自定义的Action,由应用开发者提供。

对于大部分用户请求而言,都需要得到服务器的处理。当用户发送一个需要得到服务器处理的请求时,该请求被ActionServlet拦截 到,ActionServlet将该请求转发给对应的业务逻辑控制器,业务逻辑控制器调用模型来处理用户请求;如果用户请求只是希望得到某个URL资源, 则由ActionServlet将被请求的资源转发给用户。

Struts 1的程序运行流程如图1.7所示。

 
(点击查看大图)图1.7  Struts 1的程序运行流程

下面就Struts 1程序流程具体分析MVC中的三个角色。

(1)Model部分

Struts 1的Model部分主要由底层的业务逻辑组件充当,这些业务逻辑组件封装了底层数据库访问、业务逻辑方法实现。实际上,对于一个成熟的企业应用而 言,Model部分也不是一个简单的JavaBean所能完成的,它可能是一个或多个EJB组件,也可能是一个WebService服务。总 之,Model部分封装了整个应用的所有业务逻辑,但整个部分并不是由Struts 1提供的,Struts 1也没有为实现Model组件提供任何支持。

(2)View部分

Struts 1的View部分采用JSP实现。Struts 1提供了丰富的标签库,通过这些标签库可以最大限度地减少脚本的使用。这些自定义的标签库可以输出控制器的处理结果。

虽然Struts 1提供了与Ties框架的整合,但Struts 1所支持的表现层技术非常单一:既不支持FreeMarker、Velocity等模板技术,也不支持JasperReports等报表技术。

(3)Controller部分

Struts 1的Controller由两个部分组成。

系统核心控制器:由Struts 1框架提供,就是系统中的ActionServlet。

业务逻辑控制器:由Struts 1框架提供,就是用户自己实现的Action实例。

Struts 1的核心控制器对应图1.7中的核心控制器(ActionServlet)。该控制器由Struts 1框架提供,继承HttpServlet类,因此可以配置成一个标准的Servlet,该控制器负责拦截所有HTTP请求,然后根据用户请求决定是否需要 调用业务逻辑控制器,如果需要调用业务逻辑控制器,则将请求转发给Action处理,否则直接转向请求的JSP页面。

业务逻辑控制器负责处理用户请求,但业务逻辑控制器本身并不具有处理能力,而是调用Model来完成处理。

Struts 1提供了系统所需要的核心控制器,也为实现业务逻辑控制器提供了许多支持。因此,控制器部分就是Struts 1框架的核心。有时候,我们直接将MVC层称为控制器层。

提示  对于任何的MVC框架(除Tapestry外)而言,其实都只实现了C(控制器)部分,但它负责用控制器调用业务逻辑组件,并负责控制器与视图技术(JSP、FreeMarker和Velocity等)的整合。

对于Struts 1框架而言,因为它与JSP/Servlet耦合非常紧密,因而导致了许多不可避免的缺陷,随着Web应用的逐渐扩大,这些缺陷逐渐变成制约Struts 1发展的重要因素--这也是Struts 2出现的原因。下面具体分析Struts 1中存在的种种缺陷。

(1)支持的表现层技术单一

Struts 1只支持JSP作为表现层技术,不提供与其他表现层技术,例如Velocity、FreeMarker等技术的整合。这一点严重制约了Struts 1框架的使用,对于目前的很多Java EE应用而言,并不一定使用JSP作为表现层技术。

虽然Struts 1处理完用户请求后,并没有直接转到特定的视图资源,而是返回一个ActionForward对象(可以理解ActionForward是一个逻辑视图 名),在struts-config.xml文件中定义了逻辑视图名和视图资源之间的对应关系,当ActionServlet得到处理器返回的 ActionForword对象后,可以根据逻辑视图名和视图资源之间的对应关系,将视图资源呈现给用户。

从上面的设计来看,不得不佩服Struts 1的设计者高度解耦的设计:控制器并没有直接执行转发请求,而仅仅返回一个逻辑视图名--实际的转发放在配置文件中进行管理。但因为Struts 1框架出现的年代太早了,那时候还没有FreeMarker、Velocity等技术,因而没有考虑与FreeMarker、Velocity等这些视图 技术的整合。

提示  Struts 1已经通过配置文件管理逻辑视图名和实际视图之间的对应关系,只是没有做到让逻辑视图名可以支持更多的视图技术。

虽然Struts 1有非常优秀的设计,但由于历史原因,它没有提供与更多视图技术的整合,这严重限制了Struts 1的使用。

(2)与Servlet API严重耦合,难于测试

因为Struts 1框架是在Model 2的基础上发展起来的,因此它完全是基于Servlet API的,所以在Struts 1的业务逻辑控制器内,充满了大量的Servlet API。

看下面的Action代码片段:

//业务逻辑控制器必须继承Struts 1提供的Action类
public class LoginAction extends Action
{
//处理用户请求的execute方法
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws AuctionException
{
//获取封装用户请求参数的ActionForm对象
//将其强制类型转换为登录用的LoginForm
LoginForm loginForm = (LoginForm)form;
//当用户名为crazyjava,密码为leegang时返回成功
if ("crazyjava".equals(loginForm.getUsername()
&& "leegang".equals(loginForm.getPassword())
{
//处理成功,返回一个ActionForward对象
return mapping.findForward("success");
}
else
{
//处理失败,返回一个ActionForward对象
return mapping.findForward("failure");
}
}
}

当我们需要测试上面Action类的execute方法时,该方法有4个参数:ActionMapping、ActionForm、 HttpServletRequest和HttpServletResponse,初始化这4个参数比较困难,尤其是 HttpServletRequest和HttpServletResponse两个参数,通常由Web容器负责实例化。

因为HttpServletRequest和HttpServletResponse两个参数是Servlet API,严重依赖于Web服务器。因此,一旦脱离了Web服务器,Action的测试非常困难。

(3)代码严重依赖于Struts 1 API,属于侵入式设计

正如从上面代码片段中所看到的,Struts 1的Action类必须继承Struts 1的Action基类,实现处理方法时,又包含了大量Struts 1 API:如ActionMapping、ActionForm和ActionForward类。这种侵入式设计的最大弱点在于,一旦系统需要重构时,这些 Action类将完全没有利用价值,成为一堆废品。

可见,Struts 1的Action类这种侵入式设计导致了较低的代码复用。

posted @ 2011-10-30 21:19  JaredLam  阅读(605)  评论(0编辑  收藏  举报