现在的位置: 首页 > 综合 > 正文

struts2-横空出世

2012年07月27日 ⁄ 综合 ⁄ 共 2857字 ⁄ 字号 评论关闭

 

    新版本的产生,毫无疑问是因为旧版本的开始落伍。struts1.x曾经辉煌灿烂,但现在已经成了明日黄花。大家都是使用struts1.x的老手,下面我们共同来找一下struts 1.x的茬:

 

1. 令人头痛的ActionForm

使用Struts 1框架开发过大型Web应用程序的开发人员说起ActionForm,都是头痛加无奈。为什么这么说呢?要理解ActionForm为什么让人头痛,就要从现代软件开发的分层结构说起。

在现代企业软件开发中,分层解耦是两个必须要考虑的要素。经典的软件分层结构如图1-5所示。

 

其中,数据访问层实现对数据库操作的封装,以隔离具体业务和数据库之间的联系;而业务逻辑层则实现对业务逻辑的封装,隔离用户操作的界面和具体业务逻辑;表现层即用户界面层,提供用户操作接口。这种分层封装的好处是分化了复杂的系统,同时也提高了系统的可维护性,使得开发过程中的分工协作更加方便快捷。采用这种层次结构,上层应该只依赖于它的下层结构,而不应该跨层依赖;同时,下层不应该依赖于它的上层结构,也就是说,业务逻辑层和数据访问层绝对不要依赖于表现层。在业务逻辑层和数据访问层的代码中,不要出现调用表现层代码的情况。遵循这个原则将简化在相同的基础上替换表现层的代价,也使得表现层的修改所带来的连锁反应尽可能小。

Struts是属于表现层的技术,在Struts中,为了接收表单的数据,我们必须编写一个从StrutsActionForm类继承的类,否则你就只能自己从HttpServletRequest中提取数据了。然而,不使用ActionForm,意味着你需要自己对表单数据做初始化,以及自己编写代码对表单数据进行验证。使用从ActionForm继承的类,如果更换Web框架,这个类也将被废弃。ActionForm中的数据往往需要传递给业务逻辑层和数据访问层进行处理,为了避免业务逻辑层和数据访问层依赖于Struts,通常我们会再编写一个和ActionForm类具有相同属性的普通JavaBean类,在ActionForm对象接收到数据后,将其中的数据原封不动地复制到JavaBean对象中,然后将这个JavaBean对象 向下层传递。想一想,如果能够直接使用普通的JavaBean对象来接收表单数据该多好,既可以避免多余的数据复制步骤,又可以不依赖于Struts框架。你可能会认为额外增加的这一步骤也没有什么,考虑到程序中可能还会存在着POPersistent Object,持久化对象,位于数据访问层,对应着数据库表中一条记录)和JavaBean对象之间的数据复制,加上众多的表单,对象与对象之间的数据复制会让你不胜其烦。

 

2. 支持的表现层技术单一

struts 1 只支持JSP作为表现层技术,不提供与其他表现层技术,例如Velocity,FreeMarker整合.这一点严重制约了struts 1框架的使用,对于目前的很多java EE应用而言,并不一定使用JSP作为表现层技术.虽然struts 1 处理完用户请求后,并没有直接转到特定的视图资源,而是返回一个ActionForward对象.从上面的设计来看,不得不佩服struts1 设计者高度解耦的设计:控制器并没有直接执行转发请求,而仅仅返回一个逻辑视图名----实际的转发放在配置文件中进行管理. 但因为 struts 1 框架出现的年代太早了,那时候还没有FreeMarker,Velocity等技术,因而没有考虑与这些视图技术的整合.

 

3. Servlet API 严重耦合,难于测试

因为struts 1框架是在model 2的基础上发展起来的,因此它完全是基于Servlet  API,所以在struts 1的逻辑控制器内,充满了大量的 servlet API.看下面的 Action 代码片段:

package com.wepull.action;

 

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

 

public class LoginAction extends Action {

 

   @Override

   public ActionForward execute(ActionMapping mapping, ActionForm form,

         HttpServletRequest request, HttpServletResponse response)

         throws Exception {

     

      return mapping.findForward("home");

   }

}

 

当我们需要测试上面Action类的execute 方法时,该方法有4个参数:ActionMapping,ActionForm,HttpServletRequest HttpServletResponse,初始化这4参数比较困难,尤其是 HttpServletRequest HttpServletResponse两个参数,通常由web容器负责实例化.因为 HttpServletRequest HttpServletResponse 两个参数是 Servlet API,严重依赖于Web服务器.因此,一旦脱离了web服务器,Action的测试非常困难.当然,也可以使用第三方的测试工具——JUnit的扩展工具StrutsTestCase来对Action进行单元测试。

 

4. 代码严重依赖Struts 1,属于侵入式设计

正如上面代码片段中所看到的,Struts 1Action必须继承 Struts 1Action基类,实现处理方法时,又包含了大量的struts 1API:ActionMapping,ActionFormActionForward.这种侵入式设计的最大弱点在于,一旦系统需要重构时,这些Action类将完全没有利用价值,成为一堆废品.可见,struts 1Action类这种侵入式设计导致了较低的代码复用.在这一点上,Struts1该好好借鉴一下Spring框架.

 

5. 标签库设计的繁琐冗杂

提到Struts1的标签库,大部分朋友会摇头。正所谓,吾未见其明也!Struts1的标签库分的太细:Html标签,Bean标签,Logic标签,Tiles标签,Nest标签等。功能庞杂而且书写和使用并不方便,增加了学习的曲线和应用的复杂度。对比一下Struts1的标签和JSTL大家就该知道Struts1的标签库设计

抱歉!评论已关闭.