开源技术Struts、Spring、Hibernate

更新时间:2024-04-26 21:18:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

分类号: 单位代码:11407 密 级: 学 号:20055306

北 方 民 族 大 学

硕士学位论文

开源技术Struts、Spring、Hibernate

在MIS开发中的应用研究

An Application Research on Open Source Technologies

Struts、Spring、Hibernate in MIS Development

学 位 申 请 人: 李 鉴 指

师: 冒东奎 教授

申请学位门类级别: 工学硕士 专研所

业究在

名方学

称: 计算机应用技术 向: 信息系统工程 院: 计算机科学与工程学院

论 文 完 成 日 期: 2008年5月

-1-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

独 创 性 声 明

本人声明所呈交的论文是我个人在导师指导下进行的研究工作及取得的研究成果。尽我所知,除了文中特别加以标注和致谢的地方外,论文中不包含其他人已经发表或撰写过的研究成果,也不包含为获得西北第二民族学院或其它教育机构的学位或证书而使用过的材料。与我一同工作的同志对本研究所做的任何贡献均已在论文中作了明确的说明并表示了谢意。

研究生签名: 时间: 2008年 5 月 20 日

关于论文使用授权的说明

本人完全了解西北第二民族学院有关保留、使用学位论文的规定,即:学校有权保留送交论文的复印件和磁盘,允许论文被查阅和借阅,可以采用影印、缩印或扫描等复制手段保存、汇编学位论文。同意西北第二民族学院可以用不同方式在不同媒体上发表、传播学位论文的全部或部分内容。

研究生签名: 时间:2008年 5 月 20 日

导师签名:

-1-

时间:2008年 5 月 20 日

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

摘 要

随着 Internet技术的飞速发展,基于B/S结构的服务器端应用程序得到了广泛的应用,实现Web应用的众多技术及其框架也层出不穷。传统的EJB解决方案由于其复杂性无法解决其适用范围外的问题。在开源领域,基于框架开发的技术非常活跃,尤其以Struts,Spring和Hibernate为代表。Struts是一种实现了MVC模式的Web应用框架,它全面减轻了构建多层Web应用的负担。Spring是为解决企业开发应用逻辑的复杂性而创立的一种框架。Hibernate通过建立对象关系映射,解决了以前数据库开发复杂和繁琐等问题。由于这些框架在企业开发中发挥的优势都集中在各自的范围之内,所以它们为企业开发带来了便利,同时也存在不足。那么如何整合这三种独立的框架,发挥它们各自的优势,克服J2EE的复杂性,给软件开发者提出了挑战。

本文针对上述问题,对Struts,Spring,Hibernate框架进行研究,具体分析各种框架在Web应用的不同层次上所发挥的作用。提出整合三种框架的思路,并设计出一个适合企业Web应用开发的符合JavaEE规范的整合框架。该框架基于Struts 的 MVC 设计模式,利用Struts的Controler实现整体流程控制,将应用中的业务逻辑交给Spring管理,相关类用Spring的beans配置完成,并由Spring管理下层的数据访问对象,由Hibernate负责数据的持久化。并对Spring,Hibernate和Struts整合后框架耦合性进行深入的分析研究。最后,以作者所开发的一个网站通用后台信息管理系统做为验证。开发结果表明,该应用系统具有与平台无关性,可维护性、可扩展性、可移植性,同时能够使组件的可复用性得到提高。 关键词:Spring,Struts,Hibernate,整合,MVC

-2-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

Abstract

With rapid development of the internet technology, application programs on the server side, which is based B/S structure, are used widely. A lot of technologies and their frameworks for Web Applications are emerging one by one. EJB as the traditional solution cannot resolve many problem for its complexity.In open source field ,technology base on development frameworks are flourish, especially Struts,Spring and Hibernate. struts is a Web application framework that has realized MVC mode. It can lighten the burden in constructing a multilayer Web application. Spring was created to solve the complicacy of application logic of enterprise development .Hibernate improve on the

complex database development by using Object Relational Mapping .All this frameworks take their advantage on their own field in enterprise development ,therefore they bring both convenience and insufficiency. So how to integrate the three independent frameworks,put their own advantages to the best use,overcome J2EE complexity,raise a challenge to software developers.

In order to resolve above these problem,a research work on Struts, Spring and Hibernate

frameworks has been done. The roles of the 3 frameworks in different tiers of a Web application are analyzed in detail. A thought for integration of the 3 frameworks is introduced. A new framework,that is suitable for development of enterprise Web application and conformable to J2EE specification, is designed. The framework is based on MVC design mode of Struts. Overall process control is

implemented by using Struts Controller. The business logic of the application is managed by Spring. Relative classes … through configuration of Spring Beans. Data Access Objects in underlying tiers are managed by Spring. The responsibility for Data persistence is taken by Hibernate. A intensive analysis and study on coupling performances of the integrated framework from Spring,Hibernate and Struts has been done finally,A general-purpose backend MIS for websites has been developed, that is used as a verification. The development result indicated that the application system has the attribute of platform independency, maintainability, extendibility, portability and meanwhile the module's reusability has been enhanced.

Keyword:Spring,Struts,Hibernate,integration,MVC

-3-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

目 录

开源技术STRUTS、SPRING、HIBERNATE ................................................................... 1 第1章 绪 论 ........................................................................................................................... 6 1.1 课题背景 ..................................................................................................................... 6 1.2 本文的主要工作及意义 ............................................................................................. 6

1.2.1 课题研究的内容 ........................................................................................... 6 1.2.2 课题的意义 ................................................................................................... 7

1.3 论文的组织结构 ......................................................................................................... 7 第2章 开源技术应用现状 ................................................................................................... 14 2.1 基本概念 ..................................................................................................................... 8

2.1.1 设计模式 ....................................................................................................... 8 2.1.2 软件系统架构 ............................................................................................... 8 2.1.3 框架 ............................................................................................................... 9 2.1.4 三者的关系 ................................................................................................... 9

2.2 传统的J2EE解决方案及其缺陷 ............................................................................... 8 2.3 J2EE的开源技术 ...................................................................................................... 83 第3章 WEB解决方案分析研究 ......................................................................................... 15 3.1 STRUTS框架 .............................................................................................................. 14

3.1.1 MVC设计模式 ............................................................................................ 14 3.1.2 Struts实现MVC机制 ................................................................................ 16

3.2 轻量级的SPRING框架 ............................................................................................. 18

3.2.1 依赖注入(DI)和控制反转(IoC)....................................................... 21 3.2.2 面向切面编程(AOP) ............................................................................. 23 3.2.3Spring解决方案选择 ................................................................................... 24

3.3 持久层框架HIBERNATE .......................................................................................... 26

3.3.1Java反射机制 ............................................................................................... 26 3.3.2 对象/关系映射机制 ................................................................................... 26 3.3.3Hibernate体系结构 ..................................................................................... 27 第4章 项目实例分析与设计 ............................................................................................... 30 4.1 项目需求分析 ........................................................................................................... 30 4.2 总体架构设计 ........................................................................................................... 31

4.2.1 业务逻辑层与数据持久层的通讯及其解耦方式 ..................................... 32 4.2.2 表示层与业务逻辑层的衔接 ..................................................................... 35 4.2.3 整合后的框架 ............................................................................................. 36

4.3 框架处理流程原理设计 ........................................................................................... 36 4.4 系统模块设计 ........................................................................................................... 37

-4-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

4.4.1 持久层设计 ................................................................................................. 38 4.4.2 业务层设计 ................................................................................................. 41 4.4.3 表现层设计 ................................................................................................. 43

4.5 数据库设计 ............................................................................... 错误!未定义书签。

4.5.1 数据库表逻辑关系设计及物理模型设计 ................................................. 47 4.5.2 表结构设计 ................................................................................................. 48 第5章 架构应用的实现 ....................................................................................................... 51 5.1 5.2 5.3 5.4 5.5 5.6

开发环境 ................................................................................................................... 51 持久层的实现 ........................................................................... 错误!未定义书签。 业务逻辑层的实现 ................................................................... 错误!未定义书签。 控制层的实现 ........................................................................... 错误!未定义书签。 视图层的实现 ........................................................................... 错误!未定义书签。 目录和包结构 ........................................................................... 错误!未定义书签。

第6章 结束语 ....................................................................................................................... 61

-5-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

第1章 绪论

1.1课题背景

Web开发作为一个行业从诞生到现在,已经发展到了一个非常成熟的阶段,而且规模仍在不断扩大,复杂度更加日渐升级。设计者和开发人员如何将新的设计建立在以往的工作基础上,如何复用所以往的成功案例,将大大的提高效率[1]。因此,人们越来越意识到软件技术复用的重要性,而且将注意力转移到对设计的提炼,随着对JavaEE进一步研究,在研究结果中发现,软件开发过程中特定领域软件存在共性部分,它是由一组紧密关联的classes(类)组成,强调类彼此的配合来完成某种可以重复运用的设计概念。这些类之间以特定的方式合作,彼此不可或缺,研究人员将它提取出来,框架由此诞生[2]。在开源社区中,框架更是百花齐放。

框架与建筑中的框架类似,是开发的最根本依据,一旦框架确定,项目实施路线就不容更改。同时它比建筑学框架更便于使用,因为它已经固化了应用编程接口,提供了很多对象供开发人员直接调用。 由于软件架构建立是一个复杂的过程,软件设计人员不可能对每个不同项目做出不同的架构设计。所以构建一个易于维护,扩展性强,可移植,松耦合的Web解决方案[3]成为一个值得研究的课题。

本项目是导师冒东奎教授所承担的国家民委2004年委属高等院校重点科研项目“面向西部企业信息系统整合的Web服务技术研究”(院内项目编号:M200409)的一个子项目。

1.2本文的主要工作及意义

1.2.1课题研究的内容

( 1 ) 分析传统的J2EE技术,从以前流行的EJB的使用弊端推导出使用轻量级J2EE框架的优势。 (2)总结软件开发设计过程中的常用技术和方法,象什么是设计模式,什么是架构,什么是框架,以及它们之间联系和区别,以及它们在系统开发过程中的作用。

(3)对开源软件Struts,Spring和Hibernate的核心技术的研究,并认真分析Struts MVC,Spring的IoC和AOP,中间层数据访问,以及Hibernater持久化数据原理及其方法。最后提出了一种由表示层、控制层,业务逻辑层和持久层四层整合框架的Web开发解决方案 ,即:采用Struts MVC进行系统流程设计,Spring依赖注入模式来解决业务逻辑层中代码之间依赖性过高的问题。用Hibernate解决传统JDBC操作数据库所带来的弊端。同时对控制反转模式的几种实现类型进行了分析,从而为不同的程序实现提供了更多的解决方案。

作为这些研究成果的应用,本文利用Eclipse开发工具在Tomcat容器中实现了一个整合框架系统的开发。这个系统中利用控制反转模式的思想通过设计接口和配置文件来进行动态的依赖注入,从而有效的对组件依赖性进行解耦。同时在程序中使用面向方面编程方法对模块中的横切关注点进行分解、封装、重新组合,从而提高代码的重用性和扩展性。

-6-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

1.2.2 课题的意义

(1)本文通过研究Struts,Spring,Hibernate这三种轻量级框架的核心技术,充分挖掘出它们的优势,克服每个框架自身的局限性,最后将它们的优势进行整合,得到一个改进后的整合的轻量级框架。

(2)论文工作也在集成架构的基础上,开发一个实际项目,具体探讨如何将Struts的操作委托给Spring;如何实现Struts和Spring之间的解耦;如何用依赖注入简化数据库的操作;如何实现AOP等。

(3)框架最重要的目标是提高西部企业MIS系统开发的竞争能力,包括降低成本、提高质量、改善客户满意程度,控制进度等。

1.3论文的组织结构

论文结构安排如下:

第 1 章绪论,介绍论文的研究背景、研究意义、技术应用现状、作者的工作及创新点。

第 2 章传统J2EE解决方案分析,首先阐述设计模式,框架,架构之间的联系与区别以及分别在软件分析与设计中所起的作用,然后分析了传统Web项目解决方案的技术思路及其优缺点,引出开源技术框架。整合框架所需的Struts,Spring,Hibetnate框架的核心技术。为下一章多层框架的整合提供了理论。

第 3 Web解决方案分析,主要研究整合框架所需的Struts,Spring,Hibetnate框架的核心技术及其各框架的优势所在。为下一章多层框架的整合提供了理论。

第 4 章Web应用系统分析与设计,形成新的框架结构并验证其可用性。本章重点探讨Spring与Struts和Hibernate整合的实现方式,给出相应的技术细节。并以通用后台管理系统为例,对系统进行详细的分析和设计。

第 5 章SSH整合架构应用的实现,按照自己的设计原理,对通用后台做技术实现,以论证自己设计的可行性。

第 6 章结束语,概括总结作者在本文所做的工作及心得体会, 并对今后需进一步探索的工作提出展望。

-7-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

第2章 传统J2EE解决方案分析

2.1基本概念

本整合框架始终是基于一种设计模式的,而且设计模式与架构,框架存在着紧密联系,同时也存在着细微区别(特别是重用,以及所能够解决问题的层次,目标)。只有真正清晰这些概念,才能够深入理解这种基于Struts MVC,Spring,Hibernate整合框架的内涵。也才能够给本论文在软件开发中给出一个正确定位层次(利用现有的框架技术重新整合设计)(参见后文的图2.1和图2.2)。

2.1.1设计模式

Christopher Alexander说过:“每一个模式描叙了一个我们周围重复发生的问题,以及该问题的解决方案的核心。这样,你就能够一次又一次的使用该方案而不必做重复劳动[7]”。

一般而言,一个模式有四个基本要素:

(1) 模式名称(Patern Name),一个助记名,它用一两个词来描述模式的问题、解决方案和效果。基于一个模式词汇表,开发者之间就可以讨论模式并在编写文档时使用它们。模式名可以帮助人们思考,便于我们与其他人交流设计思想及设计结果。找到恰当的模式名也是设计模式编目工作的难点之一。

(2) 问题 (Problem),描述了应该在何时使用模式。它解释了设计问题和问题存在的前因后果,它可能描述了特定的设计问题,如怎样用对象表示算法等。也可能描述了导致不灵活设计的类或对象结构。

(3) 解决方案 (Solution),描述了设计的组成部分,它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象组合)来解决问题。

(4) 效果 (Consequence),描述了模式应用的效果及使用模式应权衡的问题。软件效果大多关注对时间和空间的衡量,它们也表述了语言和实现问题。因为复用是面向对象设计的要素之一,所以模式效果包括系统的灵活性、扩充性和可移植性的影响。

设计模式是对于重复出现的问题的一种可以重用的解决方法。从编程的角度来说,一个模式提供了一系列特定的交互,这种交互可以应用于某些通用的目标。以解决某个众所周知的问题。好的设计模式会在保证有效求解问题的基础上,突破它们能解决问题的规模。可以知道,设计模式以重用为目标,解决问题是属于对象设计级别的。

2.1.2 软件系统架构

软件架构(Software architecture)是一系列相关的抽象模式,用于指导大型软件系统各个方面的设计。 软件架构是一个系统的草图。软件架构描述的对象是直接构成系统的抽象组件,同时设计各个抽象组件之间的连接方式和相对细致地描述组件之间的通讯。在实现阶段,这些抽象组件被细化为实际的组件,比如具体某个类或者对象。在面向对象领域中,组件之间的连接通常用接口_(计算机科学)来实现。

软件体系结构是构建计算机软件实践的基础。与建筑师设定建筑项目的设计原则和目标,作为绘图员画图的基础一样,一个软件架构师或者系统架构师陈述软件构架以作为满足不同客户需求的实际系统

-8-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

设计方案的基础。

软件构架是一个容易理解的概念,多数工程师(尤其是经验不多的工程师)会从直觉上来认识它,但要给出精确的定义很困难。特别是,很难明确地区分设计和构架:构架属于设计的一方面,它集中于某些具体的特征。

在“软件构架简介”中,David Garlan 和 Mary Shaw 认为软件构架是有关如下问题的设计层次:“在计算的算法和数据结构之外,设计并确定系统整体结构成为了新的问题。结构问题包括总体组织结构和全局控制结构;通信、同步和数据访问的协议;设计元素的功能分配;物理分布;设计元素的组成;定

[8]”但构架不仅是结构;标与性能;备选设计的选择。IEEE Working Group on Architecture 把其定义为“系

统在其环境中的最高层概念”。构架还包括“符合”系统完整性、经济约束条件、审美需求和样式。它并不仅注重对内部的考虑,而且还在系统的用户环境和开发环境中对系统进行整体考虑,即同时注重对外部的考虑[9]。

在 Rational Unified Process 中,软件系统的构架(在某一给定点)是指系统重要构件的组织或结构,这些重要构件通过接口与由更小部件与接口所组成的构件进行交互。

以上关于系统架构可以总结为,软件系统的架构(Architecture)有两个要素: (1)它是一个软件系统从整体到部分的最高层次的划分。

一个系统通常是由元件组成的,而这些元件如何形成、相互之间如何发生作用,则是关于这个系统本身结构的重要信息。详细地说,就是要包括架构元件(Architecture Component)、联结器(Connector)、任务流(Task-flow)。所谓架构元素,也就是组成系统的核心\砖瓦\,而联结器则描述这些元件之间通讯的路径、通讯的机制、通讯的预期结果,任务流则描述系统如何使用这些元件和联结器完成某一项需求。 (2)建造一个系统所作出的最高层次的、以后难以更改的,商业的和技术的决定。

在建造一个系统之前会有很多的重要决定需要事先作出,而一旦系统开始进行详细设计甚至建造,这些决定就很难更改甚至无法更改。显然,这样的决定必定是有关系统设计成败的最重要决定,必须经过非常慎重的研究和考察。

2.1.3 框架

框架是项目软件开发过程中提取特定领域软件的共性部分,它是由一组紧密关联的classes(类)组成,强调类彼此的配合来完成某种可以重复运用的设计概念。这些类之间以特定的方式合作,彼此不可或缺。框架的作用在于:由于提取了特定领域软件的共性部分,因此在此领域内新项目的开发过程中代码不需要从头编写,只需要在框架的基础上进行一些开发和调整便可满足要求;对于开发过程而言,这样做会提高软件的质量,降低成本,缩短开发时间,使开发越做越轻松,效益越做越好,形成一种良性循环。框架是现成可用的应用系统,它只是一个半成品,需要后来的开发人员进行依托这个半成品来对具体功能实现。所以,框架更侧重于设计,开发过程,或者可以说,框架通过一个所依托平台(半成品)提供的服务而起作用。

2.1.4三者的关系

框架由一组紧密关联的classes(类)组成,同时是一种特殊的半成品软件,它并不能提供完整无缺的解决方案,而是为你构建解决方案提供良好的基础。框架是半成品。典型地,框架是系统或子系统的半成

-9-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

品;框架中的服务可以被最终应用直接调用,而框架中的扩展点是供应用开发人员定制的“可变化点”。而这些紧密相关联的类或者是对现实世界某个实体的抽象,或者设计模式所抽象出的类群(如图2.1 所示)。

软件架构不是软件,而是关于软件如何设计的重要决策。软件架构决策涉及到如何将软件系统分解成不同的部分、各部分之间的静态结构关系和动态交互关系等。经过完整的开发过程之后,这些架构决策将体现在最终开发出的软件系统中;当然,引入软件框架之后,整个开发过程变成了“分两步走”,而架构决策往往会体现在框架之中(参见图2.2)。或许,人们常把架构和框架混为一谈的原因就在于此。

对象1对象2接口对象3对象n

图2.1类及类群与关系组合成框架

图2.2 框架和架构的关系

从它们三者的关系可以看出,设计模式是对于重复出现的问题的一种可以重用的解决方法,而一个模式提供了一系列特定的类交互。框架由一组紧密关联的classes(类)组成。而架构决策往往会体现在框架之中。清理概念上的误区后,我们接下来具体分析整合框架所需的三种开源技术,即Struts, Spring和Hibernate。

2.2传统的J2EE解决方案及其缺陷

传统的解决方案给了我们这样的映像:J2EE是一个非常好的企业应用设计规范,它采用了大量优秀

-10-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

的设计思想。J2EE设计的目标,就是让企业应用开发人员能够在一个规范的平台之上,不用考虑具体的技术问题,专注于业务逻辑实现,就可以开发出性能高、稳定性好、可管理的较高水平的系统[4]。在传统的J2EE架构体系中,其业务层主要是靠组件EJB(Enterprise JavaBean)来实现的,而且EJB一直被认为是JavaEE的核心组件,但它的诞生和为之服务的应用领域是大量数据,大量并发访问,要求极高的稳定性,安全性,以及应用分布式数据库,这样它就进入了重量级的范畴,EJB是为了解决复杂问题而设计的,它是为了复杂而复杂。不幸的很多企业级项目根本没有这样的要求,所以不利于大量实际Web应用。典型的企业级J2EE架构主要由JSP+Servlet+EJB组成,在大型分布式系统往往采用这种方式,但是在中小型企业Web应用中,采用EJB为中心的J2EE框架,主要有以下几个问题[5]:

(1) J2EE应用程序容易包含过量的“衔接”代码。.

从对许多代码的审校来看,我们总是发现很多代码毫无用处:JNDI查询代码、传输对象、获取和释放JDBC资源的try/catch代码块……。编写和维护这样的衔接代码无疑会占用大量的项目资源(包括人力资源)。而这些资源应该集中应用程序的业务领域。

(2) 许多J2EE应用程序不恰当的使用了分布式对象模型。

这是导致过度代码和代码重复的主要原因之一。在许多情况下,这也是概念性错误;内部分布式程序比供出一地的应用程序更加复杂,而且通常性能也很差。当然,如果业务需求需要使用分布式结构,那么需要实现一个分布式结构,并且接受由此导致的折衷。但是,没有充分理由,不应该这样做。

(3) EJB组件模型过于复杂。

构思EJB是作为J2EE应用程序中实现业务逻辑时减低复杂性的一种方法;不过这一目标从来没有取得成功。

(4)过度使用EJB

EJB本来是为了内部分布式的事务性程序设计的。但是多有的重要应用程序都是事务性的,而发布性不应该成为基本组件模型的组成部分。

(5)事实上,很多“J2EE设计模式”并非设计模式,而是受技术限制的解决方案

分布式的过度使用,以及诸如EJB之类的复杂API的使用,已经产生了许多不可靠的设计模式。因此我们要批判性的进行分析,并且寻找更加简单有效的方法。

(6)J2EE应用程序难以进行单元测试

J2EE API,尤其是EJB组件模型,在敏捷运动开始之前就已经定义好了,因此,它们的设计并没有考虑单元测试的简易性。通过API和隐式规范,在应用程序服务器之外对基于EJB和许多其它J2EE API的应用程序进行测试,其困难程度超乎想象。然而,在应用程序服务器外部进行单元测试是非常重要的,它可以获得测试的高覆盖率,也可以重现许多故障情形,例如数据库连接的丢失。同样,在开发和维护中,这也能够保证测试的快速进行,使得等待重新部署的时间最小化。

(7)某些J2EE技术简直就是失败

这里,最典型的例子就是实体Bean,它已经证明生产力损失惨重,而且面向对象的使用受到极大的约束。

对待这些问题的传统方法就是等待工具的支持来弥补J2EE规范,这就意味着开发者无需纠缠于上述的复杂性。不过这已经非常失败了。基于代码生成方法的工具并没有带来预期的好处,反而显示出其自身的一些问题。在这种方法中,可能要生成所有那些冗长的JNDI查询,传输对象和try/catch快。

一般说来,经验表明框架(framework)比启用基于工具(tool-enabled)的代码生成要好。一个好

-11-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

多框架通常在运行时通常比生成的代码要灵活得多;在框架中,可能有配置一个小代码块的行为,而不是去改变许多生成的类。在很多情况下,要多次采用代码生成技术生成目标代码,这使得生产率大大减低。构思精巧的框架还能够提供始终一致的抽象,而代码生成无法成功地在整个项目生命期中隐藏签证的复杂性。

基于框架的方法认识到这样一个事实,就是在J2EE拼图中丢失了一块,这一块就是:应用程序开发人员的观点。许多J2EE所提供的东西,例如JNDI,对应程序员的日常活动来说简直太底层了。J2EE规范和API非常不错,但并没有给开发人员提供编程模型;否则,J2EE规范和API会更成功!好的框架补上这一块,并且给应用程序开发人员一个简单的抽象,而且没有牺牲这个平台的核心能力。

认识到框架对于成功的J2EE项目的重要性,许多开发人员和公司尝试编写它们自己的框架,获得了不同程度的成功。在少数情况下,框架达到了它们预期的目的,大幅度降低了费用,提高了生产率。但是,大多数情形中,框架本身的开发和维护开销成了问题,而且框架的设计缺陷也显示出来。由于其核心问题是相通的,使用单个的,广泛使用的框架比一个人闭门造车要好得多。无论一个组织有多么大,它所获得的经验都无法与该产品在很多公司中被广泛使用所获得的经验相提并论。如果框架是公开源码的,其额外的优势就是可能有人贡献新的,它们采用的特性和增强功能。因此,在某些特殊领域,诸如Struts,spring和Hibernate之类的通用框架日益取代了内部框架。

2.3 J2EE的开源技术

目前, J2EE应用确实很流行,从银行,证券系统,到企业信息化平台,甚至一些小公司,都争相使用J2EE应用。几年前, J2EE应用是很“贵族”的产品,那时候使用EJB作为J2EE的核心,开发成本高,部署成本也高,开发者的学习曲线也陡峭。今天,轻量级J2EE应用的流行,让J2EE应用开始进入寻常百姓家。轻量级J2EE应用是对经典J2EE应用的简化,在保留经典J2EE应用的架构.良好的可扩展性.可维护性的基础上,简化了J2EE应用的开发,降低了J2EE应用的部署成本.轻量级J2EE应用让J2EE平台以更快的速度占领电子商务,电子政务等各种信息化平台市场。笔者从不否认对经典J2EE应用架构的喜爱,那种严谨的架构,全方位考虑的设计.优秀的分布式架构,无疑是一种编程的艺术.但它们太豪华了,以致于限制了它的市场占有率。可以这样说:经典J2EE应用是面向开发者的,而轻量级J2EE应用则面向用户.优秀的开发者会感慨并喜欢经典J2EE应用的设计,但市场则喜欢轻量级J2EE应用。轻量级J2EE应用模仿了经典J2EE应用的架构,保留了经典J2EE应用的各种优点,降低了学习难度和开发,部署成本,是一种更实际的信息化平台架构[6]。

J2EE虽然是企业应用开发的成熟规范,但由于存在上述问题,实施难度实在太大。为此,三种开源技术Struts,Spring,Hibernate分别从不同层面对J2EE进行了实现和改进。图2.3画出的是J2EE规范的客户端,服务器端和后台数据库,上面标明了上述三种开源技术对其所作的实现和改进。其中Struts是J2EE在Web层的具体实现,它基于MVC模式,并推出了一系列Action类和一套自定义标签库,将Web应用的业务逻辑和显示逻辑分离,简化了Web应用开发的难度;Spring 是一个全新的轻量级的J2EE应用框架,它的创新技术AOP(Aspect-Oriented Programming,面向切面的编程)克服了Java对象之间缺少横向联系的问题。另一项创新技术IoC(Inversion of Control ,控制反转)改变了对象从容器中查找依赖的传统模式,让容器在应用对象初始化时不等被请求就将依赖传递给对象,从而促进了应用对象之间的松耦合。IoC经纳入Java EE 5规范;Hibernate相当于在业务逻辑层和数据层之间增加了一个持久化层,通过对象关系/映射技术实现了Java应用对象到关系数据库表的自动持久化,使应用

-12-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

程序能自动完各种数据库访问操作,从而提高了数据访问效率。这三种开源技术各有所长,综合应用可构造出一个轻量级的整合框架,能显著降低企业MIS开发的难度。

图2.3 Struts,Spring,Hibernate对J2EE的实现和改进

本章对软件研发过程中常用的模式、架构和框架进行了分析,对其中涉及到的基本概念,适用范围及其作用进行了介绍,同时对传统J2EE解决方案进行了研究及并分析了其不足之处,提出了利用开源框架Struts,Spring和Hibernate进行集成开发的设想。

-13-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

第3章 Web解决方案分析研究

3.1 Struts框架

Struts是Apache软件基金下的Jakarta项目的一部分。Struts框架的主要架构设计和开发者是Craig R.McClanahan。经过长达五年的发展,Struts已经逐渐成长为一个稳定、成熟的框架,并且占有了MVC框架中最大的市场份额。但是Struts某些技术特性上已经落后于新兴的MVC框架。面对Spring MVC、Webwork2 这些设计更精密,扩展性更强的框架,Struts受到了前所未有的挑战。但站在产品开发的角度而言,Struts仍然是最稳妥的选择。

Struts是基于MVC设计模式的Web应用框架,由一组相互协作的类(组件)、Serlvet以及JSP标签库组成。Struts有它自己的控制器(Controller),同时整合了其他的一些技术去实现模型层(Model)和视图层(View)。在模型层, Struts可以很容易的与数据访问技术相结合。在视图层,Struts能够与 JSP, XSL等表示层组件结合。

3.1.1 MVC设计模式

MVC是Model-View-Controllerd 简称,即模型-视图-控制器。MVC是XeroxPARC在20世纪80年代为编程语言Smalltalk-80发明的一种软件设计模式,至今被广泛应用,最近几年被推荐为Sun公司J2EE平台的设计模式[10]。由于整合框架的设计和流程是严格按照MVC设计思想,所以首先从MVC入手,然后分析Struts实现MVC机制及工作流程。

MVC模式把应用程序分成3个核心模块:模型(Model)、视图(View)和控制器(Controller),它们分别担当不同的任务。图3.1表示了这几个模块各自的功能及它们的相互关系。

选择视图(控制器)接收用户请求调用模型相应用户请求选择视图显示响应结果业务逻辑(视图)显示模型的业务数据接收用户请求把用户输入数据传给控制器用户请求业务数据查询通知业务数据更新(模型)包含业务数据相应业务数据查询处理业务逻辑通知视图业务数据更新调用方法图3.1 MVC设计模式

事件

(1)视图

-14-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

视图是用户看到并与之交互的界面。视图向用户展示用户感兴趣的业务数据,并能接收用户的输入数据,但是视图并不进行任何实际的业务处理。视图可以向模型查询业务数据,但不能直接改变模型中的业务数据。视图还能接收模型发出的业务数据更新事件,从而对用户界面进行同步更新。

(2)模型

模型是应用程序的主体部分。模型表示业务数据和业务逻辑。一个模型能为多个视图提供业务数据。同一个模型可以被多个视图重用。

(3)控制器

控制器接收用户的输入并调用模型和视图去完成用户的请求。当用户在视图上选择按钮或菜单时,控制器接收请求并调用相应的模型组件去处理请求,然后调用相应的视图来显示模型返回的数据(如图2.4所示)。

视图层接口视图层实现控制器接口控制器实现模型层接口模型层实现

图3.2 MVC的三个模块可看作软件的三个层次

MVC的3个模块也可以看做软件的3个层次,最上层为视图层,中间为控制器层,下层为模型层。总地说来,层与层之间为自上而下的依赖关系,下层组件为上层组件提供服务。视图层与控制器层依赖模型层来处理业务逻辑和提供业务数据。此外,层与层之间还存在两处自下而上的调用,一处是控制器层调用视图层来显示业务数据,另一处是模型层通知客户层同步刷新界面。为了提高每个层的独立性,应该使每个层对外公开接口,封装实现细节。

(4)MVC处理过程

如图3.3所示,首先用户在视图提供的界面上发出请求,视图把请求转发给控制器,控制器调用相应的模型来处理用户请求,模型进行相应的业务逻辑处理,并返回数据。最后控制器调用相应的视图来显示模型返回的数据。

视图顶层包::主角11:发出请求2:转发请求控制器模型3:调用模块4:处理业务5:返回响应数据6:选择视图展示相应数据()

图3.3 MVC的处理过程

-15-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

(5)MVC的优点

首先,多个视图能共享一个模型。在MVC设计模式中,模型响应用户请求并返回响应数据,视图负责格式化数据并把它们呈现给用户,业务逻辑和数据表示分离,同一个模型可以被不同的视图重用,所以大大提高了模型层的程序代码的可重用性。

其次,模型是自包含的,与控制器和视图保持相对独立,因此可以方便地改变应用程序的业务数据和业务规则。如果把数据库从MySQL移植到Oracle,或者把RDBMS数据源改变成LDAP数据源,只需改变模型即可。一旦正确地实现了模型,不管业务数据来自数据库还是LDAP服务器,视图都会正确地显示它们。由于MVC的3个模块相互独立,改变其中一个不会影响其他两个,所以依据这种设计思想能构造良好的松耦合的组件。

此外,控制器提高了应用程序的灵活性和可配置性。控制器可以用来连接不同的模型和视图去完成用户的需求,控制器为构造应用程序提供了强有力的重组手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择适当的模型进行业务逻辑处理,然后选择适当的视图将处理结果显示给用户。

(6)MVC的适用范围

使用MVC需要精心的设计,由于它的内部原理比较复杂,所以需要花费一些时间去理解它。将MVC运用到应用程序中,会带来额外的工作量,增加应用的复杂性,所以MVC不适合小型应用程序。但对于开发存在大量用户界面,并且业务逻辑复杂的大型应用程序,MVC将会使软件在健壮性、代码重用和结构方面上一个新的台阶。尽管在最初构建MVC框架时会花费一定的工作量,但从长远角度看,它会大大提高后期软件开发的效率。

3.1.2 Struts实现MVC机制

Struts 实质上就是在 JSP Model2 的基础上实现的一个 MVC 框架。在 Struts 框架中,模型由实现业务逻辑的 JavaBean 或 EJB 组件构成,控制器由 ActionServlet 和Action 来实现,视图由一组 JSP 文件构成。图3.4表示Struts的MVC框架

Servlet/JSP容器Struts-config.xmlAction(控制器)ActionServlet浏览器Web服务器(视图)JSPActionAction(模型)JavaBeanEJB 图3.4 Struts 的MVC框架

(1) 视图

视图就是一组 JSP 文件。在这些 JSP 文件中没有业务逻辑,也没有模型信息,只有标签,这些

标签可以是标准的 JSP 标签或客户化标签,如 Struts 标签库中的标签。此外,通常把 Struts 框架中的 ActionForm Bean 也划分到视图模块中。ActionFormBean 也是一种 JavaBean,除了具有一些 JavaBean 的常规方法,还包含一些特殊的方法,用于验证 HTML 表单数据以及将其属性重新设

-16-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

置为默认值。Struts 框架利用ActionFrom Bean 来进行视图和控制器之间表单数据的传递(参见图3.5)。Struts 框架把用户输入的表单数据保存在 ActionFrom Bean 中,把它传递给控制器,控制器可以对ActionFrom Bean 中的数据进行修改,JSP 文件使用 Struts 标签读取修改后的ActionFrom Bean 的信息,重新设置 HTML 表单。

Action FormBean(包含用户输入数据)视图组件Action FormBean(包含修改后数据)图3.5 Action FormBean的作用

控制器组件

(2)模型

模型表示应用程序的状态和业务逻辑。对于大型应用,业务逻辑通常由 JavaBean或 EJB 组件实现。 (3)控制器

控制器由 ActionServlet 类和 Action 类来实现。ActionServlet 类是 Struts 框架中的核心组件。ActionServlet 继承了 Javax.servlet.http.HttpServlet 类,它在 MVC 模型中扮演中央控制器的角色。ActionServlet 主要负责接受 HTTP 请求信息,根据配置文件 struts-config.xml 的配置信息,把请求转发给适当的 Action对象。如果该 Action对象不存在,ActionServlet 会先创建这个 Action 对象。Action 类负责调用模型的方法,更新模型的状态,并帮助控制应用程序的流程。

对于小型简单的应用,Action 类本身也可以完成一些实际的业务逻辑。对于大型应用,Action 充当用户请求和业务逻辑处理之间的适配器(Adaptor),其功能就是将请求于业务逻辑分开,Action 根据用户请求调用相关的业务逻辑组件。业务逻辑由 Java Bean 或 EJB 来完成,Action 类侧重于控制应用程序的流程,而不是实现应用程序的逻辑。通过将业务逻辑放在单独的 Java 包或 EJB 中,可以提高应用程序的灵活性和可重用性。

当 ActionServlet 控制器收到用户请求后,把请求转发到一个 Action 实例。如果这个实例不存在,控制器会首先创建它,然后调用这个 Action 实例的 execute()方法。Action 的 execute()方法返回 ActionForward 对象,它封装了把用户请求再转发给其他 Web 组件的信息。用户定义自己的 Action 类,即 Action 基类的子类时,必须覆盖 execute()方法。在 Action 基类中返回 null。 (4)Struts 的配置文件 struts-config.xml

上面讲到的一个用户请求是通过 ActionServlet 来处理和转发的。那么,ActionServlet 如何决定把用户请求转发给哪个 Action 对象呢?这就需要一些描述用户请求路径和 Action 映射关系的配置信息了。在 Struts 中,这些配置映射信息都存储在特定的 XML 文件 struts-config.xml 中。在该配置文件中,每一个 Action 的映射信息都通过一个元素来配置。这些配置信息在系统启动的时候被读入内存,供 Struts 在运行期间使用。在内存中,每一个元素都对应一个 org.apache.struts.action.ActionMapping 类的实例。

到此,我们对MVC及Struts MVC有了深入理解,也知道MVC设计思想是Web应用的一种极好的设计。我们同样知道这样一个事实:模型层表示应用程序的状态和业务逻辑。那是不是Struts很优秀

-17-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

的解决了业务逻辑层的可移植,代码复用高,便于与后台交互等要求呢?答案是没有,它在这个方面远远没有另一种轻量级框架来的简单——Spring。

3.2轻量级的Spring框架

Spring是一个轻量的开源框架,由Rod Johnson创建并且在他的著作《J2EE设计开发编程指南》里进行了详细描述。Spring是为了解决企业应用开发的复杂性而创建的。以前很多业务逻辑是靠EJB完成,按照EJB的要求,编写会变得很复杂,Spring使用基本的JavaBean就可以解决这个问题。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring技术受益[11]。

Spring是一种多层的J2EE应用程序框架,其核心是提供一种新的机制来管理业务对象及其依赖关系。例如,可以利用控制反转(I0C)指定一个数据访问对象(Data Access Object)类依赖一个DataSource类。它也允许开发人员通过接口编程,使用XML文件来简单的定义其实现。Spring有许多类用来支持其它的框架(如Hibernate和Struts),这使得框架集成变得很容易[12]。Spring不仅解决了开发人员的实际问题,也促使它们养成良好的编程习惯,例如,接口编程减少耦合及提供简易的测试。在当今的编程领域中,特别是在Java中,一些优秀的开发人员正在实践测试驱动开发(Test Driven Development). 测试驱动开发要求你用测试类或是client类驱动其它类的设计。而不是先写好一个类,然后再设计client类,它要求事先写client。通过这种方法,你恰好可以知道你正在开发的类中需要哪些东西[14]。Spring本身提供了丰富的的测试套件,这使得你在测试类时变得轻松自如。Spring 的工作原理就是一种用JavaBean配置应用程序的方法。运用Spring可以通过一个seter来暴露一个类的任何依赖关系(如一个数据库连接database connection),并且在Spring中进行配置来解决依赖性。即使不用写数据库连接,这也可以在Spring进行配置。这种解决依赖性的方法称为控制反转。从根本上说,这是一个技术术语,用来解释使用某种容器来组织相互依赖的对象。Spring框架包含许多特性,并被很好地组织在图3.6所示的七个模块中。

图3.6 Spring框架

Core封装包是框架的最基础部分,提供IoC和依赖注入特性。这里的基础概念是BeanFactory,它提供对工厂模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。构建于Core封装包基础上的 Context封装包,提供了一种框架式的对象访问方法,有些象

-18-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

JNDI注册器。Context封装包的特性来至于Beans封装包,并添加了对国际化(I18N)的支持(例如资源绑定),事件传播,资源装载的方式和Context的透明创建。

DAO提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。并且,JDBC 封装包还提供了一种比编程性更好的声明性事务管理方法,它不仅仅是实现了特定接口,而且对所有的POJOs(Plain Old Java Objects)都适用。

ORM 封装包提供了常用的“对象/关系”映射应用编程接口(API)的集成层。 其中包括JPA、JDO、Hibernate 和 iBatis 。利用ORM封装包,可以混合使用所有Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。

Spring的面向切面编程(AOP) 封装包提供了符合 AOP 联盟规范的面向方面的编程

(Aspect-Oriented Programming)实现,让你可以定义,例如方法拦截器(Method-Interceptors)和切点(pointcuts)。从逻辑上讲,能够减弱实现相同功能代码与组件(或者功能模块)的耦合,使各个功能部件的责任清晰的被分离开。而且,利用资源级(Source Level)的元数据功能,还可以将各种行为信息合并到你的代码中,这有点象.Net的属性(Property)概念。

Spring中的Web包提供了基础的针对Web开发的集成特性,例如多个文件上传。利用Servlet Listeners进行IoC容器初始化和对Web的应用上下文(ApplicationContext)进行初始化。当与WebWork或Struts一起使用Spring时,这个包使Spring可与这些框架实现结合。

Spring中的 MVC 封装包提供了Web应用的MVC(Model-View-Controller)实现。Spring的MVC框架并不是仅仅提供一种传统的实现。在领域模型代码和Web form之间,它提供了一种清晰的分离模型。并且,在实现特定功能时还可以借助Spring框架的其他特性。

下面借助搭积木方式来解释各种情景下使用Spring的情况。图3.7介绍从简单的Applet一直到完整使用Spring的事务管理功能和Web框架企业应用的搭建方式[14]。

图3.7典型的完整的Spring Web应用

通过用Spring的声明式事务管理特性,可以实现像使用EJB提供的那种容器管理的事务一样,使Web应用可以做到完全事务性。 所有自定义的业务逻辑可以通过简单的POJO来实现,并利用Spring的IoC容器进行管理。对于其他的服务,比如发送email和不依赖Web层的校验信息,还可以让你自

-19-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

己决定在哪里执行校验规则。 Spring本身有对ORM支持和JPA、Hibernate、JDO以及iBatis操作的集成。例如使用Hibernate,你可复用已经存在的映射文件与标准的Hibernate SessionFactory 配置。用控制器去无缝整合Web层和领域模型,消除对 ActionForms 的依赖,或者避免了其他class为领域模型转换HTTP参数的需要。

图3.8使用了第三方框架的Spring中间层

有时候现有情况不允许你彻底从一种框架切换到另一种框架。然而,Spring却不需要强制你使用它的全部,Spring不是一种全有全无的解决方案,就像图3.8所示。如果,现有的应用使用了WebWork、Struts、Tapestry或其他的UI框架作为前端程序,完全可以只与Spring的事务特性进行集成。只需要使用 ApplicationContext 来挂接你的业务逻辑和通过 WebApplicationContext 来集成你的Web层前端程序[15]。

图 3.9 远程使用场景

当你需要通过Web服务来访问你的现有代码时,你可使用Spring提供的 Hessian-、Burlap-、Rmi- 为前缀的接口或者 JaxRpcProxyFactory 这个代理类。你会发现,远程访问现有应用程序不再那么困难了。解决方案类似于上图3.9。

-20-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

图3.10 EJBs包装现有的POJOs

像上图3.102所描绘的,Spring还为EJB提供了数据访问和抽象层,让你可以复用已存在的POJO并将它们包装在无状态SessionBean中,以便在可能需要声明式安全的非安全的Web应用中使用[16]。

按照Spring框架的思想:把Spring看作一个标准开发组件,根据自己的需要,只取用它的部分组件使用而无需涉及其他,本文的整合框架重点使用Spring的依赖注入(DI)和面向切面编程(AOP),下文对它们进行详细介绍

3.2.1依赖注入(DI)

当我们进行项目开发时,我们将一个复杂的系统进行有效的划分,形成多个模块,这样可以使我们有效的理解和控制整个系统,使每个模块都能易于理解和维护。但是模块之间以某种方式进行信息交换的时候,模块和模块之间就不可避免的 发生了某种混合关系。如果各个模块之间没有任何的关联,那么该模块不属于此系统,或者整个软件不过是互不相干的系统的简单堆积,对每一个系统其所有功能均在一个模块中实现,这等于没有做任何模块的分解。从这种意义上说来,模块间的依赖关系是不可避免的。但是,如果模块间耦合关系过强则会给我们带来很大的麻烦,对整个系统来说会造成很大的危害。特别是当需求发生变化时,代码的维护将是一个灾难。因此,我们要尽可能的消解模块间不必要的耦合,尽量提高系统的质量。IoC ( Inver -sion of Control)模式,即控制反转,就是为了要解决模块间的耦合 ,依赖注入(DependencyInjection)是对IoC模式的一种扩展的解释。IoC是一种用来解决组件(实际上也可以是简单的Java类)之间依赖关系、配置及生命周期的设计模式,对组件依赖关系的处理是IoC的精华部分。其中IoC的实际意义就是把组件之间的依赖关系提取(反转)出来,由容器来具体配置。这样,各个组件之间就不存在hard-code的关联,任何组件都可以最大程度的得到重用。而运用了IoC模式后,我们不再需要自己管理组件之间的依赖关系,只需要声明由容器去实现这种依赖关系.就好像把对组件之间依赖关系的控制进行了倒置,不再由组件自己来建立这种依赖关系而交给容器去管理。如图3.11。

-21-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

图3.11 普通依赖关系与IoC原理对比图

依赖注入的几种实现类型

在介绍如何利用控制反转模式实现彻底解耦之前先看看依赖注入的类型:

依赖注入的形式主要有三种,它们分别叫做接口注入(Interface Injection)、设值方法注入(Setter Injection)和构造子注入(Constructor Injection)。这几种类型都能有效控制代码的耦合度,并且有一定的适应范围。

接口注入

接口注入就是使用接口如Serviceable Configurable等来声明对象间的依赖关系。这类IoC容器侵入性最强,需要通过上下文来获取组件。组件需要实现容器提供的特定接口,这样,组件的重用就被限定在该容器内。因此这种思想比新的I0C解决方案更具侵入性。

设值注入

设值注入方法通过使用seters来设置依赖组件。把依赖的组件作为一个属性,通过seters方法来动态设置依赖组件。设值注入是Spring框架比较适合的注入方式。

构造子注入

构造子注入就是通过构造函数完成依赖关系的设定,在构造子注入类型的依赖注入机制中,依赖关系是通过类构造函数建立,容器通过调用类的构造方法,将其所需的依赖关系注入其中。

接口注入模式因为历史较为悠久,在很多容器中都已经得到应用。但由于其在灵活性、易用性上不如其它两种注入模式,因而在IoC的专题世界内并不被看好。设值和构造子注入型的依赖注入实现则是目前主流的loC实现模式。这两种实现方式各有特点,也各具优势。

设值注入的优势:

(1)对于习惯了传统JavaBean开发的程序员而言,通过setter方法设定依赖关系显得更加直观,更加自然。

(2)如果依赖关系(或继承关系)较为复杂,那么构造子模式的构造函数也会相当庞大(我们需要在构造函数中设定所有依赖关系),此时设值注入模式往往更为简洁。

(3)对于某些第三方类库而言,可能要求我们的组件必须提供一个默认的构造函数(如Struts中的Action),此时构造子类型的依赖注入机制就体现出其局限性,难以完成期望的功能。

-22-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

构造子注入的优势:

(1) 在构造期即创建一个完整、合法的对象,对于这条Java设计原则,构造子注入无疑是最好的响应者。

(2) 避免了繁琐的seter方法的编写,所有依赖关系均在构造函数中设定,依赖关系集中呈现,更加易读。

(3)由于没有seter方法,依赖关系在构造时由容器一次性设定,无需担心上层代码在调用过程中执行seter方法对组件依赖关系产生破坏,特别是对于Singleton模式的组件而言,这可能对整个系统产生重大的影响。可见,构造子注入和设值注入模式各有千秋,而Spring对构造子注入和设值注入类型的依赖注入机制提供了良好支持。这也就为开发人员提供了更多的选择余地。理论上,以构造子注入类型为主,辅之以设值注入类型机制作为补充,可以达到最好的依赖注入效果。这个也是本整合框架应用的方式。

3.2.2 面向切面编程(AOP)

通常,系统由很多组件组成,每个组件负责一部分功能,然而,这些组件也经常带有一些除了核心功能之外的附带功能 。系统服务如日志、事务管理和安全经常融入到一些其他功能模块中。这些系统服务通常叫做交叉业务,这是因为它们总是分布在系统的很多组件中。通过将这些业务分布在多个组件中,给我们的代码引入了双重复杂性。

(1) 实现系统级业务的代码在多个组件中复制。这意味着如果你要改变这些业务逻辑,你就必须到各个模块去修改。就算把这些业务抽象成一个独立模块,其它模块只是调用它的一个方法,但是这个方法调用也还是分布在很多地方。

(2) 组件会因为那些与自己核心业务无关的代码变得杂乱。一个向地址录中添加条目的方法应该只关心如何添加地址,而不是关心它是不是安全或支持事务的。

此时,我们该怎么办呢?这正是AOP用得着的地方。AOP帮助我们将这些服务模块化,并把它们声明式地应用在需要它们的地方,使得这些组件更加专注于自身业务,完全不知道其它涉及到的系统服务。这里的概念切面,就是我们要实现的交叉功能,是应用系统模块化的一个方面或领域。切面的最常见例子就是日志记录。日志记录在系统中到处需要用到,利用继承来重用日志模块是不合适的,这样就可以创建一个日志记录切面,并且使用AOP在系统中应用。下图3.12展示了切面应用方式

图3.12 应用切面

其中,通知Advice是切面的实际实现。连接点Joinpoint是应用程序执行过程中插入切面的地点,这个地点可以是方法调用,异常抛出,甚至可以是要修改的字段,切面代码在这些地方插入到你的应用

-23-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

流程中,添加新的行为。切入点Pointcut定义了Advice应该应用在那些连接点,通常通过指定类名和方法名,或者匹配类名和方法名式样的正则表达式来指定切入点。 AOP在Spring中的实现 :

基于AOP,业界存在各种各样的AOP实现,比如,JBoss AOP、Spring AOP、AspectJ、Aspect Werkz等。各自实现的功能也不一样。AOP实现的强弱在很大程度上取决于连接点模型。目前,Spring只支持方法级的连接点。这和一些其他AOP框架不一样,如AspectJ和JBoss,它们还提供了属性接入点,这样可以防止你创建特别细致的通知,如对更新对象属性值进行拦截。然而,由于Spring关注于提供一个实现J2EE服务的框架,所以方法拦截可以满足大部分要求,而且Spring的观点是属性拦截破坏了封装,让Advice触发在属性值改变而不是方法调用上无疑是破坏了这个概念。 Spring的AOP框架的关键点如下:

(1)Spring实现了AOP联盟接口。在Spring AOP中,存在如下几种通知(Advice)类型: Before通知:在目标方法被调用前调用,涉及接口org.springframework.aop.MethodBeforeAdvice; After通知:在目标方法被调用后调用,涉及接口为:org.springframework.aop.AfterReturningAdvice;

Throws通知:目标方法抛出异常时调用,涉及接口org.springframework.aop.MethodBeforeAdvice; Around通知:拦截对目标对象方法调用,涉及接口为:org.aopalliance.intercept.MethodInterceptor。

(2)用java编写Spring通知,并在Spring的配置文件中,定义在什么地方应用通知的切入点。 (3)Spring的运行时通知对象。代理Bean只有在第一次被应用系统需要的时候才被创建。如果你使用的是ApplicationContext,代理对象在BeanFactory载入所有Bean的时候被创建。Spring有两种代理创建方式。如果目标对象实现了一个或多个接口暴露的方法,Spring将使用JDK的

java.lang.reflect.Proxy类创建代理。这个类让Spring动态产生一个新的类,它实现所需的接口,织入了通知,并且代理对目标对象的所有请求。如果目标对象没有实现任何接口,Spring使用CGLIB库生成目标对象的子类。在创建这个子类的时候,Spring将通知织入,并且将对目标对象的调用委托给这个子类。此时,需要将Spring发行包lib/cglib目录下的JAR文件发布到应用系统中。 Spring AOP的优势 :

借助于Spring AOP,Spring IoC能够很方便的使用到非常健壮、灵活的企业级服务,是因为Spring AOP能够提供如下几方面的优势:

(1)允许开发者使用声明式企业服务,比如事务服务、安全性服务;EJB开发者都知道,EJB组件能够使用J2EE容器提供的声明式服务,但是这些服务要借助于EJB容器,而Spring AOP却不需要EJB容器,借助于Spring的事务抽象框架就可以这些服务。 (2)开发者可以开发满足业务需求的自定义切面;

(3)开发Spring AOP Advice很方便。因为这些AOP Advice仅是POJO类,借助于Spring提供的ProxyFactoryBean,能够快速的搭建Spring AOP Advice。

3.2.3 Spring解决方案选择

Spring涉及六大体系,对其中用到的技术以及API很难做出抉择,现通过对Spring的研究,对项目开发所用Spring技术的解决方案做一个总结。如下表2.1。

-24-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

表2.1 Spring技术方案选择

模 块 IoC容器,Bean工厂 作 用 基本的Spring容器,提供了强大和可以拓展的依赖注入能力。 IoC容器,应用程序上下文 AOP框架更高级的更高级的IoC容器,增加了资源载入,事件发布和其它性能。 允许把完善的拦截应用于Spring容使用理由和时机 如果需要覆盖面小的IoC容器——例如,Applet中使用。 Spring容器的一般用法。应用程序上下文是一个Bean工厂,因此其用法模型是一致的。 作为Spring的企业服务(比如申明式事务管理)IoC容器,增加了资源载器管理的任何对象,或者编程式的使用的可行技术——在这种情形中,开发者无需自觉地了入,事件发布和其它性能。 代理工厂,支持核心的AOP概念,比如解AOP的使用 切点,使它不仅是一个简单的拦截机制。 使应用程序能够实现定制的方面,来模块化代码,否则这些代码会散布到整个应用程序对象模型中。 数据访问抽象 提供了资源管理和异常处理的一般建议使用Spring的数据访问抽象,无论使用哪种方法,不管使用的是那种数据访问技术,数据访问技术。 Spring支持下列即开即用的数据访问技建议使用Spring的数据访问支持来实现持久性框术:Hibernate,JDO,TopLink,和Apache 架不可知的DAO接口,意味着业务服务层与持久性框OJB。框架为其它API的支持提供了牢固的概念基础。只要是JSR-220 POJO持久性规范和二进制包以成熟的形式发布,将马上支持它。在Spring主要数据访问概念的基础上,用户实现专用的或者其它不支持的数据访问API也是可能的。 JDBC抽象框架 在JDBC之上提供了简化了异 在需要执行基于SQL的相关操作时,用来代架分离开来。 常处理的API层,极大的减少了在典型替JDBC的直接使用。 的JDBC操作中需要编写的代码量,并且减少了产生普通错误的可能性。 事务抽象 与Spring的数据访问框架集把应用程序代码与基本的事务管理基础设施分离 成,以提供运行于任何环境中的事务抽开来。 象,并且提供无需EJB的申明式事务管理。 提供比JTA或者局部事务更简单,更容易可测试的编程式事务管理。 为任何POJO提供比EJB更强大,移植性更好的申明式事务管理。 MVC Web框架 Spring自己的Web MVC框架,概念上与Struts最相似。 如果喜欢基于请求的Web框架,而且想要高度灵活的,可定制的框架,其中模型,视图和控制器职责清晰分离,并且可以适应各种视图技术,那么可以使用它。 -25-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

JMS 支持JMS消息发布 使得JSM消息发布更容易,不管如何消费消息。 J2EE集成 与核心容器的集成以免JNDI查询,并且使EJB更容易实现和访问。 把应用程序代码与JNDI环境分离,使它在非J2EE易于测试和使用,并且通过把重点集中在提供应用程序功能相关业务接口,而不是J2EE API细节,使其目的更加清晰。 轻量级远程处理 提供了远程处理支持,可以跨 用于导出基于任何Spring管理的对象远程服越多种远程处理协议来导出POJO服务。 务。 JMX支持 给Spring管理的对象提供了JMX的管理,Spring没有提供其自己的JMX Mbean服务器,它的JMX支持与应用程序服务器或者独立的JMX服务器提供的集成在一起。 脚本支持 使得Spring容器管理任何对象都可以使用脚本语言来编写,以代替Java。 在运行时间用JMX管理应用程序对象。 3.3 持久层框架Hibernate

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任[17]。

要把握好Hibernate,必须掌握Hibernate的实现机制,体系结构原理。其它的象对象关系映射将在具体整合应用中介绍,以免发生重复,象Hibernate的主键的具体应用,检索方式,集合映射可以参考相关书籍,因为这些都是应用很强的东西,在具体开发中参阅会得到更好的效果,本文不再叙述。

3.3.1 Java反射机制

反射机制(reflection)是Java语言非常重要的特性,同时也是Hibernate的核心机制。这种特性不仅允许运行中的Java程序对自身进行检测,而且还能够直接操作程序自身的方法。很多开源框架都抓住了这样一个特性,从而造就了Java现在的辉煌局面[18]。Hibernate为实现反射机制的应用提供了丰富的接口,具体接口的含义参看Hibernate API。

3.3.2 对象/关系映射机制

Hibernate中最核心的技术就是ORM,所谓ORM,简单地说就是将Java中的对象与对象的关系,对应到关系型数据库中的表格与表格之间的关系,Hibernate提供了这个过程中自动化对应转换的方案,

-26-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

相反地,也提供了关系型数据库中的表格与表格之间的关系,对应至Java程序中的对象与对象的关系。Hibernate在Java程序与数据库之间进行转换,Java程序员重要事先定义好对象与数据库表格之间的对应,此后Java程序设计人员就可以使用熟悉的面向对象程序设计方法编写程序,而不再需要进行特定的与SQL之间的转换,所有SQL的转换交由Hibernate进行处理。也就是说 ,Hibernate中提供了数据查询和获取数据的方法,从而大幅度减少了开发时人工使用SQL和JDBC处理数据的时间。Hiberna e的目标是承担开发人员为了实现数据持久处理而需要做的大量重复性工作,帮助开发人员轻松地从数据表中获取到的结果集,从表格式的表示形式直接转换到对应的对象表示形式。也就是说,原先需要开发人员手工编写代码实现将记录字段中的值取出封装成对象的过程,以及将对象中的属性值分别取出作为对应记录字段值存储到数据表中的过程都可以交给Hibernate提供的相关工具完成。Hibernate本身带给我们的不仅仅是一种软件开发的架构,更是一种值得推广的数据持久性解决方案。这些数据持久性设计的概念,是可以在脱离开Hibernate之后,推广应用到更广泛的数据持久性处理领域中的。目前,EJB3A中的实体Bean的最新设计已经采用了和Hibernate类似的方案[19]。

3.3.3 Hibernate体系结构

一个非常高层次的Hibernate体系结构图如下图3.13所示。

图3.13 Hibernate体系结构图

这幅图展示了Hibernate使用数据库和配置文件数据来为应用程序提供持久化服务(和持久化的对象)。 我们展示一个更详细的运行时结构图。不幸的是,Hibernate很灵活并且支持多种运行方式。我们展示一下两种极端情况。轻型体系中,应用程序自己提供JDBC连接,并且自行管理事务。这种方式使用了Hibernate API的一个最小子集[20]。参见下图3.14。

-27-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

图3.14 Hibernate轻量解决方案

全面解决体系中,对于应用程序来说,所有的底层JDBC/JTA API都被抽象了,Hibernate会替你照管所有的细节。参见下图3.15所做的改进。

图3.15 全面解决的体系结构方案

下面是图中一些对象的定义:

SessionFactory (org.hibernate.SessionFactory) 是对单一数据库的已编译映射文件的线程安全实现不可变的高速缓存。它是Session的工厂,是ConnectionProvider的客户。可能持有一个可选的可在进程级别或集群级别事务间重用的(二级)数据缓存。

会话 Session (org.hibernate.Session) 单线程的短生命周期的对象,是应用程序和持久化存储的一次对话。封装了一个JDBC连接,也是Transaction的工厂。保持一个持久化对象的强制(第一级)缓存,用来遍历对象图或者根据标识符查询对象。

持久化对象和集合 ( Persistent objects and collections) 包含持久化状态和商业功能的短生命周期的单线程对象。它们可能是普通的JavaBean或POJO,唯一特别的是它们通常跟且只跟一个Session相关联。一旦Session被关闭,它们将游离并能在任何应用层被使用(例如,直接作为表示层的数据传输对象)。

-28-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

临时分离对象和集合(Transient and detached objects and collections) 当前没有跟Session关联的持久化类的实例。它们可能是应用程序实例化但是还没有持久化的或者是被已关闭的Session实例化的。

事务 Transaction (org.hibernate.Transaction) (可选)单线程,短生命周期的对象,应用程序用它来表示一批工作的原子操作。是底层JDBC,JTA或者CORBA事务的抽象。一个Session某些情况下可能跨越多个Transaction 事务。然而,使用底层API或者Transaction进行的事务划分不是可选的。

ConnectionProvider (org.hibernate.connection.ConnectionProvider) (可选) JDBC连接的工厂和连接池。底层 Datasource或DriverManager的抽象应用。对应用程序不可见,但可以被开发者扩展/实现。

TransactionFactory (org.hibernate.TransactionFactory) (可选)事务实例的工厂。对应用程序不可见,但可以被开发者扩展/实现。

扩展接口(Extension Interfaces)

Hibernate 提供很多可选的可扩展接口,你可以实现它们来定制你的客持久化层的行为。在API中查看更多细节。

本章分别从宏观上阐述了轻量级框架Struts,Spring和Hibernate的技术内涵。挑选的角度主要集中在它们各自在项目开发中所能发挥的优势的之处。重点介绍了StrutsMVC模式原理和实现方式,Spring在解决复杂业务逻辑时用到的的DI和AOP,并对DI的几种实现方式进行了分析,供开发人员参阅。同时对Spring解决方案进行了总结,为下一章实现框架整合打下理论基础。

-29-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

第4章 Web应用系统分析与设计

基于Web的项目,一般都分为部署在服务器上供客户访问的网站前台,和对网站进行管理的后台,网站后台管理范围依据具体项目有所不同。大致来说,一般的网站后台都有权限管理,不同权限可以对数据库做不同的操作。另外,象文章发布(有的是本单位的新闻之类),图片(或者是产品,或者是人物)等都是必须的。本章以开发一个通用的网站后台管理系统为例,需求范围是一般后台管理功能的交集,提出一个以Struts、Spring和Hibernate整合架构来实现,以为以后MIS系统开发做参考。

4.1项目需求分析

通过对多个后台管理系统分析,一般的系统都具有如下功能:用户管理,模块管理,文章管理,图片管理,链接管理,对数据库模糊查询,对登录后操作人员所做的各种操作进行记录,回收站管理等。 1. 会员管理子系统

任何一个后台都必须有用户管理,除非它是给某个特定用户,它记录用户基本信息(姓名,密码,性别,年龄,地址,Email,电话,创建用户时间,最近登录时间),使用权限。同时可以根据权限做不同的操作,系统管理员必须有增加用户,删除用户,修改用户信息等功能。

1、 会员注册 2、 会员列表 3、 权限设置 4、 删除用户

2. 信息发布子系统

一般的单位都必须提供文章管理,本模块用来为网站添加新闻,文献,评论等文字的东西,所以文章的信息必须有文章的一级标题,二级标题,作者,内容,文章创作时间,文章修改时间等。还可以根据权限可以写文章,读文章,删除文章。

新闻发布 产品信息发布 3. 订单管理子系统

5、 订单申请 6、 订单列表 7、 订单处理 8、 订单删除

4. 招聘管理子系统

9、 招聘处理 10、 11、 12、

岗位添加 岗位修改 岗位删除

-30-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

5. 留言管理

13、 14、 15、 16、

留言列表 留言处理 留言删除 权限设置

6. 日志管理子系统

任何一个登录本网站的人员都必须对其跟踪,知道她对本网站做了些什么。

图4.1是网站后台管理系统用例图。一般软件开发都有详细设计说明书,本论文目的是给西部MIS系统开发系统架构设计作参考,故不在论文中提及设计说明书。本系统在附录一中有用户管理模块的的详细设计说明书的样板,读者可以参阅。

用户管理图片管理模块管理<><><><>文章管理<><>管理员<><><>功能拓展链接管理信息查询回收站管理工作记录 图4.1 网站后台管理系统用例图

4.2总体架构设计

整合框架的思想是利用Struts架构作为系统的流程控制,它负责了MVC的分离,而且他的作用也仅仅是控制MVC的分离,而没有使用Struts的模型,因为模型交给Spring管理能够带来给以后系统带来巨大的便利,如数据库由MySq替换成Oracal时,只需要修改里面的数据源,也就带来了便于移植的便利。当然还有其他的好处。业务层用Spring的IoC和AOP支持。具体做法是用面向对象的分析方法根据需求来提出一个模型,将这些模型采用Java语言实现出基本的Java对象,然后写出基本的DAO接口,并给出Hibernate的DAO实现,采用Hibernate架构实现的DAO类来实现Java类与数据库之间的转换和访问,然后由Spring来完成业务逻辑。图4.2是整合框架原理图。

-31-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

表示层Struts-MVCStrutsActionActionFormJSPStruts-config.xml业务逻辑层Spring事务管理ApplicationContextHibernate的Session管理业务逻辑类管理数据持久层Hibernate数据源或者DAO Class数据连接池查询语言支持等 图4.2整合框架原理图

本章先阐述数据持久层和业务逻辑层如何实现通讯。然后介绍业务逻辑层如何解决Struts中应用逻辑所存在局限的问题,即通过Spring管理,从而形成了一个整合后的框架。

4.2.1 业务逻辑层与数据持久层的通讯及其解耦方式

业务逻辑与数据持久层的通讯设计如图4.3所示。在这里重点介绍接口设计思想和HibernateTemplatet以及对象关系映射。

接口实现接口业务逻辑Bean继承HibernateTemplateHibernate O/R映射管理数据库 图4.3 业务逻辑与数据库通讯设计

(1)使用接口设计思想

封装的一种方式是通过使用接口(Interface)实现的。接口(Interface)提供一种途径,使类隐藏其处理的特定事物的细节,仅对外公布它必须支持的属性。对于编程所涉及的,你可以修改类的实现,而不修改它的调用,因为属性本身没有改变,修改的仅仅是类的实现。通过实现类的接口,并且在类设计时仅对外公布接口(Interface),你就有效的封装了类的定义,这样后台实现的变动将对系统其它部分的影响最小,也就有效的解决了耦合过高的问题。另外,模块的接口多了一层隔离,同样降低了耦合,把接口的通用性和接口的适应性分离,又明确了模块的边界,使得接口在日后的优化和调整有了缓冲。 (2)HibernateTemplate

就像JDBCTemplate一样,HibernateTemplate封装了Hibernate存储时的细节。HibernateTemplate也提供持久层访问模板化,使用HibernateTemplate无须实现特定接口,它只需要提供一个SessionFactory的引用,就可执行持久化操作。对于在Web应用,通常启动时自动加载

ApplicationContext,SessionFactory和DAO对象都处在Spring上下文管理下,因此无须在代码中显式设置,可采用依赖注入解耦SessionFactory和DAO,依赖关系通过配置文件来设置。当数据库进行移植时(例如由mysql转换为sqlserver),只需要修改有下划线的语句,所有上层设计和编码都没有任何改变,这里实现了完全的与数据库的解耦。需要说明的是,数据源和SessionFactory是属于

-32-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

hibernate-config.xml中的,为了便于管理,在这里一起集成到了applicationContext.xml中,如下代码所示:

-33-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

DAO实现类中,可采用更简单的方式来取得HibernateTemplate的实例。代码如下: public class PersnDAOImpl implements PersonDAO {

//以私有的成员变量来保存SessionFactory,之所以要用private,是为了防止对象之间访问时出错,因为在多人协作开发中,各个开发人员可能用了相同的对象名字。

private SessionFactory sessionFactory; //设值注入SessionFactory必需的setter方法

public void setSessionFactory(SessionFactory sessionFactory) {

this.sessionFactory = sessionFactory; }

public List loadPersonByName(final String name) {

HibernateTemplate hibernateTemplate = new HibernateTemplate(this.sessionFactory); //此处采用HibernateTemplate完成数据库访问 } }

另外HibernateTemplate提供非常多的常用方法来完成基本的操作,比如通常的增加、删除、修改、查询等操作,Spring 2.0更增加对命名SQL查询的支持,也增加对分页的支持。大部分情况下,使用Hibernate的常规用法,就可完成大多数DAO对象的CRUD操作。下面是HibernateTemplate的常用方法简介:

void delete(Object entity):删除指定持久化实例。

deleteAll(Collection entities):删除集合内全部持久化类实例 find(String queryString):根据HQL查询字符串来返回实例集合。 findByNamedQuery(String queryName):根据命名查询返回实例集合。 get(Class entityClass, Serializable id):根据主键加载特定持久化类的实例。 save(Object entity):保存新的实例。

-34-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

saveOrUpdate(Object entity):根据实例状态,选择保存或者更新。 update(Object entity):更新实例的状态,要求entity是持久状态。 setMaxResults(int maxResults):设置分页的大小。 (3) 对象关系映射

对象关系映射(Object Relational Mapping,简称ORM)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中。这样我们就由对数据库的操作完全转为对对象的操作[21]。

4.2.2业务逻辑层的衔接

我们已经知道:依赖注入具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者实例的工作通常由Spring容器来完成,然后注入调用者。本系统中,业务逻辑层主要是通过依赖注入实现的。如图4.4所示。Action主要负责操作的具体动作,而不具体实现,也就是说,它只是一个空壳,具体的业务逻辑实现由Spring的Bean完成,这样的直接目的是为了解耦,因为Action也是Class对象,在Struts中,Action负责具体的行为,一旦行为确定,就无法更改。如果系统需求变更或者稍作更改时,整个Action都要重写,由此也会让系统其它调用Action的地方一起更改,这样的后果类似于重做系统,这在软件开发中被称为失败。为了解决这样一个难题,我的设计方法是用依赖注入思想,业务逻辑Bean负责具体的行为实现,无论系统需求怎么变更,只要更改业务逻辑Bean,而Action和与Action相关的调用都可以保持不变,而Action调用Bean时,也不必每次都去实例化,在Spring的ApplicationContext容器中进行相关配置实现注入。

ActionSpringAplictionContext业务逻辑Bean图4.4 用Spring实现Struts与业务逻辑的桥接

例如下面代码,通过依赖注入,仅仅几行代码ModuleAction就获得了Bean moduleService和userOperationService的具体动作实现,并且完全实现了解耦。

-35-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

bean中的属性,象abstract(抽象类),lazy-init(延迟实例化),autowire(自动装载)这些属性配置,请参阅相关书籍,这里不做重复。

4.2.3 整合后的框架

通过上面两个小结的设计,我们实现了业务逻辑与持久层的通讯和系统中业务逻辑的衔接。就形成了一套整合后的框架。这样的一个框架避免了Stuts用Action控制业务逻辑而无法解耦,从而容易使系统开发失败的问题。而且接口有效的封装了类的定义,这样后台实现的变动将对系统其它部分的影响最小,也就有效的解决了耦合过高的问题。Hibernate使开发人员在数据库操作方面,工作量降到了最低,大大减轻了软件开发人员的负担。整合后的框架主体部分如图4.5所示。这样一个设计,也就实现了系统开发低耦合,易重用,便于移植的目标。

ActionSpringAplictionContext接口实现接口业务逻辑Bean继承HibernateTemplateHibernate O/R映射管理数据库 图4.5 整合框架主体部分原理图

4.3框架处理流程原理设计

框架处理流程原理如下图4.6所示。用户通过浏览器发送Http请求(每个请求都是.do标识),发送后的请求由控制器(ActionServlet)负责接收,在配置文件中与点do匹配,并且寻找相关的Action。找到后把接受的数据填充ActionForm,自动执行ActionForm里面的方法,用来判断数据是否合法,如果返回为null,表示通过验证(validate方法)。如果返回非null,表示不能通过验证,这里需要说明的是ActionForm是可选的,根据需要才进行验证。验证成功后,控制器根据与之对应的Action执行execute方法。到此为止,只是利用的Struts MVC模式,并没有使用Struts处理业务逻辑和数据库操作。尽管Action有这个能力,但Action完全把这个任务交给相关的Bean。Action利用注入的业务逻辑Bean处理业务逻辑,由于这个调用不是自己完成的,是通过Spring 依赖注入的,所以这个地方可以做得完全解耦,因为Spring可以根据需要注入不同的Bean,只需要修改applicationContext.xml文件里所配置的Bean就可以了,而无需其它改动。Bean用来实现接口和继承HibernateDaoSupport类,接口用

-36-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

来定义功能模块应该实现的功能,为了进一步解耦和定义模块边界,具体实现留给了Bean。继承HibernateDaoSupport是为了使用它所封装的属性和方法,Hibernate是用来建立对象关系映射的工具,通过它可以很容易的操作数据库。

HTTP Request Arrives.do?YControler receiver the RequestMap to ActionFind Action?foundnoCreate ActionFormNot foundReturn errorValidate ?NointerfaceCreate Action Execute()DAOProcess ActionForwardReturn actionForwardThis ActionMapping?yesReturn response 图4.6 框架处理流程原理UML状态图

4.4系统模块设计

系统设计是根据相应的需求提炼出对应的模块

(1)常规功能:有很多功能在较高层次上设计是类似的,除了一些细节。当用户登录后,首先都有对数据的浏览,然后根据管理员自己的需要,增加,删除,修改。设计如图4.7所示:

-37-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

一般用户管理员用户登录用户类型?查看修改数据库删除 图4.7 用户登录及其权限设计

(2)图片管理:图片是指所有单位需要发布出去的各种图片信息。这个模块提供信息为图片名称,所属模块等,提供操作为,添加指定类型模块,对其修改和删除等。

(3)模块管理:模块管理是对文章模块和图片模块进行管理,因为图片和文章都对自己进行了分类,分成不同类型的图片和不同类型的文章。提供信息是模块名称,模块内容以及类型。提供操作为添加指定类型模块,修改和对其删除。

(4)文章管理:文章既可以是事业单位的科普文章,文件,通知等,也可以是工厂的产品说明,产品发布信息,甚至是订单。总之是所在单位所需要提供出去共大家共享的信息。提供信息是,文章标题,作者,发布时间,修改时间。提供功能是添加,按文章类型检索,修改,删除等。

(5)链接管理:每一个后台一般都会对他们所管理的网站链接进行管理,管理那些本网站经常要访问的地方。通过这个模块得到的信息是:链接名称,链接地址,链接的图片。并提供添加,修改,删除链接功能。

(6)回收站管理:由于这个后台信息管理个系统可能有多个系统管理员,当一个系统管理员删除了其他管理员所需要的信息时,我们必须有办法对其记录和恢复。实现的功能是得到一下信息:删除对象名称,对象类型,时间。以及提供分类检索,恢复,和彻底删除。

(7)系统操作跟踪:由于一个系统有多个系统管理员,而每一个操作做都会对数据库相应的表产生作用,为了避免管理员之间的操作使每个管理员都知道,所以对操作进行跟踪。一般会得到用户,操作,操作时间,操作所在的IP地址。

(8)信息查询:查询分为一般查询和模糊查询,顾名思义,查询就是检索自己需要的信息。 (9)功能拓展:如果系统要增加新功能,可以在此处进入。

4.4.1 持久层设计

数据持久层的设计目标是为整个项目提供一个高层、统一、安全和并发的数据持久机制。完成对各种数据进行持久化的编程工作,并为系统业务逻辑层提供服务。数据持久层提供了数据访问方法,能够使其它程序员避免手工编写程序访问数据持久层(Persistene layer),使其专注于业务逻辑的开发,并且能够在不同项目中重用映射框架,大大简化了数据增、删、改、查等功能的开发过程,同时又不丧失多层结构的天然优势,继承延续J2EE特有的可伸缩性和可扩展性。

1 数据持久层及ORM映射框架

Hibernate是一种新的ORM映射工具,是JDBC的轻量级的对象封装。Hibernate可以用在JDBC可以使用的任何场合,例如Java应用程序的数据库访问代码,DAO接口的实现类等。Hibernate不仅提供了从Java类到数据表之间的映射,也提供了数据查询和恢复机制。相对于使用JDBC和SQL来手工操作数据库,使用Hibernate,可以大大减少操作数据库的工作量。

-38-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

Hibernate是一个和JDBC密切关联的、独立的对象持久层框架,可以搭配各种应用服务器、Web 服务器和EJB Container共同使用,Hibernate的兼容性仅同JDBC驱动、底层数据库产品间有一定的关系,但是和使用它的Java程序、应用服务器没有任何关系,也不存在兼容性问题。而且事实表明Hibernate可以和多种Web服务器或者应用服务器良好集成,如今已经支持几乎所有的流行的数据库服务器(达16种)。

在较为常用的数据持久方案中,Hibernate无疑是最优秀的,下面是对各种持久方案的比较[22]。 方法一: 流行的数据持久层架构:

Business Layer <-> Session Bean <-> Entity Bean <-> DB 方法二:为了解决性能障碍的替代架构: Business Layer <-> DAO <-> JDBC <-> DB

方法三:使用Hibernate来提高上面架构的开发效率的架构: Business Layer <-> DAO <-> Hibernate <-> DB 我们就上面3个架构来作如下分析。

(1)内存消耗:采用JDBC的架构无疑是最省内存的,Hibernate的架构次之,实体Bean的架构最差。

(2)运行效率:如果JDBC的代码写的非常优化,那么JDBC架构运行效率最高,但是实际项目中,这一点几乎做不到,这需要程序员非常精通JDBC,运用Catch语句,调整PreapredStatement的Catch Size和Fetch Size等参数,以及在必要的情况下采用结果集缓存(cache)等等。而一般情况下程序员是做不到这一点的。因此Hibernate架构表现出最快的运行效率。实体Bean的架构效率会差的很远。

(3)开发效率:在有Eclipse、JBuilder等开发工具的支持下,对于简单的项目,实体Bean架构开发效率最高,JDBC次之,Hibernate最差。但是在大的项目,特别是持久层关系映射很复杂的情况下,Hibernate效率高的惊人,JDBC次之,而实体Bean架构很可能会失败。

通过对各种方案分析对比,Hibernate无疑是最好的选择,在本系统中所采用的设计思路是POJO<->object.hbm.xml<->table。即通过POJO暂时保持和传递数据,然后按照每个对象的对象关系映射文件所指引的规则与表交付。 以文章功能模块设计为例(只说明前四个属性实现方式,其它实现与这个一样),如下图4.8,4.9,4.10所示:

图4.8 article模块对应的POJO

-39-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

图4.9 与article POJO对应的对象关系映射文件article.hbm.xml

图4.10 与article.hbm.xml对应的表

如上面三个图说展示的,POJO的每一个属性都通过其映射文件把规则映射到表中的字段,通过这样一种设计,这样只要对对象进行操作,也就同样对表进行了操作。

2 数据持久层设计

复杂性是应用开发过程中最令人头疼的一个问题。每当在一个应用中增加一个功能时,它的复杂性通常呈次方级的增长[23]。这种复杂性往往导致程序的开发无法再继续下去。这也是现在为什么许多应用只有Beta版本而没有正式版的原因。

专家将应用开发过程产生的复杂性分为两类,即非本质的(accidental)和本质的(essential)。本质的复杂性是对于解决目标问题所必然产生的复杂性,非本质的复杂性是由于选择了不适当的开发工具和设计工具而产生的复杂性。对于一个功能确定的程序来讲,本质的复杂性是确定的,而非本质的复杂性则是没有限制的。因此,一个应用的开发要想较顺利地取得成功,就需要尽可能地减少非本质的复杂性[24]。

设计模式使人们可以更加简单方便地复用成功的设计和体系结构。将已证实的技术表述成设计模式,也会使新系统开发者更加容易理解其设计思路。

衡量一个系统优秀与否的关键因素,除了能够满足用户需求外还有如下方面:首先是灵活性。灵活性意指这种结构或模式不依赖于任何实际应用,应该与操作系统、应用程序无关。提供独立的结构,可以提供最大的重用。其次是可扩展性。随着业务的扩展,新的业务不断增加,业务逻辑自然增加,系统必然会进行修改或添加相应功能模块。再次是可配置性。最后是安全性。

数据持久层的设计采纳了多种设计模式,最大限度的降低了系统内部各模块、子系统间的耦合性,使得系统相对易于扩展,并且能够在进行改变时,保证持久层的业务逻辑层相对稳定,基本不需要因持久层的调整改变而进行逻辑层的变动。

3 数据访问对象(DAO)

根据数据源不同,数据访问也不同。根据存储的类型(关系数据库、面向对象数据库等)和供应商不同,持久性存储(比如数据库)的访问差别也很大。当业务组件或表示组件需要访问某数据源时,它们可以使用合适的API来获得连接性,以及操作该数据源。但是在这些组件中包含连接性和数据访问代码会引入这些组件及数据源实现之间的紧密耦合。组件中这类代码依赖性使应用程序从某种数据源迁移到其

-40-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

它种类的数据源将变得非常麻烦和困难,当数据源变化时,组件也需要改变,以便于能够处理新类型的数据源。

在本项目开发项中,数据持久层使用数据访问对象(DAO)来抽象和封装所有对数据源的访问。DAO管理着与数据源的连接以便于检索和存储数据,DAO实现了用来操作数据源的访问机制,内部封装了对Hibenernate数据操纵、事务处理、会话管理等API的封装。外界依赖于DAO的业务组件为其客户端使用DAO提供了更简单的接口,DAO完全向客户端隐藏了数据源实现细节。由于当低层数据源实现变化时,DAO向客户端提供的接口不会变化,采用该设计模式允许DAO调整到不同的存储方式,而不会影响其客户端或业务组件,即使将来不再采用Hibernate作为关系映射框架,上层客户端也不会受到任何影响。另外,DAO还充当组件和数据源之间的适配器的角色。由于整个项目持久层的这种设计较多,而且每个模块原理类似,我们仅对资源模块的一个持久层设计方案进行介绍(pictureModule)。如下图4.11所示。每一个DAO都继承对应的接口(本例operateInterface),这样可以界定对应操作,其实现者pictureDAO实现operatorInterface同时继承Spring框架下HibernateDaoSupport对象,这样即在规范下操作,又获得了Spring框架中DAO的支持,运行结果可以得到相关对象(picture)。

<<实现类>>pictureDAO+save()()+findByID() : object(idl)+delete()()+merge(Picture detachedInstance)() : object(idl)+findAllForRecycle()() : any(idl)+findAll()() : any(idl)+findByPictureDisplayPlace(Object pictureDisplayPlace)() : any(idl)+findByPictureContent(Object pictureContent)() : object(idl)+findByPictureUrl(Object pictureUrl)() : object(idl)+findByPictureName(Object pictureName)() : any(idl)+findByProperty(String propertyName, Object value)() : object(idl)+findById( java.lang.String id)() : object(idl)picture-id : any(idl)-name : string(idl)-url : string(idl)-content : string(idl)-isDelete : char(idl)-deleteTime : octet(idl)-pictureCreateTime : string(idl)<<接口>>operateInterface+save()()+findById()() : object(idl)+findByTitle()() : object(idl)+delete()()+findByproperty(object tem,object tem2)() : object(idl)+finBypictureName(String name)() : object(idl)+findBypictureUrl(String url)() : object(idl)+findByPictureDisplayPlace(Object pictureDisplayPlace)() : object(idl)+findAll()() : any(idl)+findAllForRecycle()() : any(idl)+merge(Picture detachedInstance)()+.....()

图4.11 图片(picture)模块设计

4.4.2业务层设计

与为什么需要数据访问层类似,如果我们曾经进行过缺乏业务层的应用构建,那么对于这个问题的回答就相当简单直白了。如果我们不把所有的业务逻辑都集中在一个独立的区域,那么最后的结果就是逻辑代码散布在表现层代码之间,典型的结果就是大量的代码重复,更不要提创建缺乏明确职责边界的代码。撇开代码重复问题,缺乏明确职责界定的代码通常难于维护,因为很难知道某个功能实现到底位于何处。

一个定义明晰的业务层扮演着应用程序入口的角色,为我们的表现层代码提供了一个简单统一的业

-41-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

务逻辑实现点。好的业务层也对我们的应用在执行何种操作,以及向用户表达怎样的逻辑进行了明确的定义。

如果我们决定采用两种不同类型的用户界面对同一逻辑进行表述,那么忽略逻辑层的一个重大缺陷将浮出水面。例如我们提供了一个Web应用,同时,我们又计划为经常使用这项应用的客户提供一个桌面客户端软件,如果逻辑代码与Web表现层代码相混合,那么我们就不得不进行代码重构,或者干脆针对Swing或者SWT重新编写一份新的逻辑实现,这需要大量的重复开发和测试工作。对构建一个稳固的业务层的重要性进行强调永远都不会显得多余。如果没有业务层,就很可能会导致我们的项目失败。无法通过集中化的方式进行业务逻辑处理,不可避免的将导致更多的错误,维护工作的噩梦以及不愉快的客户体验。

在业务层设计中,为实现表现层和业务逻辑层之间的最大限度解耦,引入了业务代理模式 (buiness proxy),这样,当表现层或业务逻辑层具体实现发生变化时,对彼此的影响很小。使用业务代理模式的好处是:

1.业务层所有服务完全展示给客户端,客户端可以完全介入调用。 2 动态扩展性强,可为整个业务逻辑层动态扩展新的功能。 3.客户端调用业务层的实现代码简洁,最大限度降低代码的耦合性。

在表示层与业务对象之间插入委托对象之后,客户机就可以调用业务而不需要知道操作和业务对象本身。业务代理模式结原理构图如下图4.12所示

Client CodeBusinessProxyCreate ProxyBusinessObjectCreate ObjectCall Business MethodCall Business Method图4.12 业务代理模式

为了实现一种松散结合,解耦和代码移植,依据上面研究的理论结果完全可以实现。为了便于业务需求的更改,由DAO实现具体的业务逻辑功能,Action做动作的外壳,当Action要完成相应的动作时,调用对应的DAO,这个调用不用实例化对象,用Spring 的IoC原理,在applicationContext.xml配置实现。在这里还考虑了一个问题,当项目较复杂时,可能会出现多次调用同一个DAO,这样就要频繁注入,为了使结构清晰,解耦性强,我们为每一个Action设置一个代理,每个Action只要访问其ActionProxy。以下图4.13的user设计模块为例,图中4,5,6,7就说明怎样实现代理和IoC。当对用户有个具体行为时,由userDAO做相应的实现,然后将其注入到userActionProxy中,以后任何一个功能模块要执行这个用户的行为时,不用一次次的频繁注入到相应的Action中,只要访问相关的代理(proxy)就可以了。这样就真正做到了当表现层或业务逻辑层具体实现发生变化时,对彼此的影响很小。总之,Spring依赖注入设计思想在其中起决定性作用。

-42-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

ActionServletActionForm(selected)UserActionActionProxyIoC FrameworkPersistentJSPOperator1:Submit2:validate3:right4:Call Proxy6:set()7:Return Resultset8:TransactionResult9:Select View to DisplayerrorJavaBean5:create()Submit PageProxy and IoCData Persistent OperateView to Display 图4.13 业务逻辑模块实现方式设计

4.4.3 表现层设计

表现层负责管理用户请求和响应,并提供控制器将调用委托到业务逻辑和其他上游处理。表现层的原理比较简单,如图4.14所示。页面提交请求,由ActionServlet对接收的数据统一控制,根据xml文件里面的配置将数据转发到对应的Action,而页面显示过程就是这样一个反过程。

页面ActionServlet数据转发userAcionpictureActionmoduleActionarticleAction 图4.14 页面数据与Action之间交互设计

设计表现层时需要考虑的几个问题:

开发者在设计表现层时,可以使用不同的模型,这时需要考虑一些相关的设计问题。这些问题和模型关系的紧密程度也各有不同,它们可以影响系统的各个方面,包括有安全、数据完整性、可管理性和扩展性。虽然这些设计问题大部分都可以用模型的形式表示,但我们不打算这样做,因为这样更为抽象,我们选择以非正式的文档形式表示。我们只是根据不同的模型,将每个需要考虑的问题列出来。 Session管理

用户Session指的是跨越一个客户和服务器多个请求间的一个对话。我们将在以下部分根据用户Session的概念讨论这个问题。 客户端的Session状态

在客户端保存Session的状态指的是将Session的状态串行化并且嵌入到返回给客户的HTML页面中。

在客户端保存Session的状态有这以下的好处: . 它实现起来相对容易

. 在保存少量的状态信息时,它工作得很好

-43-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

此外,这个策略还消除了跨越多个服务器复制状态的问题,例如多个服务器间实现负载均衡时就会遇到这种情况。

在客户端保存Session状态通常有两个方法--HTML的隐藏字段和HTTP cookies--我们将在下面讨论这些策略。第三个策略则是在每个页面的URL中嵌入Session状态信息,例如<form action=someServlet?var1=x&var2=y method=GET>。虽然第三个方法比较少见,但它也有着其它两个方法的许多限制。

HTML的隐藏字段(HTML Hidden Fields)

虽然这个方法实现起来相对容易,不过使用HTML隐藏字段在客户端保存Session状态仍然有着许多的缺点。这些缺点在保存大量的状态时尤为突出。保存大量的状态将会对性能有很大的影响。因为每次发出请求和响应时,都需要在网络中传送这些状态信息。

此外,当你利用隐藏的字段来保存Session状态时,这些持久的状态值只能是字符串值,因此所有的对象引用都必须被“字符串化”,而这些信息除非经过特别的加密,否则都是以明文的形式显示在HTML的源代码中。 HTTP Cookies

与隐藏字段的方法一样,使用HTTP Cookies的方式也是相对简单的。不幸的是,这两个方法有着许多相同的缺点。特别是,在保存大量的状态信息时将会对性能产生很大的影响,因为在每次的请求和响应时,都必须在网络上传送全部的Session状态信息。

在客户端保存Session状态时,我们也会遇到大小和类型的局限问题。cookie headers的大小是有限制的,这样就限制了可以被持久保存的数据量,而且和隐藏字段的方法一样,当你使用cookies来保存Session状态时,这些持久的状态信息只能使用字符串值。 在客户端保存Session状态会带来的安全问题

当你在客户端保存Session状态时,你必须考虑到由此带来的安全问题。如果你不想数据暴露给客户端,你就需要一些方法来加密数据,从而保证数据的安全。

虽然在客户端保存Session状态相对容易实现,不过它有着很多的缺点,这些都要我们花费时间去解决。对于需要处理大量数据的项目,特别是企业的系统,使用这种方式是得不偿失的。 表现层的Session状态

当Session状态保存在服务器端时,它使用一个Session ID得到,并且会一直保持住,直到发生以下的情形:

. 一个预定义的Session超时发生了 . Session被手动设置为无效 . 状态由Session中移除

要注意的是服务器关闭后,一些内存中的Session管理机制可能不能恢复。

很明显,对于要保存大量Session状态的应用,将它们的Session状态放在服务器是更好的。当状态被保存在服务器上时,你不会有客户端Session管理的大小和类型限制。此外,还避免了由此带来的安全问题,而且也不会遇到由于在每个请求间传送Session状态带来的性能影响。 使用该方式,你可以更加灵活地作处理,并且便于扩展和提高性能。

如果你在服务器上保存Session状态,你必须要决定如何使该状态信息被每个服务器得到,即你运行该应用的服务器。如果群集的软件是运行在负载均衡的硬件上,那么就要处理这个Session状态的复

-44-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

制问题,这是一个多维的问题,不过,众多的应用服务器现在都提供了各种各样的解决方案。也就是说,在应用服务器的级别上有解决的方法。其中的一个方法是保证用户只与一个服务器打交道,它在流量管理软件上用得比较多,例如Resonate [Resonate]的软件,在用户的Session中,该用户发出的每个请求都会被路由到同一个服务器处理。这种方式也被称为server affinity。

另一个可选的方式是在商业层或者资源层保存Session状态。企业JavaBeans组件可用来在商业层保存Session的状态,而一个关系数据库则可用在资源层。 控制客户访问

有很多时候我们都要限制或者控制客户端访问某些应用资源。下面我们就来讨论其中两种这样的情形。

限制或者控制客户访问的一个原因是防止一个视图或者部分的视图被一个客户直接访问。这个问题会发生在以下情况,例如仅有注册或者登陆后的用户才可允许访问一个特别的视图,或者是根据用户的角色限制用户访问部分的视图。

在描述过这个问题后,我们将讨论第二种情况,它和控制应用中一个用户的流程有关。后者的讨论和重复的form提交有关,因为多次提交将会导致不必要的重复事务。 控制视图访问

在一些情况下,资源被限制为完全不允许某些用户访问。有几个方法可以做到这一点。一个方法是加入应用逻辑到处理控制器或者视图的程序中,禁止某些用户访问。另一个方案是设置运行时的系统,对于一些资源,仅允许经由另一个应用资源内部调用。在这种情形,对于这些资源的访问必须被通过另一个表现层的应用资源进行,例如一个servlet控制器。对于这些受限制的资源不允许通过一个浏览器直接调用。

处理这个问题的一个常见方法是使用一个控制器来作为该类访问控制的一个委托者。另一个常见的方式是在一个视图中置入一个保护设置。我们这里主要讨论基于视图的控制策略。在考虑选择何种方式来控制访问之前,我们首先来描述一下这些策略。 在视图中置入保护逻辑:

对于在一个视图的处理中置入一个保护逻辑,有两个常见的应用。一个是防止访问整个的资源,而另一个是限制访问部分的资源。

在每个视图中包含一个All-or-Nothing保护

在一些情况下,置入到视图处理代码中的逻辑以all-or-nothing的模式允许或者拒绝访问。也就是说,这个逻辑限制某个特别的用户访问一个特别的视图。通常这一类型的保护最好封装到一个中央化的控制器中,这样便于集中化管理。如果只有很少的页面需要防护,那么可以使用这个策略。通常这个情形都是发生在一个非技术人员需要更新网站一小部分的静态文件。如果客户仍然需要登陆到网站来浏览这些页面,那么只需要在每个页面的顶部加入一个自定义的tag(标记)就可以做到控制访问。下面的例子所示。

在每个视图中包含一个All-or-Nothing保护

<%@ taglib uri=\ prefix=\> <corePatterns:guard/> 给视图的某些部分加入保护

-45-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

在其它情况下,置入到视图处理代码的逻辑可拒绝访问一个视图的某些部分。这个策略可以和上面的all-or-nothing策略一起使用。为说明这一点,我们这里使用控制访问一个建筑物中的一个房间作类比。all-or-nothing的保护策略告诉用户是否可以进入房间,而第二个保护策略则是告诉用户在进入房间后,允许他们看到什么东西。以下就是一些你可以利用这个策略的例子。 根据用户的角色决定是否显示视图的某些部分

根据用户的角色,视图的某部分可能不显示。例如,一个经理在收看管理信息时,他可以访问到其员工的子视图,而作为一个员工,他只可以看到自己组织的信息,而不可以访问其它信息,如例子3.2所示。

根据用户的角色,部分的视图不显示

<%@ taglib uri=\ prefix=\> <HTML>

<corePatterns:guard role=\>

<b>This should be seen only by managers!</b> <corePatterns:guard/> </HTML>

根据系统的状态或者错误情形不显示部分的视图

根据系统的环境,显示的规划可以被修改。例如,如果用户使用的是一个单CPU的硬件设备,那么使用多个CPU的部分设备就可以不显示。 根据配置控制资源访问

要限制某个客户直接访问一个特别的视图,你可以配置表现层只有通过内部的资源才可以访问到这些资源,例如一个使用RequestDispatcher的servlet控制器。此外,你还可以使用Web容器中内置 的安全技术,根据servlet2.2或者以后的规范。安全限制被定义在称为web.xml的配置描述文件中(deployment descriptor)。

basic和form-based的认证方法在Servlet规范中也有描述。在此我们不打算重复这个规范,你可以到以下网址去查看当前规范的细节(http://java.sun.com/products/servlet/index.html)。 你已经明白了加入安全限制到你的应用时会有什么用处,我们简要讨论了这个问题并且介绍了如何通过配置令它和all-or-nothing保护相关。最后,我们描述了一个简单和常用的方法作为all-or-nothing保护,以限制一个资源的访问。

4.5数据库设计

数据库设计是系统设计中非常重要的一个环节。数据库是一切系统设计的基础,通俗地说,数据库设计就像高楼大厦的根基一样,如果设计不合理,不完善,将在系统开发工程中,甚至在后期系统维护,功能变更和功能拓展时引起较多的问题,严重时甚至要重新设计项目,重新做大量已经完成的工作[26]。

根据功能模块划分的结果可知,本系统的用户有系统用户和一般用户。系统用户可以实现系统内的全部操作,一般用户只能受限操作。因此在本系统中需要创建用户数据实体用于记录用户信息,以及查询信息。根据图4.1 网站后台管理系统用例图可知,其它实体包括图片实体,模块实体,文章实体,链

-46-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

接实体等,由于系统具有拓展功能,拓展的功能未知,所以这些实体根据需要临时创建。以上这些实体是基本的数据实体,部分实体间存在关联关系,这就意味着需要注意级联关系,这是一个较复杂的数据库。下面将要设计数据库 ,在数据库表设计过程中,一般要遵循以下原则[27]。

(1)数据库的一个表最好只存储一个实体或者对象的相关信息,不同的实体最好存储在不同的数据表中,如果实体可能再划分,实体的划分原则是最好能够比当前系统要开发实体复杂度小。 (2)数据表的信息结构一定要合适,表的字段数量一般不要过度。 (3)扩充信息和动态变化的信息一定要分别放在不同表里。

4.5.1数据库表逻辑关系设计及物理模型设计

数据库是项目的基础设施,数据库表设计合理,关系适当,对项目开发非常重要,本网站后台管理系统的数据库表逻辑设计如图4.15。

模块信息表PK文章信息表PK 文章编号文章标题1文章标题2模块id文章作者文章内容文章建立日期文章浏览次数文章是否被删除删除时间用户id 模块id模块名模块内容模块类型用户操作记录表用户信息表PK 用户id号用户名用户口令用户性别用户地址用户Email用户电话创建用户时间图片信息表PK 图片id图片名称图片地址图片内容图片建立时间图片是否删除图片删除时间PK 用户操作表id操作内容操作时间操作的IP地址操作用户名字用户id连接控制表PK 链接id链接名链接到的地址链接到的图片链接是否删除链接删除时间图片id

图4.15 数据库表逻辑关系设计

图4.16是网站后台管理系统中用到的所有表对应的物理数据模型,使用PowerDesiner设计,使用

-47-

北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

本工具的好处是可以概念模型,面向对象模型,物理模型等多个模型中自由转换。而且可以生成代码外壳。

articlearticle_iduser_idmodule_idarticle_title1article_title2article_authorarticle_contentarticle_createtimearticle_browseisdeletedelete_timevarchar(32)varchar(32)varchar(32)varchar(100)varchar(100)varchar(32)textdateintintdatemodulemodule_idmodule_nameFK_ARTICLE_REFERENCE_MODULEmodule_contenttypevarchar(32)varchar(100)varchar(100)intuser_infouser_iduser_nameFK_ARTICLE_REFERENCE_USER_INFuser_passworduser_sexuser_addressuser_emailuser_teluser_createtimeFK_USER_OPE_REFERENCE_USER_INFpopdom_idvarchar(32)varchar(32)varchar(32)charvarchar(100)varchar(32)varchar(32)datevarchar(32)user_operationuser_operation_iduser_idoperation_contentoperation_timeoperation_ipuser_namevarchar(32)varchar(32)varchar(32)datevarchar(32)varchar(32)FK_USER_INF_REFERENCE_POPEDOMpopedomlinklink_idlink_namelink_urllink_pictureisdeletedelete_timepicture_idpopdom_idvarchar(32)popdom_namevarchar(32)popdom_contentvarchar(32)varchar(32)varchar(100)varchar(100)varchar(100)intpicturedatevarchar(32)FK_LINK_REFERENCE_PICTUREpicture_idvarchar(32)Picture_namevarchar(100)picture_urlvarchar(100)picture_contentlong binarypicture_createtimedateflux_countisdeleteintdelete_timedatecount_idvarchar(32)count_numberintcount_datedate 图4.16 网站后台管理系统数据库物理模型

4.5.2数据库表关系设计

首先要创建一个数据库,本系统使用的是mysql的辅助图形化界面工具mysql-front。这几张表的字段说明如表4.1~4.5所示。

表4.1 用户信息表

序 号 1 2 user_id user_name -48-

字 段 含 义 用户id 用户名 varchar(32) varchar(32) 类 型 北方民族大学硕士学位论文 开源技术Struts,Spring,Hibernate在MIS开发中的应用研究

3 4 5 6 7 8 9 user_password user_sex user_address user_email user_tel user_create_time user_last_login_time 用户口令 性别 住址 Email 电话 创建时间 最近登录时间 表4.2图片信息表

varchar(32) char(2) varchar(100) varchar(20) varchar(20) datetime datetime 序 号 1 2 3 4 5 6 7 8 字 段 picture_id picture_name picture_url picture_content picture_display_place picture_create_time` `isdelete` `delete_time` 含 义 图片id 图片名 图片来源地址 图片内容 图片显示位置 创建图片时间 图片是否被删除 删除时间 表4.3 文章信息表

varchar(32) 类 型 varchar(255) varchar(255) longblob varchar(32) datetime int(2) datetime 序 号 1 2 3 4 5 6 7 8 9 10 user_id module_id article_id 字 段 含 义 用户id 模块id 文章id 文章标题1 文章标题2 文章作者 文章内容 文章建立时间 最后修改文章时间 文章浏览次数 -49-

类 型 varchar(32) varchar(32) varchar(32) varchar(100) varchar(100) varchar(32) longtext datetime datetime int(11) article_title1 article_title2 article_author article_content article_create_time article_last_change_time article_browse

本文来源:https://www.bwwdw.com/article/52up.html

Top