标签:
http://blog.csdn.net/slnqnd/article/details/1772910/
Struts2.0 +Hibernate 3.2 +Spring 2.0
一. Struts
1.定义
它是使用 servlet 和 JavaServer Pages 技术的一种 Model-View-Controller 实现, 可帮助您控制Web 项目中的变化并提高专业化水平。“模型-视图-控制 器”(MVC) 就是用来帮助您控制变化的一种设计模式。MVC 减弱了业务逻辑接口和数据接口之间的耦合。Struts 是一种 MVC 实现,它将 Servlet 2.2 和 JSP 1.1 标记(属于 J2EE 规范)用作实现的一部分。(http://www-128.ibm.com/developerworks/cn/java/j-struts/index.html)
2.结构
在 struts+hibernate+spring 三层结构模型中处于表现层
Struts框架的组件结构图
(http://www-128.ibm.com/developerworks/cn/java/l-struts-mvc/index.html)
3.业务流程及核心原理
Struts 对MVC框架提供了对开发MVC系统的底层支持,它采用的主要技术是Servlet,JSP和custom tag library。
(http://www-128.ibm.com/developerworks/cn/java/l-struts-mvc/index.html)
Struts uml 图
作为一个MVC的框架,Struts对Model、View和Controller都提供了对应的实现组件,对应上面的UML图,分别进行介绍,并且看看它们是如何结合在一起的。
2. Model: 模型包含应用程序的核心功能。模型封装了应用程序的状态。有时它包含的唯一功能就是状态。它对视图 或控制器一无所知。MVC系统中的Model部分从概念上可以分为两类--系统的内部状态,和改变系统状态的动作。Struts为Model部分提供了 Action和ActionForm对象:所有的Action处理器对象都是开发者从Struts的Action类派生的子类。Action处理器对象封 装了具体的处理逻辑,调用业务逻辑模块,并且把响应提交到合适的View组件以产生响应。Struts提供的ActionForm组件对象,它可以通过定 义属性描述客户端表单数据。开发者可以从它派生子类对象,利用它和Struts提供的自定义标记库结合可以实现对客户端的表单数据的良好封装和支 持,Action处理器对象可以直接对它进行读写,而不再需要和request、response对象进行数据交互。通过ActionForm组件对象实 现了对View和Model之间交互的支持。Struts通常建议使用一组JavaBean表示系统的内部状态,根据系统的复杂度也可以使用像 Entity EJB 和 Session EJB等组件来实现系统状态。Struts建议在实现时把"做什么"(Action)和"如何做"(业务逻辑)分离。这样可以实现业务逻辑的重用。
3.View:视图提供模型的表示。它是应用程序的 外观。视图可以访问模型的读方法,但不能访问写 方法。此外,它对控制器一无所知。当更改模型时,视图应得到通知。 Struts应用中的View部分是通过JSP技术实现的。Struts提供了自定义 的标记库可以使用,通过这些自定义标记可以非常好地和系统的Model部分交互,通过使用这些自定义标记创建的JSP表单,可以实现和Model部分中的 ActionForm的映射,完成对用户数据的封装,同时这些自定义标记还提供了像模板定制等多种显示功能。
Struts框架的处理流程清楚的体现了MVC系统的特点,简单的Struts组件结构。Struts Controller ActionServlet处理客户请求,利用配置的ActionMapping对象把请求映射到Action处理器对象进行处理。Action处理对象 访问ActionForm中的数据,处理和响应客户请求,它还调用后台的Bean组件,这些组件封装了具体的业务逻辑。Action处理器对象根据处理结 果通知Controller,Controller进行下一步的处理。
总结一下各类:
(http://www-128.ibm.com/developerworks/cn/java/j-struts/index.html)
Command (ActionServlet) 与 Model (Action & ActionForm) 之间的关系的 UML 图
ActionServlet 类
Struts 的控制器是将事件(事件通常是 HTTP post)映射到类的一个 servlet。控制器使用配置文件以使您不必对这些值进行硬编码。ActionServlet 是该 MVC 实现 的 Command 部分,它是这一框架的核心。 ActionServlet (Command) 创建并使 用 Action 、 ActionForm 和ActionForward 。如前所述, struts-config.xml 文件配置 该 Command。在创建 Web 项目时,您将扩展 Action 和 ActionForm 来解决特定的问题。文件 struts- config.xml 指示ActionServlet 如何使用这些扩展的类。这种方法有几个优点:
可以通过扩展 ActionServlet 来添加 Command 功能。
ActionForm 类
ActionForm 维护 Web 应用程序的会话状态。 ActionForm 是一个抽象类,必须为每个输入表单模型创建该类的子类。当我说 输入表单模型 时,是指 ActionForm 表示的是由 HTML 表单设置或更新的一般意义上的数据。例如,您可能有一个由 HTML 表单设置的 UserActionForm。Struts 框架将执行以下操作:
注:
Action 类
Action 类是业务逻辑的一个包装。 Action 类的用途是将 HttpServletRequest 转换为业务逻辑。要使用 Action ,请创建它的子类并覆盖 process() 方法。
ActionServlet (Command) 使用 perform() 方法将参数化的类传递 给 ActionForm 。仍然没有太多讨厌的 request.getParameter() 调用。当事件进展到这一步时,输入表单数据(或 HTML 表单数据)已被从请求流中提取出来并转移到 ActionForm 类中。
注:扩展 Action 类时请注意简洁。 Action 类应该控制应用程序的流程,而不应该控制应用程序的逻辑。通过将业务逻辑放在单独的包或 EJB 中,我们就可以提供更大的灵活性和可重用性。
考虑 Action 类的另一种方式是 Adapter 设计模式。 Action 的用途是“将类的接口转换为客户机 所需的另一个接口。Adapter 使类能够协同工作,如果没有 Adapter,则这些类会因为不兼容的接口而无法协同工作。”(摘自 Gof 所著 的 Design Patterns - Elements of Reusable OO Software)。本例中的客户机 是 ActionServlet ,它对我们的具体业务类接口一无所知。因此,Struts 提供了它能够理解的一个业务接口,即 Action 。通过 扩展 Action ,我们使得我们的业务接口与Struts 业务接口保持兼容。(一个有趣的发现是, Action 是类而不是接 口)。 Action 开始为一个接口,后来却变成了一个类。真是金无足赤。)
Error 类
UML 图(图 6)还包括 ActionError 和 ActionErrors 。 ActionError 封 装了单个错误消息。 ActionErrors 是 ActionError 类的容器,View 可以使用标记访问这些类。 ActionError 是 Struts 保持错误列表的方式。
图 7. Command (ActionServlet) 与 Model (Action) 之间的关系的 UML 图
ActionMapping 类
输入事件通常是在 HTTP 请求表单中发生的,servlet 容器将 HTTP 请求转换为 HttpServletRequest 。控制器查看输入事件并将请求分派给某个 Action 类。 struts-config.xml 确 定 Controller 调用哪个 Action 类。 struts-config.xml 配置信息被转换为一组 ActionMapping , 而后者又被放入 ActionMappings 容器中。(您可能尚未注意到这一点,以 s结尾的类就是容器)
ActionMapping 包含有关特定事件如何映射到特定 Action 的信 息。 ActionServlet(Command) 通过 perform() 方法将 ActionMapping 传递给 Action 类。这样 就使 Action可访问用于控制流程的信息。
ActionMappings
ActionMappings 是 ActionMapping 对象的一个集合。
4.利用Struts框架开发MVC系统要做的工作
(http://www-128.ibm.com/developerworks/cn/java/l-struts-mvc/index.html)
由于Struts已经为我们提供了一个非常好的MVC框架,我们利用Struts开发MVC系统时可以大大加快开发的速度。在开发时可以采用的一个开发流程如下:
具体在使用Struts框架时,对应各个部分的开发工作主要包括:
下面对这两个配置文件做一些介绍:
web.xml文件的配置:
web应用中的web.xml是第一个要配置的地方,它描述了系统的Controller对象。在web.xml中增加如下标记
<servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>application</param-name> ?????? </servlet> |
说明:这个servlet对象就是Struts提供的Controller,还可以为它指定初始化参数,比如对系统应用属性的支持。
<servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servelt-mapping> |
说明:实现客户请求的url信息和服务器端具体处理的映射关系。
<taglib> <taglib-url>/WEB-INF/struts-bean.tld</taglib-url> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> ??????? |
说明:添加对Struts提供的应用所使用的自定义标记库的引用。
struts-config.xml文件的配置:
struts-config.xml是用于建立Controller和Model之间的关系的。它描述了Controller所使用的把请求对应到具体处理的法则,同时它还描述了客户提供的数据与ActionForm组件的对应映射关系。
在struts-config.xml中增加如下标记
<form-beans> <form-bean name="loginForm" type="loginForm" /> </form-beans> |
说明:<form-bean>标记描述一个具体的ActionForm子类对象,通过它和JSP页面中的自定标记的结合使用可以实现ActionForm和View之间的数据映射。
<action-mappings> <action path="/login" type="loginAction" name="loginForm" input="/login.jsp" ??? /> </action-mappings> |
说明:<action-mappings>标记描述了请求和处理的一对一映射关系。input和path属 性唯一的标记了客户端的一个请求,name属性描述封装客户端的数据的ActionForm子类对象。Type属性描述处理这个请求的Action子类对 象。
通过对两个配置文件的配置,把Struts框架中MVC的各个部分联系起来,实现一个真正的MVC系统。
5. Struts 的优点(http://www-128.ibm.com/developerworks/cn/java/j-struts/index.html)
l JSP 标记机制的使用
标记特性从 JSP 文件获得可重用代码和抽象 Java 代码。这个特性能很好地集成到基于 JSP的开发工具中,这些工具允许用标记编写代码。
l 标记库
为什么要另发明一种轮子,或标记库呢?如果您在库中找不到您所要的标记,那就自己定义吧。此外,如果您正在学习 JSP 标记技术,则 Struts 为您提供了一个起点。
l 开放源码
您可以获得开放源码的全部优点,比如可以查看代码并让使用库的每个人检查代码。许多人都可以进行很好的代码检查。
l MVC 实现样例
如果您希望创建您自己的 MVC 实现,则 Struts 可增加您的见识。
l 管理问题空间
分治是解决问题并使问题可管理的极好方法。当然,这是一把双刃剑。问题越来越复杂,并且需要越来越多的管理。
6.Struts的缺点(http://www-128.ibm.com/developerworks/cn/java/j-struts/index.html)
二. Hibernate
1.定义
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序实用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP, 完成数据持久化的重任。Hibernate 框架就允许Java中的对象-关系的持久性和查询服务。Hibernate 对已经熟悉了SQL 和JDBC API的Java开发者来或具有中度的学习曲线。Hibernate 的持久对象基于POJO和Java 群集(collections)。
2.Hibernate的体系结构及工作原理
(http://blog.csdn.net/hina1115/archive/2005/10/18/508717.aspx)
1.Hibernate 的初始化.
读取Hibernate 的配置信息-〉创建Session Factory
1)创建Configeration类的实例。
它的构造方法:将配置信息(Hibernate config.xml)读入到内存。
一个Configeration 实例代表Hibernate 所有Java类到Sql数据库映射的集合。
2)创建SessionFactory实例
把Configeration 对象中的所有配置信息拷贝到SessionFactory的缓存中。
SessionFactory的实例代表一个数据库存储员源,创建后不再与Configeration 对象关联。
缓存(cache):指Java对象的属性(通常是一些集合类型的属性--占用内存空间。
SessionFactory的缓存中:Hibernate 配置信息。O/R映射元数据。
缓存-大:重量级对象 小:轻量级对象
3)调用SessionFactory创建Session的方法
a.用户自行提供JDBC连接。
Connection con=dataSource.getConnection();
Session s=sessionFactory.openSession(con);
b.让SessionFactory提供连接
Session s=sessionFactory.openSession();
4)通过Session 接口提供的各种方法来操纵数据库访问。
3.Hibernate 的缓存体系
一级缓存:
Session 有一个内置的缓存,其中存放了被当前工作单元加载的对象。
每个Session 都有自己独立的缓存,且只能被当前工作单元访问。
二级缓存:
SessionFactory的外置的可插拔的缓存插件。其中的数据可被多个Session共享访问。
SessionFactory的内置缓存:存放了映射元数据,预定义的Sql语句。
4. Hibernate 中Java对象的状态
1.临时状态 (transient)
特征:
a.不处于Session 缓存中
b.数据库中没有对象记录
Java如何进入临时状态
a.通过new语句刚创建一个对象时
b.当调用Session 的delete()方法,从Session 缓存中删除一个对象时。
2.持久化状态(persisted)
特征:
a.处于Session 缓存中
b.持久化对象数据库中设有对象记录
c.Session 在特定时刻会保持二者同步
Java如何进入持久化状态
a.Session 的save()把临时-》持久化状态
b.Session 的load(),get()方法返回的对象
c.Session 的find()返回的list集合中存放的对象
d.Session 的update(),saveOrupdate()使游离-》持久化
3.游离状态(detached)
特征:
a.不再位于Session 缓存中
b.游离对象由持久化状态转变而来,数据库中可能还有对应记录。
Java如何进入持久化状态-》游离状态
a.Session 的close()方法
b.Session 的evict()方法,从缓存中删除一个对象。提高性能。少用。
5. Hibernate的优点
(http://www.ibm.com/developerworks/cn/opensource/os-lightweight6/)
Hibernate 有一个灵活的映射机制。一些场景比其他场景付出更多的努力来映射,但是如果您能在一个关系模式中表 示它,那么也许在 Hibernate 中有一种方法来映射到它。Hibernate 的性能比大多数的框架要好而且还在不断提升。文档很优秀,收 购 JBoss 后,支持也在改善。JBoss 小组也把Hibernate 放置在一个合适的位置以抢在竞争者之前实现 JSR 200 持久性标准。
对 Hibernate 来说,与其他开放源码框架和商业框架的集成比其他的替代框架要好。一般来说,Spring 与 Hibernate 的集成比与其他任何一个持久性框架的集成要好。
Hibernate 是一个创新的框架。在推动与 SQL 的集成上,它比大多数其他的框架走的更远。它具有一些其他框架不支持的特性,比如会话过滤。还有一支强大的公共和商业开发人员团队为其工作。
6. Hibernate的缺点
由于其灵活性,相同的问题可以有多种解决方案,无法决定选择何种方案。
Hibernate 比替代框架更加难以管理。
最后,Hibernate 不像一些持久性框架那么专业。例如,对于一些边缘情况,比如管理懒散加载,Kodo JDO 有非常好的错误信息和更加可预测的行为。
三.Spring
1. 定义
Spring是轻量级的J2EE应用程序框架。Spring的核心是个轻量级容器(container),实现了IoC(Inversion of Control)模式的容器,Spring的目标是实现一个全方位的整合框架,在Spring框架下实现多个子框架的组合,这些子框架之间彼此可以独立, 也可以使用其它的框架方案加以替代,Spring希望提供one-stop shop的框架整合方案 。Spring的核心是个轻量级容器(container),实现了IoC(Inversion of Control)模式的容器,Spring的目标是实现一个全方位的整合框架,在Spring框架下实现多个子框架的组合,这些子框架之间彼此可以独立, 也可以使用其它的框架方案加以替代,Spring希望提供one-stop shop的框架整合方案 。
2. Spring框架
(http://www.ibm.com/developerworks/cn/java/wa-spring1/)
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,如图 1 所示。
图 1. Spring 框架的 7 个模块
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心 要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境 (Web 或 EJB)、独立 应用程序、测试环境之间重用。
3. Spring的核心:IOC + AOP
(http://www.ibm.com/developerworks/cn/java/wa-spring1/)
a. IOC
控制反转模式(也称作依赖性介入)的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务。容器 (在 Spring框架中是 IOC 容器) 负责将这些联系在一起。
在典型的 IOC 场景中,容器创建了所有对象,并设置必要的属性将它们连接在一起,决定什么时间调用方法。下表列出了 IOC 的一个实现模式。
类型1 |
服务需要实现专门的接口,通过接口,由对象提供这些服务,可以从对象查询依赖性(例如,需要的附加服务) |
类型2 |
通过 JavaBean 的属性(例如 setter 方法)分配依赖性 |
类型3 |
依赖性以构造函数的形式提供,不以 JavaBean 属性的形式公开 |
Spring 框架的 IOC 容器采用类型 2 和类型3 实现。
b. AOP
面向方面的编程,即 AOP,是一种编程技术,它允许程序员对横切关注点或横切典型的职责分界线的行为(例如日志和事务管理)进行模块化。AOP 的核心构造是方面,它将那些影响多个类的行为封装到可重用的模块中。
AOP 和 IOC 是补充性的技术,它们都运用模块化方式解决企业应用程序开发中的复杂问题。在典型的面向对象开发方式中,可能要将日志记录语句放在所有方法和 Java 类中才能实现日志功能。在 AOP 方式中,可以反过来将日志服务模块化,并以声明的方式将它们应用到需要日志的组件上。当然,优势就是 Java 类不需要知道日志服务的存在,也不需要考虑相关的代码。所以,用Spring AOP 编写的应用程序代码是松散耦合的。
AOP 的功能完全集成到了 Spring 事务管理、日志和其他各种特性的上下文中。
Spring 设计的核心是 org.springframework.beans
包,它的设计目标是与 JavaBean 组件一起使用。这个包通常不是由用户直接使用,而是由服务器将其用作其他多数功能的底层中介。下一个最高级抽象是 BeanFactory
接口,它是工厂设计模式的实现,允许通过名称创建和检索对象。BeanFactory
也可以管理对象之间的关系。
4. Spring的优点
(http://www.imtinewlife.com/BBS/ShowPost.asp?ThreadID=201)
Spring能有效地组织你的中间层对象,无论你是否选择使用了EJB。如果你仅仅使用了Struts或其他的包含了J2EE特有APIs的framework,你会发现Spring关注了遗留下的问题。
. Spring能消除在许多工程上对Singleton的过多使用。根据我的经验,这是一个主要的问题,它减少了系统的可测试性和面向对象特性。
Spring 能消除使用各种各样格式的属性定制文件的需要,在整个应用和工程中,可通过一种一致的方法来进行配置。曾经感到迷惑,一个特定类要查找
迷幻般的属性关键字或系统属性,为此不得不读Javadoc乃至源编码吗?有了Spring,你可很简单地看到类的JavaBean属性。倒置控制的使用
(在下面讨论)帮助完成这种简化。 Spring能通过接口而不是类促进好的编程习惯,减少编程代价到几乎为零。
. Spring被设计为让使用它创建的应用尽可能少的依赖于他的APIs。在Spring应用中的大多数业务对象没有依赖于Spring。
. 使用Spring构建的应用程序易于单元测试。
. Spring能使EJB的使用成为一个实现选择,而不是应用架构的必然选择。你能选择用POJOs或localEJBs来实现业务接口,却不会影响调用代码。
. Spring帮助你解决许多问题而无需使用EJB。Spring能提供一种EJB的替换物,它们适于许多web应用。例如,Spring能使用AOP提供声明性事务而不通过使用EJB容器,如果你仅仅需要与单个的数据库打交道,甚至不需要JTA实现。
. Spring为数据存取提供了一致的框架,不论是使用JDBC或O/Rmapping产品(如Hibernate)。
Spring确实使你能通过最简单可行的解决办法解决你的问题。这些特性是有很大价值的。
5. 总结
Spring的核心即是个IoC/DI的容器,它可以帮程序设计人员完成组件之间的依赖关系注入,使得组件之间的依赖达到最小,进而提高组件的重用
性,Spring是个低侵入性(invasive)的框架,Spring中的组件并不会意识到它正置身于Spring中,这使得组件可以轻易的从框架中脱
离,而几乎不用任何的修改,反过来说,组件也可以简单的方式加入至框架中,使得组件甚至框架的整合变得容易。
Spring最为人重视的另
一方面是支持AOP(Aspect-Oriented
Programming),然而AOP框架只是Spring支持的一个子框架,说Spring框架是AOP框架并不是一件适当的描述,人们对于新奇
的 AOP关注映射至Spring上,使得人们对于Spring的关注集中在它的AOP框架上,虽然有所误解,但也突显了Spring的另一个令人关注的
特色。
Spring也提供MVC Web框架的解決方案,但您也可以将自己所熟悉的MVC
Web框架与Spring解合,像是Struts、Webwork等等,都可以与Spring整合而成为进用于自己的解決方案。Spring也提供其它方
面的整合,像是持久层的整合如JDBC、O/R
Mapping工具(Hibernate、iBATIS)、事务处理等等,Spring作了对多方面整合的努力,故说Spring是个全方位的应用程序框
架。
四.Struts + Hibernate + Spring的综合应用
Struts: 用来作VC部分,即控制和显示作用;
Spring: 用来作数据库操作的事务处理,在配置文件里配置好就OK了;
Hibernate:用来作DAO处理,在此用了Spring的getHibernateTemplate()方法来操作hsql进行数据增删改等操作。
l 项目中 Sttuts、Hibernate、Spring的基本流程
1. Write your business class:
DTO, FormBean, Action, Service Interface, Service Implementation
2. Write JSP Pages
3. struts-config.xml Configuration : FormBean , Action , Forward pages.
4. applicationContext-service.xml Configuration : add your Service Interface and Service Implementation
5. Add your service factory Get method to ServiceFactory.java
6. Build project and Generate the Description file (*.hbm.xml) of DTO
7. applicationContext.xml Configuation : add *.hbm.xml file to applicationContext for O/R
Mapping.
l 用 Struts+Spring+Hibernate组装WEB应用
(http://java.chinaitlab.com/Struts/39925.html)
表现层我们将使用Struts;业务层我们将使用Spring;持久层使用Hibrenate.
图1展示了当这些框架组合在一起时从高层看是什么样子。
图1用Struts, Spring, 和 Hibernate框架构建的概览
应用程序的分层
大多数不复杂的web应 用都能被分成至少4个各负其责的层次。这些层次是:表现层、持久层、业务层、领域模型层。每层在应用程序中都有明确的责任,不应该和其它层混淆功能。每一 应用层应该彼此独立但要给他们之间放一个通讯接口。让我们从审视各个层开始,讨论这些层应该提供什么和不应该提供什么。
表现层
在一个典型的web应用的一端是表现层。很多Java开发者也理解Struts所提供的。然而,太常见的是,他们把像业务逻辑之类的耦合的代码放进了一个org.apache.struts.Action。所以,让我们在像Struts这样一个框架应该提供什么上取得一致意见。这儿是Struts负责的:
为用户管理请求和响应;
提供一个控制器代理调用业务逻辑和其它上层处理;
处理从其它层掷出给一个Struts Action的异常;
为显示提供一个模型;
执行用户接口验证。
这儿是一些经常用Struts编写的但是却不应该和Struts表现层相伴的项目:
直接和数据库通讯,比如JDBC调用;
业务逻辑和与你的应用程序相关的验证;
事务管理;
在表现层中引入这种代码将导致典型耦合和讨厌的维护。
持久层
在典型web应用的另一端是持久层。这通常是使事情迅速失控的地方。开发者低估了构建他们自己的持久层框架的挑战性。一般来说,机构内部自己写的持久层不仅需要大量的开发时间,而且还经常缺少功能和变得难以控制。有几个开源的“对象-关系映射”框架非常解决问题。尤其是,Hibernate框架为java提供了"对象-关系持久化"机制和查询服务。Hibernate对那些已经熟悉了SQL和JDBC API的Java开发者有一个适中的学习曲线。Hibernate持久对象是基于简单旧式Java对象和Java集合。此外,使用Hibernate并不妨碍你正在使用的IDE。下面的列表包含了你该写在一个持久层框架里的代码类型:
查询相关的信息成为对象。Hibernate通过一种叫作HQL的面向对象的查询语言或者使用条件表达式API来做这个事情。 HQL非常类似于SQL-- 只是把SQL里的table和columns用Object和它的fields代替。有一些新的专用的HQL语言成分要学;不过,它们容易理解而且文档做得好。HQL是一种使用来查询对象的自然语言,花很小的代价就能学习它。
保存、更新、删除储存在数据库中的信息。
像Hibernate这样的高级“对象-关系”映射框架提供对大多数主流SQL数据库的支持,它们支持“父/子”关系、事务处理、继承和多态。
这儿是一些应该在持久层里被避免的项目:
业务逻辑应该在你的应用的一个高一些的层次里。持久层里仅仅允许数据存取操作。
你不应该把持久层逻辑和你的表现层逻辑搅在一起。避免像JSPs或基于servlet的类这些表现层组件里的逻辑和数据存取直接通讯。通过把持久层逻辑隔离进它自己的层,应用程序变得易于修改而不会影响在其它层的代码。例如:Hebernate能够被其它持久层框架或者API代替而不会修改在其它任何层的代码。
业务层
在一个典型的web应 用程序的中间的组件是业务层或服务层。从编码的视角来看,这个服务层是最容易被忽视的一层。不难在用户接口层或者持久层里找到散布在其中的这种类型的代 码。这不是正确的地方,因为这导致了应用程序的紧耦合,这样一来,随着时间推移代码将很难维护。幸好,针对这一问题有好几种Frameworks存在。在这个领域两个最流行的框架是Spring和PicoContainer,它们叫作微容器,你可以不费力不费神的把你的对象连在一起。所有这些框架都工作在一个简单的叫作“依赖注入”(也通称“控制反转”)的概念上。这篇文章将着眼于Spring的为指定的配置参数通过bean属性的setter注入的使用。Spring也提供了一个构建器注入的复杂形式作为setter注入的一个替代。对象们被一个简单的XML文件连在一起,这个XML文件含有到像事务管理器、对象工厂、包含业务逻辑的服务对象、和数据存取对象这些对象的引用。
这篇文章的后面将用例子来把Spring使用这些概念的方法说得更清楚一些。业务层应该负责下面这些事情:
处理应用程序的业务逻辑和业务验证;
管理事务;
预留和其它层交互的接口;
管理业务层对象之间的依赖;
增加在表现层和持久层之间的灵活性,使它们互不直接通讯;
从表现层中提供一个上下文给业务层获得业务服务;
管理从业务逻辑到持久层的实现。
领域模型层
最后,因为我们讨论的是一个不是很复杂的、基于web的应用程序,我们需要一组能在不同的层之间移动的对象。领域对象层由那些代表现实世界中的业务对象的对象们组成,比如:一份订单、订单项、产品等等。这个层让开发者停止建立和维护不必要的数据传输对象(或者叫作DTOs),来匹配他们的领域对象。例如,Hibernate允许你把数据库信息读进领域对象的一个对象图,这样你可以在连接断开的情况下把这些数据显示到UI层。那些对象也能被更新和送回到持久层并在数据库里更新。而且,你不必把对象转化成DTOs,因为DTOs在不同的应用层间移动,可能在转换中丢失。这个模型使得Java开发者自然地以一种面向对象的风格和对象打交道,没有附加的编码。
既然每个层是互相作用的,我们就先来创建domain objects。首先,我们要在这些Object中要确定那些是需要持久化的,哪些是提供给business logic,那些是显示接口的设计。 下一步,我们将配置我们的持久层并且定义好Hibernate的OR mappings。然后定义好Business Objects。有了这些组成部分之后,我们将 使用Spring把这些连接起来。 最后,我们提供给Spring一个持久层,从这个持久层里我们可以知道它是如何与业务逻辑层(business service layer)通信的,以及它是怎样处理其他层抛出的异常的。
域对象层(Domain Object Layer)
这层是编码的着手点,我们的编码就从这层开始。 例子中Order 与OrderItem 是一个One—To—Many的关系。 下面就是Domain Object Layer的两个对象:
· com.meagle.bo.Order.java: 包含了一个Order的概要信息
· com.meagle.bo.OrderLineItem.java: 包含了Order的详细信息
好好考虑怎你的package命名,这反应出了你是怎样分层的。 例如 domain objects在程序中可能打包在com.meagle.bo内。 更详细一点将打包在com. meagle.bo的子目录下面。business logic应该从com.meagle.serice开始打包,而DAO 对象应该位于com.meagle.service.dao.hibernate。反应Forms和Actions的 持久对象(presentation classes) 应该分别放在com.meagle.action和com.meagle.forms包。 准确的给包命名使得你的classes很好分割并且易于维护,并且在你添加新的classes时,能使得程序结构上保持上下一致。
持久层的配置(Persistence Layer Configuration)
建立Hibernate的持久层 需要好几个步骤。 第一步让我们把BO持久化。 既然Hibernate是通过POJO工作的, 因此Order和 OrderLineItem对象需要给所有的fileds 加上getter,setter方法。 Hibernate通过XML文件来映射(OR)对象,以下两个xml文件分别映射了Order 和OrderItem对象。(这里有个叫XDoclet工具可以自动生成你的XML影射文件)
- Order.hbm.xml
- OrderLineItem.hbm.xml
你可以在WebContent/WEB-INF/classes/com/meagle/bo目录下找到这些xml文件。Hibernate的[urlhttp://www.hibernate.org/hib_docs/api/net/sf/hibernate/SessionFactory.html]SessionFactory [/url]是用来告诉程序 应该与哪个数据库通信,该使用哪个连接池或使用了DataSource, 应该加载哪些持久对象。而Session接口是用来完成Selecting,Saving,Delete和Updating这些操作。 后面的我们将讲述SessionFactory和Session是怎样设置的。
业务层的配置(Business Layer Configuration)
既然我们已经有了domain objects,接下来我们就要business service objects了,用他们来执行程序的logic,调用持久层,得到UI层的requests,处理transactions,并且控制exceptions。 为了将这些连接起来并且易于管理,我们将使用面向方面的 SpringFramework。 Spring 提供了 控制倒置(inversion of control 0==IoC)和注射依赖设置(setter dependency injection)这些方式(可供选择),用XML文件将对象连接起来。 IoC是一个简单概念(它允许一个对象在上层接受其他对象的创建),用IoC这种方式让你的对象从创建中释放了出来,降低了偶合度。
这里是一个没有使用IoC的对象创建的例子,它有很高偶合度。
图 2.没有使用 IoC. A 创建了 B 和 C
而这里是一个使用IoC的例子,这种方式允许对象在高层可以创建并进入另外一个对象,所以这样可以直接被执行。
图 3. 对象使用了 IoC。 A 包含了接受B,C的 setter方法 , 这同样达到了 由A创建B,C的目的。
建立我们的业务服务对象(Building Our Business Service Objects)
Business Object中的Setter方法接受的是接口,这样我们可以很松散的定义对象实现,然后注入。 在我们的案例中,我们将用一个business service object接收一个DAO,用它来控制domain objects的持久化。 由于在这个例子中使用了Hibernate,我们可以很方便的用其他持久框架实现 同时通知Spring 有新的DAO可以使用了。
在面向接口的编程中,你会明白 “注射依赖”模式是怎样松散耦合你的业务逻辑和持久机制的:)。
下面是一个接口business service object,DAO代码片段:
代码: |
|
注意到这段代码里有一个 setOrderDao(),它就是一个DAO
Object设置方法(注射器)。 但这里并没有一个getOrderDao的方法,这不必要,因为你并不会在外部访问这个orderDao。这个DAO
Objecte将被调用,和我们的persistence layer 通信。我们将用Spring把DAO Object 和 business
service object搭配起来的。因为我们是面向接口编程的,所以并不需要将实现类紧密的耦合在一起。
接下去我们开始我们的DAO的实现类进行编码。 既然Spring已经有对Hibernate的支持,那这个例子就直接继承HibernateDaoSupport类了,这个类很有用,我们可以参考HibernateTemplate(它主要是针对HibernateDaoSupport的一个用法,译注:具体可以查看Srping 的API)。
下面是这个DAO接口代码:
代码: |
public interface IOrderDAO { |
我们仍然要给我们持久层组装很多关联的对象,这里包含了HibernateSessionFactory和TransactionManager。 Spring 提供了一个 HibernateTransactionManager,他用线程捆绑了一个Hibernate Session,用它来支持transactions(请查看ThreadLocal) 。
下面是HibernateSessionFactory 和 HibernateTransactionManager:的配置:
代码: |
<bean id="mySessionFactory" |
可以看出:每个对象都可以在Spring 配置信息中用<bean>标签引用。在这里,mySessionFactory引用了
HibernateSessionFactory,而myTransactionManager引用了
HibernateTransactionManage。 注意代码中myTransactionManger
Bean有个sessionFactory属性。 HibernateTransactionManager有个sessionFactory
setter 和 getter方法,这是用来在Spring启动的时候实现“依赖注入” (dependency
injection)的。 在sessionFactory 属性里 引用mySessionFactory。这两个对象在Spring容器初始化后就被
组装了起来了。 这样的搭配让你从 单例(singleton
objects)和工厂(factories)中解放了出来,降低了代码的维护代价。mySessionFactory.的两个属性,分别是用来注入
mappingResources 和 hibernatePropertes的。通常,如果你在Spring之外使用Hibernate,这样的设置应
该放在hibernate.cfg.xml中的。 不管怎样,Spring提供了一个便捷的方式-----在Spring内部配置中并入了
Hibernate的配置。 如果要得到更多的信息,可以查阅Spring API。
既然我们已经组装配置好了Service Beans,就需要把Business Service Object和 DAO也组装起来,并把这些对象配到一个事务管理器(transaction manager)里。
在Spring中的配置信息:
代码: |
|
图4 是我们对象搭建的一个提纲。 从中可以看出,每个对象都联系着Spring,并且能通过Spring注入到其他对象。把它与Spring的配置文件比较,观察他们之间的关系
图 4. Spring就是这样基于配置文件,将各个Bean搭建在一起。
这
个例子使用一个TransactionProxyFactoryBean,它定义了一个setTransactionManager()。 这对象很有
用,他能很方便的处理你申明的事物还有Service
Object。 你可以通过transactionAttributes属性来定义怎样处理。 想知道更多还是参考
TransactionAttributeEditor吧。
TransactionProxyFactoryBean 还有个
setter. 这会被我们 Business service
object(orderTarget)引用, orderTarget定义了 业务服务层,并且它还有个属性,由setOrderDAO()引用。这个
属性
Spring 和Bean 的还有一点要注意的: bean可以以用两种方式创造。 这些都在单例模式(Sington)和原型模
式(propotype)中定义了。 默认的方式是singleton,这意味着共享的实例将被束缚。 而原形模式是在Spring用到bean的时候允
许新建实例的。当每个用户需要得到他们自己Bean的Copy时,你应该仅使用prototype模式。(更多的请参考设计模式中的单例模式和原形模
式)
提供一个服务定位器(Providing a Service Locator)
既
然我们已经将我们的Serices和DAO搭配起来了。我们需要把我们的Service显示到其他层。 这个通常是在Struts或者Swing这层里编
码。一个简单方法就是用 服务定位器返回给Spring context 。当然,可以通过直接调用Spring中的Bean来做。
下面是一个Struts Actin 中的服务定位器的一个例子。
代码: |
|
UI 层配置 (UI Layer Configuration)
这个例子里UI层 使用了Struts framework. 这里我们要讲述一下在给程序分层的时候, 哪些是和Struts部分的。我们就从一个Struts-config.xml文件中的Action的配置信息开始吧。
代码: |
|
SaveNewOrder 这个Action是用来持久化UI层里的表单提交过来Order的。这是Struts中一个很典型的
Action; 注意观察这个Action中exception配置,这些Exceptions也在Spring 配置文件
(applicationContext-hibernate.xml)中配置了(就在 business service
object的transactionAttributes属性里)。 当异常在业务层被被抛出时,我们可以控制他们,并适当的显示给UI层。
第一个异常,OrderException,在持久层保存order对象失败的时候被触发。这将导致事物回滚并且通过BO把异常回传到Struts这一层。
第二个异常,OrderMinimumAmountException也同第一个一样。
搭配整和的最后一步 通过是让你显示层和业务层相结合。这个已经被服务定位器(service locator)实现了(前面讨论过了), 这里服务层作为一个接口提供给我们的业务逻辑和持久层。
SaveNewOrder Action 在Struts中用一个服务定位器(service locator)来调用执行业务方法的。 方法代码如下:
代码: |
public ActionForward execute( OrderForm oForm = (OrderForm) form; // See the full source code in the sample app. // in BaseAction. } |
总结
这篇文章在技术和构架方面掩盖了很多低层的基础信息, 文章的主要的意图在于让你意识到如何给你应用程序分
层。 分层可以“解耦”你的代码——允许新的组件被添加进来,而且让你的代码易于维护。 这里用到的技术只是专注于把“解偶”做好。 不管怎样,使用这样
的构架可以让你用其他技术代替现在的层。 例如,你可能不使用Hibernate实现持久化。既然你在DAO中面向接口的编程的,所以你完全可以用
iBATIS来代替。或者,你也可能想用Struts外的其他的技术或者框架替换现在的UI层(转换久层,实现层并不应该直接影响到你的业务逻辑和业务服
务层)。 用适当的框架搭建你的Web应用,其实也不是一件烦琐的工作,更主要的是它“解耦”了你程序中的各个层。
标签:
原文地址:http://www.cnblogs.com/zhengah/p/4988908.html