1.3 J2EE轻量级框架Struts+Spring+Hibernate
1.3.1 轻量级J2EE架构技术
轻量级是指一种开发方法,指简化的编程模型和更具响应能力的容器等,轻量级开发旨在消除传统API的复杂性与限制,同时,采用轻量级的方式进行开发也缩短了应用程序的开发周期与部署上的复杂度。
轻量级的软件开发不强迫业务对象遵循平台接口,可以使用POJO来实现业务。IOC模式在轻量级的领域中起着巨大的作用,它的引入解决了对象依赖性的问题,有助于简化代码、将业务逻辑与基础架构分离,使应用程序高内聚、低耦合,从而使应用程序更易于维护,提高了开发效率,也使框架响应能力提高,达到了简化的目的。
为解决经典架构中的一系列问题,J2EE逐渐流行起非EJB架构的“轻量级容器”,它与EJB架构一样,由容器管理业务对象,然后再组织整个架构,但是业务对象运行在“轻量级容器”中。轻量级容器不和J2EE绑定,既可运行在Web容器中,也可运行在一个标准应用程序中。
轻量级容器的启动开销很小,而且无需EJB部署,提供了一种管理、定位业务对象的方法,不必使用JNDI寻址、定制服务器之类的额外辅助,并为应用对象提供注册服务。轻量级容器较EJB功能强大,避免了容器强制业务对象采用特定的接口,降低了侵入性。
1.3.2 认识SSH
SSH在J2EE项目中表示了3种框架,即Spring + Struts +Hibernate 。
在基于J2EE的应用程序开发过程中,难于控制开发进度、开发效率低下、部署环境复杂、维护困难等问题层出不穷。对于中小企业,使用完整的J2EE实现过于庞大,最终常导致开发的失败。
J2EE轻量级框架Struts+Spring+Hibernate应运而生,并逐渐流行,轻量级是和以EJB为核心的复杂框架对比而言的。轻量级框架致力于提供最简单的组件来构筑Web应用系统,Spring是典型的一种轻量级架构,越来越多的开发人员开始关注并使用这种架构。通过Spring组合其他专一的开源产品,如表示层的Struts、持久对象层的Hibernate,来构建应用系统,实现J2EE简单化编程。如图1-12所示。
图1-12 Struts+Spring+Hibernate框架体系结构图
整体框架和业务层用Spring,表示层用Struts,而持久层用Hibernate。Spring是一个开放的框架,不要求一定要用Spring自己的解决方案。Struts作为表示层的成熟技术已经在市场上广泛应用,可以很好地和Spring技术中间层紧密结合,Struts可以使用Spring提供的事务处理等特性,所以选择Struts作为框架的表示层技术。Spring按照资源管理的方法提供和Hibernate的集成及DAO(Data Access Object)实现和事务策略支持,Spring通过IOC(控制反转)机制和Hibernate集成,Spring能够很好地支持开发人员选择O/R映射技术。
1.Struts
如图1-13所示,Struts对Model、View和Controller都提供了对应的组件。 ActionServlet类是Struts的核心控制器,负责拦截来自用户的请求。Action类通常由用户提供,该控制器负责接收来自ActionServlet的请求,并根据该请求调用模型的业务逻辑方法处理请求,然后将处理结果返回给JSP页面显示。
图1-13 Struts 框架结构
(1)Model部分。Model部分由ActionForm和JavaBean组成,其中ActionForm用于封装用户的请求参数,将其封装成ActionForm对象,该对象被ActionServlet转发给Action,Action根据ActionForm里面的请求参数处理用户的请求。JavaBean则封装了底层的业务逻辑,包括数据库访问等。
(2)View部分。该部分采用JSP实现。 Struts提供了丰富的标签库,通过标签库可以减少脚本的使用,自定义的标签库可以实现与Model的有效交互,并增加了现实功能。对应图中的JSP部分。
(3)Controller组件。Controller组件由两个部分组成——系统核心控制器和业务逻辑控制器。
系统核心控制器,对应图1-13中的ActionServlet。该控制器由Struts框架提供,继承HttpServlet类,因此可以配置成标注的Servlet。该控制器负责拦截所有的HTTP请求,然后根据用户请求决定是否要转给业务逻辑控制器。业务逻辑控制器负责处理用户请求,本身不具备处理能力,而是调用Model来完成处理,对应Action部分。
Struts的优点在于实现了MVC模式,将Web系统各组件进行了良好的分工合作;Spring的特性在于IoC机制;Hibernate的长处在于数据持久化。要结合这3种技术的优点,采取的策略有许多种,如可以将Hibernate的sessionFactory、数据操作组件交给Spring容器来管理,必要时进行注入处理;可以将Struts的Action交给Spring容器来管理,而不必再在Action中声明业务逻辑操作的组件。
2.Spring
Spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架。Spring的目的是解决企业应用开发的复杂性,它使用基本的JavaBean代替EJB,并提供更多的企业应用功能,可在任何Java中应用。
Spring框架是一个分层架构,由7个定义良好的模块组成。Spring模块构建在核心容器之上,核心容器定义了创建、配置和管理Bean的方式,其体系结构如图1-14所示。
图1-14 Spring 框架体系结构
从大小与开销两方面而言,Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的,Spring应用中的对象不依赖于Spring的特定类。
(1)控制反转。Spring通过一种称做控制反转(IOC)的技术促进了松耦合。当应用了IOC时,一个对象依赖的其他对象会通过被动的方式传递进来,而不是这个对象自己创建或查找依赖对象。可以认为IOC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
(2)面向切面。Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(如审计(Auditing)和事务(Transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑,仅此而已。它们并不负责(甚至是意识)其他的系统级关注点,如日志或事务支持。
(3)容器。Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个Bean如何被创建,基于一个可配置原型(Prototype),你的Bean可以创建一个单独的实例或每次需要时都生成一个新的实例,以及它们是如何相互关联的。然而, Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
(4)框架。Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等),将应用逻辑的开发留给了你。
所有Spring的这些特征使你能够编写更干净、更可管理、更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
3.Hibernate
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲地使用对象编程思维来操纵数据库。Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序中使用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任,Hibernate的工作原理如图1-15所示。
图1-15 Hibernate工作原理
Hibernate的核心接口一共有5个,分别为:Session、SessionFactory、Transaction、Query和Configuration。这5个核心接口在任何开发中都会用到。通过这些接口,不仅可以对持久化对象进行存取,还能够进行事务控制。下面对这五个核心接口分别加以介绍。
(1)Session接口。Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,它包含了很多常见的SQL语句。)。但需要注意的是,Session对象是非线程安全的。同时,Hibernate的Session不同于JSP应用中的HttpSession。这里,当使用Session这个术语时,其实指的是Hibernate中的Session,而以后会将HttpSesion对象称为用户Session。
(2)SessionFactory接口。SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是,SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就足够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。
(3)Configuration接口。Configuration接口负责配置并启动Hibernate和创建SessionFactory对象。在Hibernate的启动的过程中,Configuration类的实例首先定位映射文档位置、读取配置,然后创建SessionFactory对象。
(4)Transaction接口。Transaction接口负责事务相关的操作。它是可选的,开发人员也可以设计编写自己的底层事务处理代码。
(5)Query和Criteria接口。Query和Criteria接口负责执行各种数据库查询。它可以使用HQL语言或SQL语句两种表达方式。
1.3.3 SSH框架结构模型
轻量级J2EE开发平台承袭J2EE基于组件的多层应用模型。它在综合考虑用户界面、业务逻辑、数据存储的功能和逻辑的基础上,根据应用功能和应用逻辑划分层次,明确责任,实现松耦合的组件式架构。在技术层面上,使用Spring规划轻量级J2EE应用平台时,可以按职责将应用分成四层:域模型层、业务层、持久层、表现层。Spring作为业务层成为连接其他层之间的枢纽,允许层之间以松耦合的方式向其他层暴露功能而不必依赖特定的技术。其他的层分别负责不同方面的应用职责,对功能进行封装,明确地定义接口在层与层之间通信。SSH框架结构模型如图1-16所示。
图1-16 SSH框架结构模型
(1)域模型层。在一个应用中,首先需要使用一组对象来表达现实世界中的概念。传统的方法是使用DTO(数据传输对象)将数据库中的数据转化为问题域中的对象,在应用开发时需要额外的编码。引入域模型层,借助一组业务对象,实现问题域和计算机域的阻抗匹配,替代系统中数据传输对象:用对象的方式描述现实世界,真实地反映现实世界对象(如订单、产品等),可以减少额外的编码,便于理解,降低代码管理难度。此外,域模型层的业务对象在各层之间进行数据传递和数据转化,作为各层之间数据通信的载体,能够最大化地降低系统间数据传递的开销,而且业务对象代表了现实世界中的对象,使得系统在进行扩充、重构时,各子系统间数据传递部分不会受到影响。
(2)表现层。表现层是用户直接和软件交互的部分。表现层向用户展现软件系统的功能,响应用户的请求,并向用户呈现处理的结果。因而如果用户界面不甚高效,那么无论其他部分多么优良,都将于事无补。成熟的方式是采用MVC(模型—视图—控制器)模式组织表现层,分离用户界面代码(视图)与应用数据和业务逻辑(模型),然后使用控制器匹配视图和模型,减少数据表现、数据描述和应用操作的耦合,最终得到响应快速、界面美观的表现层。
(3)持久层。持久层位于应用的一端,负责将数据持久化。数据持久层的设计目标是为整个项目提供一个高层、统一、安全、并发的数据持久机制,将复杂的业务逻辑和数据逻辑分离,使系统的紧耦合关系转化为松耦合关系,完成对各种数据进行持久化的编程工作,并为系统业务逻辑层提供服务。数据持久层提供了数据访问逻辑,能够使程序员避免手工编写程序访问数据持久层,使其专注于业务逻辑的开发,并且能够在不同项目中重用已有实现,简化数据增、删、查、改等功能的开发过程,同时又不丧失多层结构的天然优势,继承延续J2EE特有的可伸缩性和可扩展性。
(4)业务层。从应用分层上来看,业务层位于中间层次。业务层又称为服务层。合理地构建业务层,可以降低层次之间的耦合度,增加业务的可伸缩性和灵活性。借助Spring的IOC容器,使用配置文件管理其他各个层次的依赖关系、装配业务组件,降低层次之间的耦合,实现插件式编程;借助Spring的AOP实现,集中处理系统中的企业级服务,如事务管理、日志管理等,使代码更加简洁,增强复用性,提高开发效率。
在应用开发中,域模型层将现实世界对象抽象为域对象,持久层负责将域对象和数据库对应起来,业务层调用持久层的数据逻辑。执行应用逻辑,处理表现层的请求并以适当的方式向用户展示处理结果。
Struts作为前台控制框架简化了程序的开发,使页面设计人员和Java程序员达到有效的分离,使项目可扩展性大大增强,提升了开发效率,降低了维护成本。
Spring作为一个应用于所有层面的综合框架,具有强大的应用功能及灵活性,非常适合作为一些大规模软件项目的底层平台。
Hibernate作为后台ORM(Object Relation Mapping)持久层框架的轻量级组件,对持久层进行了轻量级封装,降低了程序的复杂度,易于调试,减轻了程序员的负担,具有很强的扩展性。并且API开放,可自行对Hibernate源码进行修改,扩展所需的功能。
1.3.4 SSH架构轻量级Web应用
SSH架构是当前非常流行的架构,很多金融、电信项目和大型门户网站均选择该架构作为业务支撑的架构,开发流程已经非常成熟。如图1-17所示,SSH由3个开源的框架组合而成,表现层用Struts,Struts充当视图层和控制层;业务层用Spring,Spring通过控制反转让控制层间接调用业务逻辑层;持久层用Hibernate,Hibernate充当数据访问层。每个层在功能上职责明确,不应该与其他层混合,各层通过通信接口相互联系。
图1-17 基于Struts、Spring和Hibernate的整合框架
(1)Struts负责Web层。
ActionFormBean接收网页中表单提交的数据,然后通过Action进行处理,再Forward到对应的网页,在struts-config.xml中定义<action-mapping>,ActionServlet会加载。
(2)Spring负责业务层管理,即Service(或Manager)。
Service为Action提供统计的调用接口,封装持久层的DAO,并集成了Hibernate,Spring可对JavaBean和事物进行统一管理。
(3)Hibernate负责持久化层,完成数据库的CRUD操作。
Hibernate提供OR/Mapping,它有一组hbm.xml文件和POJO,是与数据库中的表相对应的,然后定义DAO,这些是与数据库打交道的类,它们会使用PO。
在Struts+Spring+Hibernate的系统中,对象的调用流程是:JSP→Action→Service→DAO→Hibernate,数据的流向是ActionFormBean接受用户的数据,Action将数据从ActionFormBean中取出,封装成VO或PO,再调用业务层的Bean类,完成多种业务处理后再Forward。业务层Bean收到这个PO对象之后,会调用DAO接口方法,进行持久化操作。