框架(Framework)是可重用的半完成的应用程序可以用来产生专门的定制程序
您只要细心地研究真实的应用程序就会发现程序大致上由两类性质不同的组件组成一类与程序要处理的具体事务密切相关我们不妨把它们叫做业务组件另一类是应用服务比如说一个税务征管系统和一个图书管理系统会在处理它们的业务方面存在很大的差异这些直接处理业务的组件由于业务性质的不同不大可能在不同的系统中重用而另一些组件如决定程序流向的控制输入的校验错误处理及标签库等这些只与程序相关的组件在不同的系统中可以很好地得到重用人们自然会想要是把这些在不同应用程序中有共性的一些东西抽取出来做成一个半成品程序这样的半成品就是所谓的程序框架再做一个新的东西时就不必白手起家而是可以在这个基础上开始搭建实际上有些大型软件企业选择自己搭建这样的框架但大多数中小型软件企业或者其他组织没有条件自己建立框架
Struts作为一个开放原代码的应用框架在最近几年得到了飞速的发展在JSP Web应用开发中应用得非常广泛有的文献上说它已经成为JSP Web应用框架的事实上的标准那么究竟什么是Struts呢?
要回答这个问题还得从JSP Web应用的两种基本的结构模式Model 和Model 说起为了给读者一些实实在在的帮助并力图让学习曲线变得平坦一些我想采用实例驱动的方法来逐步深入地回答有关问题因为学一门技术的最好方法莫过于在实践中学习在实践中体会逐步加深对其精神实质的理解和把握而不是一上来就引入一大堆新概念让大家觉得无所适从或者死记硬背一大堆概念而面对一个真正的实际需求束手无策正如一个人即使在书本上学成了游泳博士只要他不下水我想他也是不大可能真正会游泳的
Model 结构如图所示
图
mode 是一个以JSP文件为中心的模式在这种模式中JSP页面不仅负责表现逻辑也负责控制逻辑专业书籍上称之为逻辑耦合在页面中这种处理方式对一些规模很小的项目如一个简单的留言簿也没什么太大的坏处实际上人们开始接触一些对自己来说是新的东西的时候比如用JSP访问数据库时往往喜欢别人能提供一个包含这一切的单个JSP页面因为这样在一个页面上他就可以把握全局便于理解但是用Model 模式开发大型时程序流向由一些互相能够感知的页面决定当页面很多时要清楚地把握其流向将是很复杂的事情当您修改一页时可能会影响相关的很多页面大有牵一发而动全身的感觉使得程序的修改与维护变得异常困难还有一个问题就是程序逻辑开发与页面设计纠缠在一起既不便于分工合作也不利于代码的重用这样的程序其健壮性和可伸缩性都不好
Grady Booch等人在UML用户指南一书中强调建模的重要性时打了一个制作狗窝私人住宅和大厦的形象比喻来说明人们处理不同规模的事物时应该采用的合理方法一样人们对不同规模的应用程序也应该采用不同的模式
为了克服Model 的缺陷人们引入了Model 如图所示
图
它引入了控制器这个概念控制器一般由servlet来担任客户端的请求不再直接送给一个处理业务逻辑的JSP页面而是送给这个控制器再由控制器根据具体的请求调用不同的事务逻辑并将处理结果返回到合适的页面因此这个servlet控制器为应用程序提供了一个进行前后端处理的中枢一方面为输入数据的验证身份认证日志及实现国际化编程提供了一个合适的切入点另一方面也提供了将业务逻辑从JSP文件剥离的可能业务逻辑从JSP页面分离后JSP文件蜕变成一个单纯完成显示任务的东西这就是常说的View而独立出来的事务逻辑变成人们常说的Model再加上控制器Control本身就构成了MVC模式实践证明MVC模式为大型程序的开发及维护提供了巨大的便利
其实MVC开始并不是为Web应用程序提出的模式传统的MVC要求M将其状态变化通报给V但由于Web浏览器工作在典型的拉模式而非推模式很难做到这一点因此有些人又将用于Web应用的MVC称之为MVC正如上面所提到的MVC是一种模式当然可以有各种不同的具体实现包括您自己就可以实现一个体现MVC思想的程序框架Struts就是一种具体实现MVC的程序框架它的大致结构如图三所示
图三
图三基本勾勒出了一个基于Struts的应用程序的结构从左到右分别是其表示层(view)控制层(controller)和模型层(Model)其表示层使用Struts标签库构建来自客户的所有需要通过框架的请求统一由叫ActionServlet的servlet接收(ActionServlet Struts已经为我们写好了只要您应用没有什么特别的要求它基本上都能满足您的要求)根据接收的请求参数和Struts配置(strutsconfigxml)中ActionMapping将请求送给合适的Action去处理解决由谁做的问题它们共同构成Struts的控制器Action则是Struts应用中真正干活的组件开发人员一般都要在这里耗费大量的时间它解决的是做什么的问题它通过调用需要的业务组件(模型)来完成应用的业务业务组件解决的是如何做的问题并将执行的结果返回一个代表所需的描绘响应的JSP(或Action)的ActionForward对象给ActionServlet以将响应呈现给客户
过程如图四所示
这里要特别说明一下的是就是Action这个类上面已经说到了它是Struts中真正干活的地方也是值得我们高度关注的地方可是关于它到底是属于控制层还是属于模型层存在两种不同的意见一种认为它属于模型层如《JSP Web编程指南》另一些则认为它属于控制层如《Programming Jakarta Struts》《Mastering Jakarta Struts》和《Struts Kick Start》等认为它是控制器的一部分还有其他一些书如《Struts in Action》也建议要避免将业务逻辑放在Action类中也就是说图中Action后的括号中的内容应该从中移出但实际中确有一些系统将比较简单的且不打算重用的业务逻辑放在Action中所以在图中还是这样表示显然将业务对象从Action分离出来后有利于它的重用同时也增强了应用程序的健壮性和设计的灵活性因此它实际上可以看作是Controller与Model的适配器如果硬要把它归于那一部分笔者更倾向于后一种看法即它是Controller的一部分换句话说它不应该包含过多的业务逻辑而应该只是简单地收集业务方法所需要的数据并传递给业务对象实际上它的主要职责是
校验前提条件或者声明
调用需要的业务逻辑方法
检测或处理其他错误
路由控制到相关视图
上面这样简单的描述初学者可能会感到有些难以接受下面举个比较具体的例子来进一步帮助我们理解如假设我们做的是个电子商务程序现在程序要完成的操作任务是提交定单并返回定单号给客户这就是关于做什么的问题应该由Action类完成但具体怎么获得数据库连接插入定单数据到数据库表中又怎么从数据库表中取得这个定单号(一般是自增数据列的数据)这一系列复杂的问题这都是解决怎么做的问题则应该由一个(假设名为orderBo)业务对象即Model来完成orderBo可能用一个返回整型值的名为submitOrder的方法来做这件事Action则是先校验定单数据是否正确以免常说的垃圾进垃圾出如果正确则简单地调用orderBo的submitOrder方法来得到定单号它还要处理在调用过程中可能出现任何错误最后根据不同的情况返回不同的结果给客户
二为什么要使用Struts框架
既然本文的开始就说了自己可以建这种框架为什么要使用Struts呢?我想下面列举的这些理由是显而易见的首先它是建立在MVC这种公认的好的模式上的Struts在MV和C上都有涉及但它主要是提供一个好的控制器和一套定制的标签库上也就是说它的着力点在C和V上因此它天生就有MVC所带来的一系列优点如结构层次分明高可重用性增加了程序的健壮性和可伸缩性便于开发与设计分工提供集中统一的权限控制校验国际化日志等等其次它是个开源项目得到了包括它的发明者Craig RMcClanahan在内的一些程序大师和高手持续而细心的呵护并且经受了实战的检验使其功能越来越强大体系也日臻完善最后是它对其他技术和框架显示出很好的融合性如现在它已经与tiles融为一体可以展望它很快就会与JSF等融会在一起当然和其他任何技术一样它也不是十全十美的如它对类和一些属性参数的命名显得有些随意给使用带来一些不便还有如Action类execute方法的只能接收一个ActionForm参数等但瑕不掩瑜这些没有影响它被广泛使用
三Struts的安装与基本配置
我们主要针对Struts版本进行讲解这里假定读者已经配置好java运行环境和相应的Web容器本文例子所使用的是jsdk和Tomcat下面将采用类似于step by step的方式介绍其基础部分
安装Struts
到 下载Struts的安装文件本文例子使用的是版
接下来您要进行如下几个步骤来完成安装
解压下载的安装文件到您的本地硬盘
生成一个新的Web应用假设我们生成的应用程序的根目录在/Webapps/mystruts目录在serverxml文件中为该应用新建一个别名如/mystruts
从第步解压的文件中拷贝下列jar文件到/Webapps/mystruts/WEBINF/lib目录主要文件有如下一些
quote: strutsjarcommons-beanutilsjarcommons-collectionsjarcommons-dbcpjarcommons-digesterjarcommons-loggingjarcommons-pooljarcommons-servicesjarcommons-validatorjar
创建一个webxml文件这是一个基于servlet的Web应用程序都需要的部署描述文件一个Struts Web应用在本质上也是一个基于servlet的Web应用它也不能例外
Struts有两个组件要在该文件中进行配置它们是ActionServlet和标签库下面是一个配置清单
quote: //EN app__dtd> action orgapachestrutsactionActionServlet config /WEBINF/strutsconfigxml debug action *do /WEBINF/strutsbeantld /WEBINF/strutsbeantld /WEBINF/strutshtmltld /WEBINF/strutshtmltld /WEBINF/strutslogictld /WEBINF/strutslogictld
上面我们在webxml中完成了对servlet和标签库的基本配置而更多的框架组件要在strutsconfigxml中进行配置
创建一个基本的strutsconfigxml文件并把它放在/Webapps/mystruts/WEBINF/目录中该文件是基于Struts应用程序的配置描述文件它将MVC结构中的各组件结合在一起开发的过程中会不断对它进行充实和更改在Struts时一个应用只能有一个这样的文件给分工开发带来了一些不便在Struts时可以有多个这样的文件将上述缺点克服了需在该文件中配置的组件有datasources
quote: globalexecptionsformbeansglobalforwardsactionmappingscontrollermessageresourcesplugin配置清单如下 quote: //EN config__dtd>
到此为止我们已经具备了完成一个最简单Struts应用的所需的各种组件前面已经提到在开发过程中我们会不断充实和修改上面两个配置描述文件下面我们将实际做一个非常简单的应用程序来体验一下Struts应用开发的真实过程以期对其有一个真实的认识在完成基础部分的介绍后笔者会给出一些在实际开发中经常用到而又让初学者感到有些难度的实例最后会介绍Struts与其他框架的关系及结合它们生成应用程序的例子