MVC设计模式的Struts技术实现(1)
引言
在目前国内的面向中小企业的Web应用程序设计中,以单纯的ASP/JSP/Servlet代码构建的基于服务器端运行的系统占大多数。但上述系统有一个共同的缺陷,就是当业务逻辑越来越复杂的时候,系统构建所带来的复杂度和所耗费的成本将进一步提升,由于结构的不清晰所带来的系统可读性也进一步降低,后期的维护和扩展难度进一步增加。鉴于此,在J2EE领域,业界通常采用在Server集成一些可复用的组件比如EJB等以及FrameWork技术来使得系统结构清晰化,以及实现软件的可复用、可扩展和高效率。在这里,我们采用Jakarta Struts技术,通过和Logical层、DataPersistence的配合,快速构建一个可复用、可扩展的、结构清晰的Web应用程序--LPMT。
事实证明,作为一个日渐成熟的优秀的FrameWork技术,Struts在构建的基于MVC设计模式的Web系统方面有得天独厚的优势。本文谨从MVC架构设计、控制逻辑实现、WebForm技术实现、代码复用等方面对Struts在LPMT中的应用作一个技术总结。
第一章 应用系统开发框架对软件开发的意义
软件构件化是21世纪软件工业发展的大势趋。工业化的软件复用已经从通用类库进化到了面向领域的应用框架。Gartner Group认为:“到2003年,至少70%的新应用将主要建立在如软件构件和应用框架这类‘构造块’之上;应用开发的未来就在于提供一开放体系结构,以方便构件的选择、组装和集成”。框架的重用已成为软件生产中最有效的重用方式之一。
1.1 什么是系统开发框架框架是整个或部分系统的可重用设计部分,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。框架规定了应用的体系结构,阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程,表现为一组抽象类以及其实例之间协作的方法,它为构件复用提供了上下文(Context)关系。框架是构件技术、软件体系结构研究和应用软件开发三者发展结合的产物。在很多情况下,框架通常以构件库的形式出现,但构件库只是框架的一个重要部分。框架的关键还在于框架内对象间的交互模式和控制流模式。
框架是实现了某应用领域通用完备功能(除去特殊应用的部分)的底层服务。使用这种框架的编程人员可以在一个通用功能已经实现的基础上开始具体的系统开发。框架提供了所有应用期望的默认行为的类集合。具体的应用通过重写子类(该子类属于框架的默认行为)或组装对象来支持应用专用的行为。
应用框架强调的是软件的设计重用性和系统的可扩充性,以缩短大型应用软件系统的开发周期,提高开发质量。与传统的基于类库的面向对象重用技术比较,应用框架更注重于面向专业领域的软件重用。应用框架具有领域相关性,构件根据框架进行复合而生成可运行的系统。框架的粒度越大,其中包含的领域知识就更加完整。
1.2 框架、构件与设计模式框架(Framework)、构件(Component)和设计模式(Design pattern)是一个成熟的系统平台中三个重要的部分,同时又是三个很容易混淆的概念。框架往往是为实现一个或多个设计模式而设计的可重用可扩展的设计,是软件系统开发的半成品,而构件是框架当中的可重用的工具包、类库或者API。
构件通常是代码重用,而设计模式是设计重用,框架则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。在软件生产中有三种级别的重用:内部重用,即在同一应用中能公共使用的抽象块;代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用;应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得最高级别的重用性。
框架与设计模式虽然相似,但却有着根本的不同。设计模式是对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比框架更抽象;框架可以用代码表示,也能直接执行或复用,而对模式而言只有实例才能用代码表示;设计模式是比框架更小的元素,一个框架中往往含有一个或多个设计模式,框架总是针对某一特定应用领域,但同一模式却可适用于各种应用。可以说,框架是软件,而设计模式是软件的知识。
1.3 应用系统开发框架对软件开发的意义框架的最大好处就是重用。面向对象系统获得的最大的复用方式就是框架,一个大的应用系统往往可能由多层互相协作的框架组成。
由于框架能重用代码,因此从一已有构件库中建立应用变得非常容易,因为构件都采用框架统一定义的接口,从而使构件间的通信简单。
框架能重用设计。它提供可重用的抽象算法及高层设计,并能将大系统分解成更小的构件,而且能描述构件间的内部接口。这些标准接口使在已有的构件基础上通过组装建立各种各样的系统成为可能。只要符合接口定义,新的构件就能插入框架中,构件设计者就能重用构架的设计。
框架还能重用分析。所有的人员若按照框架的思想来分析事务,那么就能将它划分为同样的构件,采用相似的解决方法,从而使采用同一框架的分析人员之间能进行沟通。
目前的主流的系统开发框架大都提供了对数据持久性、事务、安全性、负载均衡、应用集成等问题的现成的解决方案,因此采用框架技术进行软件开发的主要优点包括:
(1) 领域内的软件结构一致性好;
(2) 建立更加开放的系统;
(3) 重用代码大大增加,软件生产效率和质量也得到了提高;
(4) 软件设计人员要专注于对领域的了解,使需求分析更充分;
(5) 存储了经验,可以让那些经验丰富的人员去设计框架和领域构件,而不必限于低层编程;
(6) 允许采用快速原型技术;
(7) 有利于在一个项目内多人协同工作;
(8) 大粒度的重用使得平均开发费用降低,开发速度加快,开发人员减少,维护费用降低,而参数化框架使得适应性、灵活性增强。
第二章 MVC设计模式及Struts技术
MVC(Model-View-Controller,模型-视图-控制器)设计模式是一种基于请求-响应(Request-Response)模式的应用框架。Struts是Apache Software Foundation针对MVC设计模式开发的运行于Server端开源项目。Struts基于Java Servlet/JavaServer Pages技术,试图提供一种能够分离表现层,并且允许表现层独立于传输层和数据持久层的开源框架。自Struts发布之日起,它就受到开源社区的欢迎和广泛支持,也日益成为开源社区的一个备受瞩目的项目。
2.1 MVC设计模式MVC结构的框架的组成部分包括以下的内容:
l 模型(Model)
模型包含了应用程序的核心,它封装了应用程序的数据结构和事务逻辑,集中体现了应用程序的状态。有时候仅包含状态信息,因为它并不了解视图或控制器的信息。JavaBean很适合扮演这个角色,因为其能够处理绝大部分事务逻辑和数据结构,还能与数据库或文件系统进行交互,承担维护应用程序数据的责任。
l 视图(View)
视图实现模块的外观,它是应用程序的外在表现。它可以访问模型的数据,却不了解模型的情况,同时它也不了解控制器的情况。当模型发生改变时,视图会得到通知,它可以访问模型的数据,但不能改变这些数据。Web界面的开发人员不需要了解或关心数据库发生什么事情,或者事务逻辑进行了什么操作,他只需要掌握HTML的知识,而不需要深入了解Java。JSP页面适合完成这个功能,因为它只包含很少的非HTML代码。
l 控制器(Controller)
控制器控制整个框架中各个组件的协调工作,对用户的输入做出反应,并且将模型和视图联系在一起,它创建并设置模块。Servlet能够接受客户端的HTTP请求,并且根据需要创建所需的JavaBeans,然后将模块产生的变化通知给视图。
Model、View、Controller这三类组件各自的责任以及它们之间的关系如图1所示。
实现MVC设计模式的系统通常会包括业务逻辑层、数据逻辑层。
业务逻辑层(Business Logic):这是FrameWork所要解决问题的关键;对框架本身来说,这里仅仅只是概念和几个提供服务的基础组件,真正的实现与客户的业务逻辑接轨,还需要开发人员在框架上再次扩展;
数据逻辑层(Data Logic):绝大部分应用系统都需要涉及到数据交互,这一层主要包括了数据逻辑和数据访问接口。在MVC结构的框架中,Model组件用于描述应用程序中的数据以及操作该数据的方法,与用户界面无关;View组件负责将数据展现给用户;Controller组件将用户操作翻译为对Model组件的操作;接到Controller传来的操作之后,Model再更新View,以及反映出数据的变化。
在MVC框架下的Web应用系统中,由于HTTP本身缺乏状态信息,客户端必须对服务器进行再查询才能发现由输入所造成的改变,在这种情况下,控制器不能将应用程序的改变通知视图。一般情况下,客户端不得不再次查询视图才能看到更新后的情况,基于这样的改进后的框架称为MVC的模型2体系。
2.2 Struts结构和处理流程Struts利用Jsp页面、自定义的标签库、Java Servlet和Action等类来实现服务器端建模,并为MVC模式设计提供相应的组件。
2.2.1 Controller
控制器的作用是从客户端接受请求,并且选择执行相应的业务逻辑,然后把响应结果送回到客户端。在Struts中Controller功能由图中ActionServlet和ActionMapping对象构成:核心是一个Servlet类型的对象ActionServlet,它用来接受客户端的请求。ActionServlet包括一组基于配置的ActionMapping对象,每个ActionMapping对象实现了一个请求到一个具体的Model部分中Action处理器对象之间的映射。
2.2.2 Model
MVC系统中的Model部分从概念上可以分为两类――系统的内部状态和改变系统状态的动作。Struts为Model部分提供了Action和ActionForm对象:所有的Action处理器对象都是开发者从Struts的Action类派生的子类。Action处理器对象封装了具体的处理逻辑,调用业务逻辑模块,并且把响应提交到合适的View组件以产生响应。Struts提供的ActionForm组件对象,它可以通过定义属性描述客户端表单数据。开发者可以从它派生子类对象,利用它和Struts提供的自定义标记库结合可以实现对客户端的表单数据的良好封装和支持,Action处理器对象可以直接对它进行读写,而不再需要和request、response对象进行数据交互。通过ActionForm组件对象实现了对View和Model之间交互的支持。
2.2.3 View
Struts应用中的View部分是通过JSP技术实现的。Struts提供了自定义的标签库可以使用,通过这些自定义标签可以非常好地和系统的Model部分交互,通过使用这些自定义标签创建的JSP表单,可以实现和Model部分中的ActionForm的映射,完成对用户数据的封装,同时这些自定义标签还提供了像模板定制等多种显示功能。
Struts框架的处理流程清楚的体现了MVC系统的特点,简单的Struts组件结构如左图3所示。Struts Controller ActionServlet处理客户请求,利用配置的ActionMapping对象把请求映射到Action处理器对象进行处理。Action处理对象访问ActionForm中的数据,处理和响应客户请求,它还调用后台的Bean组件,这些组件封装了具体的业务逻辑。Action处理器对象根据处理结果通知Controller,Controller进行下一步的处理。
2.3 利用Struts框架进行MVC开发的流程在利用Struts框架进行MVC开发的时候,我们采用如下开发流程:
(1) 收集和定义应用需求。
(2) 基于数据采集和显示的原则定义和开发"屏幕显示"需求。
(3) 为每一个"屏幕显示"定义访问路径。
(4) 定义ActionMappings建立到应用业务逻辑之间的联系。
(5) 开发满足"屏幕显示"需求的所有支持对象。
(6) 基于每一个"屏幕显示"需求提供的数据属性来创建对应的ActionForm对象。
(7) 开发被ActionMapping调用的Action对象。
(8) 开发应用业务逻辑对象 (Bean,EJB,等等)。
(9) 对应ActionMapping设计的流程创建JSP页面。
(10) 建立合适的配置文件struts-config.xml,web.xml。
(11) 开发/测试/部署。
在目前国内的面向中小企业的Web应用程序设计中,以单纯的ASP/JSP/Servlet代码构建的基于服务器端运行的系统占大多数。但上述系统有一个共同的缺陷,就是当业务逻辑越来越复杂的时候,系统构建所带来的复杂度和所耗费的成本将进一步提升,由于结构的不清晰所带来的系统可读性也进一步降低,后期的维护和扩展难度进一步增加。鉴于此,在J2EE领域,业界通常采用在Server集成一些可复用的组件比如EJB等以及FrameWork技术来使得系统结构清晰化,以及实现软件的可复用、可扩展和高效率。在这里,我们采用Jakarta Struts技术,通过和Logical层、DataPersistence的配合,快速构建一个可复用、可扩展的、结构清晰的Web应用程序--LPMT。
事实证明,作为一个日渐成熟的优秀的FrameWork技术,Struts在构建的基于MVC设计模式的Web系统方面有得天独厚的优势。本文谨从MVC架构设计、控制逻辑实现、WebForm技术实现、代码复用等方面对Struts在LPMT中的应用作一个技术总结。
第一章 应用系统开发框架对软件开发的意义
软件构件化是21世纪软件工业发展的大势趋。工业化的软件复用已经从通用类库进化到了面向领域的应用框架。Gartner Group认为:“到2003年,至少70%的新应用将主要建立在如软件构件和应用框架这类‘构造块’之上;应用开发的未来就在于提供一开放体系结构,以方便构件的选择、组装和集成”。框架的重用已成为软件生产中最有效的重用方式之一。
1.1 什么是系统开发框架框架是整个或部分系统的可重用设计部分,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。前者是从应用方面而后者是从目的方面给出的定义。框架规定了应用的体系结构,阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程,表现为一组抽象类以及其实例之间协作的方法,它为构件复用提供了上下文(Context)关系。框架是构件技术、软件体系结构研究和应用软件开发三者发展结合的产物。在很多情况下,框架通常以构件库的形式出现,但构件库只是框架的一个重要部分。框架的关键还在于框架内对象间的交互模式和控制流模式。
框架是实现了某应用领域通用完备功能(除去特殊应用的部分)的底层服务。使用这种框架的编程人员可以在一个通用功能已经实现的基础上开始具体的系统开发。框架提供了所有应用期望的默认行为的类集合。具体的应用通过重写子类(该子类属于框架的默认行为)或组装对象来支持应用专用的行为。
应用框架强调的是软件的设计重用性和系统的可扩充性,以缩短大型应用软件系统的开发周期,提高开发质量。与传统的基于类库的面向对象重用技术比较,应用框架更注重于面向专业领域的软件重用。应用框架具有领域相关性,构件根据框架进行复合而生成可运行的系统。框架的粒度越大,其中包含的领域知识就更加完整。
1.2 框架、构件与设计模式框架(Framework)、构件(Component)和设计模式(Design pattern)是一个成熟的系统平台中三个重要的部分,同时又是三个很容易混淆的概念。框架往往是为实现一个或多个设计模式而设计的可重用可扩展的设计,是软件系统开发的半成品,而构件是框架当中的可重用的工具包、类库或者API。
构件通常是代码重用,而设计模式是设计重用,框架则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。在软件生产中有三种级别的重用:内部重用,即在同一应用中能公共使用的抽象块;代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用;应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得最高级别的重用性。
框架与设计模式虽然相似,但却有着根本的不同。设计模式是对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比框架更抽象;框架可以用代码表示,也能直接执行或复用,而对模式而言只有实例才能用代码表示;设计模式是比框架更小的元素,一个框架中往往含有一个或多个设计模式,框架总是针对某一特定应用领域,但同一模式却可适用于各种应用。可以说,框架是软件,而设计模式是软件的知识。
1.3 应用系统开发框架对软件开发的意义框架的最大好处就是重用。面向对象系统获得的最大的复用方式就是框架,一个大的应用系统往往可能由多层互相协作的框架组成。
由于框架能重用代码,因此从一已有构件库中建立应用变得非常容易,因为构件都采用框架统一定义的接口,从而使构件间的通信简单。
框架能重用设计。它提供可重用的抽象算法及高层设计,并能将大系统分解成更小的构件,而且能描述构件间的内部接口。这些标准接口使在已有的构件基础上通过组装建立各种各样的系统成为可能。只要符合接口定义,新的构件就能插入框架中,构件设计者就能重用构架的设计。
框架还能重用分析。所有的人员若按照框架的思想来分析事务,那么就能将它划分为同样的构件,采用相似的解决方法,从而使采用同一框架的分析人员之间能进行沟通。
目前的主流的系统开发框架大都提供了对数据持久性、事务、安全性、负载均衡、应用集成等问题的现成的解决方案,因此采用框架技术进行软件开发的主要优点包括:
(1) 领域内的软件结构一致性好;
(2) 建立更加开放的系统;
(3) 重用代码大大增加,软件生产效率和质量也得到了提高;
(4) 软件设计人员要专注于对领域的了解,使需求分析更充分;
(5) 存储了经验,可以让那些经验丰富的人员去设计框架和领域构件,而不必限于低层编程;
(6) 允许采用快速原型技术;
(7) 有利于在一个项目内多人协同工作;
(8) 大粒度的重用使得平均开发费用降低,开发速度加快,开发人员减少,维护费用降低,而参数化框架使得适应性、灵活性增强。
第二章 MVC设计模式及Struts技术
MVC(Model-View-Controller,模型-视图-控制器)设计模式是一种基于请求-响应(Request-Response)模式的应用框架。Struts是Apache Software Foundation针对MVC设计模式开发的运行于Server端开源项目。Struts基于Java Servlet/JavaServer Pages技术,试图提供一种能够分离表现层,并且允许表现层独立于传输层和数据持久层的开源框架。自Struts发布之日起,它就受到开源社区的欢迎和广泛支持,也日益成为开源社区的一个备受瞩目的项目。
2.1 MVC设计模式MVC结构的框架的组成部分包括以下的内容:
l 模型(Model)
模型包含了应用程序的核心,它封装了应用程序的数据结构和事务逻辑,集中体现了应用程序的状态。有时候仅包含状态信息,因为它并不了解视图或控制器的信息。JavaBean很适合扮演这个角色,因为其能够处理绝大部分事务逻辑和数据结构,还能与数据库或文件系统进行交互,承担维护应用程序数据的责任。
l 视图(View)
视图实现模块的外观,它是应用程序的外在表现。它可以访问模型的数据,却不了解模型的情况,同时它也不了解控制器的情况。当模型发生改变时,视图会得到通知,它可以访问模型的数据,但不能改变这些数据。Web界面的开发人员不需要了解或关心数据库发生什么事情,或者事务逻辑进行了什么操作,他只需要掌握HTML的知识,而不需要深入了解Java。JSP页面适合完成这个功能,因为它只包含很少的非HTML代码。
l 控制器(Controller)
控制器控制整个框架中各个组件的协调工作,对用户的输入做出反应,并且将模型和视图联系在一起,它创建并设置模块。Servlet能够接受客户端的HTTP请求,并且根据需要创建所需的JavaBeans,然后将模块产生的变化通知给视图。
Model、View、Controller这三类组件各自的责任以及它们之间的关系如图1所示。
实现MVC设计模式的系统通常会包括业务逻辑层、数据逻辑层。
业务逻辑层(Business Logic):这是FrameWork所要解决问题的关键;对框架本身来说,这里仅仅只是概念和几个提供服务的基础组件,真正的实现与客户的业务逻辑接轨,还需要开发人员在框架上再次扩展;
数据逻辑层(Data Logic):绝大部分应用系统都需要涉及到数据交互,这一层主要包括了数据逻辑和数据访问接口。在MVC结构的框架中,Model组件用于描述应用程序中的数据以及操作该数据的方法,与用户界面无关;View组件负责将数据展现给用户;Controller组件将用户操作翻译为对Model组件的操作;接到Controller传来的操作之后,Model再更新View,以及反映出数据的变化。
在MVC框架下的Web应用系统中,由于HTTP本身缺乏状态信息,客户端必须对服务器进行再查询才能发现由输入所造成的改变,在这种情况下,控制器不能将应用程序的改变通知视图。一般情况下,客户端不得不再次查询视图才能看到更新后的情况,基于这样的改进后的框架称为MVC的模型2体系。
2.2 Struts结构和处理流程Struts利用Jsp页面、自定义的标签库、Java Servlet和Action等类来实现服务器端建模,并为MVC模式设计提供相应的组件。
2.2.1 Controller
控制器的作用是从客户端接受请求,并且选择执行相应的业务逻辑,然后把响应结果送回到客户端。在Struts中Controller功能由图中ActionServlet和ActionMapping对象构成:核心是一个Servlet类型的对象ActionServlet,它用来接受客户端的请求。ActionServlet包括一组基于配置的ActionMapping对象,每个ActionMapping对象实现了一个请求到一个具体的Model部分中Action处理器对象之间的映射。
2.2.2 Model
MVC系统中的Model部分从概念上可以分为两类――系统的内部状态和改变系统状态的动作。Struts为Model部分提供了Action和ActionForm对象:所有的Action处理器对象都是开发者从Struts的Action类派生的子类。Action处理器对象封装了具体的处理逻辑,调用业务逻辑模块,并且把响应提交到合适的View组件以产生响应。Struts提供的ActionForm组件对象,它可以通过定义属性描述客户端表单数据。开发者可以从它派生子类对象,利用它和Struts提供的自定义标记库结合可以实现对客户端的表单数据的良好封装和支持,Action处理器对象可以直接对它进行读写,而不再需要和request、response对象进行数据交互。通过ActionForm组件对象实现了对View和Model之间交互的支持。
2.2.3 View
Struts应用中的View部分是通过JSP技术实现的。Struts提供了自定义的标签库可以使用,通过这些自定义标签可以非常好地和系统的Model部分交互,通过使用这些自定义标签创建的JSP表单,可以实现和Model部分中的ActionForm的映射,完成对用户数据的封装,同时这些自定义标签还提供了像模板定制等多种显示功能。
Struts框架的处理流程清楚的体现了MVC系统的特点,简单的Struts组件结构如左图3所示。Struts Controller ActionServlet处理客户请求,利用配置的ActionMapping对象把请求映射到Action处理器对象进行处理。Action处理对象访问ActionForm中的数据,处理和响应客户请求,它还调用后台的Bean组件,这些组件封装了具体的业务逻辑。Action处理器对象根据处理结果通知Controller,Controller进行下一步的处理。
2.3 利用Struts框架进行MVC开发的流程在利用Struts框架进行MVC开发的时候,我们采用如下开发流程:
(1) 收集和定义应用需求。
(2) 基于数据采集和显示的原则定义和开发"屏幕显示"需求。
(3) 为每一个"屏幕显示"定义访问路径。
(4) 定义ActionMappings建立到应用业务逻辑之间的联系。
(5) 开发满足"屏幕显示"需求的所有支持对象。
(6) 基于每一个"屏幕显示"需求提供的数据属性来创建对应的ActionForm对象。
(7) 开发被ActionMapping调用的Action对象。
(8) 开发应用业务逻辑对象 (Bean,EJB,等等)。
(9) 对应ActionMapping设计的流程创建JSP页面。
(10) 建立合适的配置文件struts-config.xml,web.xml。
(11) 开发/测试/部署。