集成spring struts hibernate思想
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
应用程序的分层
Web应用程序一般分为四层,这四层是:presentation(描述),business (业务),persistence(持久)和domain model(域模型)。
(一)表示层(The Presentation Layer)
一般来讲,一个典型的Web应用的的末端应该是表示层。
用来管理用户的请求,做出相应的响应,给出显示。
一般使用Struts框架来实现应用程序的表示层。
(二)域模型层(The Domain Model Layer )
域模块层由实际需求中的业务对象组成,即我们常说的BO(Business Object)比如, Order , Pet等等。
开发者在这层不用管那些DTOs,仅关注domain object即可。
例如,Hibernate允许你将数据库中的信息存放入对象(domain objects),这样你可以在连接断开的情况下把这些数据显示到UI层。
而那些对象也可以返回给持久层,从而在数据库里更新。
(三) 业务层(The Business Layer)
一个典型Web应用的中间部分是业务层或者服务层。
这一层最容易受到忽视,从而导致大量的代码紧密的耦合在一起,从而使整个程序变的难以维护。
一般使用Spring框架来解决这个问题,Spring把程序中所涉及到包含业务逻辑和Dao的Objects--例如transaction management handler(事物管理控制)、Object Factories(对象工厂)、service objects(服务组件)--都通过XML来配置联系起来,从而使业务层变得非常灵活和易于维护。
(四)持久层(The Persistence Layer)
持久层是典型的Web应用的另一个末端。
现在已经有很多很好的ORM开源框架来解决持久层的各种问题,尤其是Hibernate。
Hibernate为Java提供了OR持久化机制和查询服务, 它还给已经熟悉SQL和JDBC API 的Java开发者一个学习桥梁,他们学习起来很方便。
Hibernate的持久对象是基于POJO 和Java collections。
开发步骤
创建域模型层
这层是编码的着手点,我们的编码就从这层开始。
本应用中的Domain Object比较简单,只使用了一个对象:Object.java。
代码清单:
package com.ibm.sample.bo;
public class InfoObject
{
private Long infoId;
private String title;
private String content;
}
infoId记录了这个InfoObject对象的唯一标识,title记录了新闻标题,content记录了新闻内容。
创建持久层
持久化BO。
Hibernate是通过POJO工作的,因此我们先给InfoObject 对象的fileds 加上getter,setter方法。
Hibernate通过XML文件来映射(OR)对象,在这里,我们使用XDoclet工具来生成hibernate的XML映射文件。
为了使用Xdoclet这个工具,我们需要在BO对象的代码里面添加一些描述语句。
修改后的BO对象代码如下:
package com.ibm.sample.bo;
/**
* @author rayguo mail:guorui@
*
* @hibernate.class table="InfoObject"
*
*/
public class InfoObject {
private Long infoId;
private String title;
private String content;
/**
* Returns the Content.
* @return String
*
* @hibernate.property
* @hibernate.column name="Content" not-null="false"
* length="3000"
*/
public String getContent() {
return content;
}
/**
* Returns the id.
* @return Long
*
* @hibernate.id column="infoId"
* generator-class="native"
*/
public Long getInfoId() {
return infoId;
}
/**
* Returns the Title.
* @return String
*
* @hibernate.property
* @hibernate.column name="title" not-null="true"
* length="200"
*/
public String getTitle() {
return title;
}
public void setContent(String string) {
content = string;
}
public void setInfoId(Long long1) {
infoId = long1;
}
public void setTitle(String string) {
title = string;
}
}
创建DAO接口。
为了程序的扩展性,我们首先需要创建一个提供数据访问服务的接口层,定义出对外的访问接口,在本示例中,为IInfoObjectDAO,代码如下:
package com.ibm.sample.dao;
public interface IInfoObjectDAO {
public abstract InfoObject saveInfoObject(InfoObject info);
public abstract InfoObject getInfoObjectById(Long infoId);
public abstract List getAllInfoObjects();
public abstract void removeInfoObject(Long infoId); }
创建DAO层的实现。
本示例的DAO层实现,我们采用了Hibernate,按通常的实现,我们需要先得到Hibernate的session对象,然后调用session对象的save,delete,update等方法来实现对数据对象的CRUD操作,但由于Spring框架已经提供了对Hibernate框架的良好支持,使我们不再需要再头痛于Hibernate的session管理,事务管理等方面,这些Spring框架已经进行了很好的封装,我们只需要将我们的Hibernate实现类继承HibernateDaoSupport类,然后通过调用HibernateTemplate类上的方法,就可以实现我们需要的数据对象访问的操作。
代码如下:
package com.ibm.sample.dao.hibernate;
public class InfoObjectDAOHibernate extends HibernateDaoSupport implements IInfoObjectDAO {
public InfoObjectDAOHibernate(){
super();
}
public InfoObject saveInfoObject(InfoObject info) {
getHibernateTemplate().saveOrUpdate(info);
return info;
}
public InfoObject getInfoObjectById(Long infoId){
InfoObject info =
(InfoObject) getHibernateTemplate().load(InfoObject.class, infoId);
return info;
}
public void removeInfoObject(Long infoId) {
InfoObject info = getInfoObjectById(infoId);
getHibernateTemplate().delete(info);
}
public List getAllInfoObjects() {
return
getHibernateTemplate().loadAll(InfoObject.class);
}
}
通过配置,将Spring框架与Hibernate框架结合使用。
如果你以前使用过Hibernate,你现在该感到有些迷惑:使用Hibernate框架的时候,需要提供的hibernate.cfg.xml配置文件应该放在哪里呢?为了使Spring框架能够真正的感知到Hibernate对象,为其添加事务管理,
SessionFactory管理等功能,我们需要添加一个Spring的配置文件,而且,Spring提供了一个便捷的方式-----在Spring内部配置中并入了Hibernate的hibernate.cfg.xml配置文件。
首先在Sample项目的JavaSource/dao目录下,建立文件applicationContext-hibernate.xml,在文件中添加如下内容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"/dtd/spring-beans.dtd">
<beans>
<!-- ==================== Start of PERSISTENCE DEFINITIONS ================== -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerD ataSource"
destroy-method="close">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/infos</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value></value>
</property>
</bean>
<!-- Choose the dialect that matches your "dataSource" definition -->
<bean id="mySessionFactory"
class="org.springframework.orm.hibernate.LocalSessi onFactoryBean">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="mappingResources">
<list>
<value>com/ibm/sample/bo/InfoObject.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop
key="hibernate.dialect">net.sf.hibernate.dialect.My SQLDialect</prop>
</props>
</property>
</bean>
<!-- DAO object: Hibernate implementation -->
<bean id="infoObjectDAO"
class="com.ibm.b2e.app.itsubsystem.dao.hibernate.In foObjectDAOHibernate">
<property name="sessionFactory"><ref
local="mySessionFactory"/></property> </bean>
</beans>
Spring的核心功能就是Bean管理,在这个配置文件中,我们配置了3个Java 对象,id分别为:dataSource, mySessionFactory和infoObjectDAO。
mySessionFactory的dataSource属性引用了dataSource对象,infoObjectDAO 的sessionFactory属性又引用了mySessionFactory对象。
在Spring框架启动的时候,会自动的根据这个配置文件,生成相应的对象,并将生成的对象注入到对应的属性中去,这就是所谓的"依赖注入"(dependency injection)。
通过这样的方式,可以将我们从单例模式(singleton objects)和工厂模式(factories)中解放出来,降低代码的维护成本。
在这里,mySessionFactory中配置的属性,对应于Hibernate的hibernate.cfg.xml配置文件。
dataSource中的属性设置是针对MySql数据库的,你需要将其改成与你的测试环境数据库一致。
好了,至此,我们完成了示例应用的DAO层创建工作,是不是感到有些心神不宁?是的,虽然我们用的不是测试驱动开发(Test Driver Development),可现在也该写点测试用例来测试一下我们刚刚新建的DAO层了。
创建业务层
现在,我们需要来构建我们的BSO(business service objects)了,用来执行程序的逻辑,调用持久层,得到UI层的requests,处理transactions,并且控制exceptions。
在这里,我们将使用Spring框架,很快,你就会感受到使用Spring框架来管理业务层,将给你的应用程序带来极大的灵活性,和更松散的耦合度。
1.建立业务服务对象接口
首先我们需要做的,还是要定义出我们在业务层提供的接口。
在Spring框架中,任何注册到Spring框架中的bean,如果实现了某个接口,那么在得到这个bean 的时候,只能将其下溯造型成其接口进行操作,而不能直接下溯造型成具体的类型进行操作。
原因在于Spring的AOP实现机制,Spring中的Bean管理实际上是基于动态AOP机制实现,为了实现动态AOP,Spring在默认情况下会使用Java Dynamic Proxy,但是,Dynamic Proxy要求其代理的对象必须实现一个接口,该接口定义了准备进行代理的方法。
而对于没有实现任何接口的Java Class,需要采用其他方式,Spring通过CGLib实现这一功能。
当类实现了一个
接口之后,Spring将通过Java Dynamic Proxy机制实现代理功能,此时返回的Bean,是通过ng.reflect.Proxy.newProxyInstance方法创建的其接口的一个代理实现,这个实例实现了其接口,但与类已经没有继承关系,因此无法通过下溯造型进行强制转型,如果进行转换,则会抛出异常。
这也就强制要求编程人员要面向接口编程,使程序员能够从接口的角度考虑程序设计,从而降低了程序的耦合度。
package com.ibm.sample.service;
public interface IInfoObjectService {
public abstract InfoObject saveInfoObject(InfoObject infoObject) throws InfoObjectException;
public abstract InfoObject findInfoObjectById(Long id) throws InfoObjectException;
public abstract List findAllInfoObjects() throws InfoObjectException;
public abstract void removeInfoObject(Long deleteId) throws InfoObjectException;
public abstract void setInfoObjectDAO(IInfoObjectDAO infoObjectDAO);
}
通过接口可以看到,在业务层对底层的Exception进行了捕捉,并进行了统一的封装,再用定义好的业务服务级别的Exception抛出。
注意到这段代码里有一个setInfoObjectDAO(),它就是一个DAO Object设置方法,将DAO的实现注射到Service对象中。
但这里并没有一个getInfoObjectDao的方法,这不必要,因为并不会在外部访问这个DAO。
Service层将调用这个DAO Object和持
久层通信。
我们将用Spring把DAO Object 和business service object搭配起来的。
因为我们是面向接口编程的,所以并不需要将实现类紧密的耦合在一起。
2.实现业务服务对象接口,并通过Spring将其和DAO对象关联起来因为本例比较简单,所以接口的实现也很简单,并没有什么复杂的操作,通过调用InfoObjectDAO对象上的方法,就可以实现服务对象接口,具体的代码见附件中的com.ibm.sample.service.impl. InfoObjectServiceImpl.java文件。
我们主要需要关注的是如何通过Spring将业务对象与DAO对象关联起来,并实现事务。
在Spring的配置文件中添加如下代码:
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="myTransactionManager"
class="org.springframework.orm.hibernate.HibernateT ransactionManager">
<property name="sessionFactory"><ref
local="mySessionFactory"/></property>
</bean>
<!-- ***** InfoObject SERVICE *****-->
<bean id="infoObjectService"
class="org.springframework.transaction.interceptor. TransactionProxyFactoryBean">
<property name="transactionManager"><ref
local="myTransactionManager"/></property>
<property name="target"><ref
local="infoObjectTarget"/></property>
<property name="transactionAttributes">
<props>
<prop
key="find*">PROPAGATION_REQUIRED,readOnly,-InfoObjectExce ption</prop>
<prop
key="save*">PROPAGATION_REQUIRED,-InfoObjectException</pr op>
</props>
</property>
</bean>
<!-- InfoObjectTarget primary business object implementation -->
<bean id="infoObjectTarget"
class="com.ibm.sample.service.impl. InfoObjectServiceImpl">
<property name="infoObjectDAO"><ref
local="infoObjectDAO"/></property>
</bean>
在这里,myTransactionManager引用了mySessionFactory bean。
本例使用一个TransactionProxyFactoryBean,它定义了一个属性transactionManager。
这个对象很有用,它能很方便的处理你申明的事物还有Service Object。
你可以通过transactionAttributes 属性来定义怎样处理。
TransactionProxyFactoryBean 还有个属性target. 这将会注入我们的Business service object(infoObjectTarget)引用,infoObjectTarget定义了业务服务层,并且它还有个属性,将会注入我们的DAO对象(InfoObjectDAO)引用,通过这个配置,我们就将DAO对象和Service Object对象关联了起来,并在Business Service这一层提供了事务管理,在InfoObjectService中所有以find 开头的方法,则以只读的事务处理机制进行处理。
(设为只读型事务,可以使持久层尝试对数据操作进行优化,如对于只读事务Hibernate将不执行flush操作,而某些数据库连接池和JDBC 驱动也对只读型操作进行了特别优化。
);而使用save开头的方法,将会纳入事务管理范围。
如果此方法中抛出异常,则Spring 将当前事务回滚,如果方法正常结束,则提交事务。
在这里,我们的DAO层是使用Hibernate实现的,如果我们将DAO层的实现技术改为JDBC,JDO,DAO等,只需要实现IInfoObjectDAO接口,并在Spring
配置文件里,将infoObjectDAO bean的实现类名替换为新实现的类名即可,如此就可以将改动控制在最小的范围之内,不会因为DAO层的变化而引起程序结构大规模的改变,显得非常的灵活,具有良好的可维护性。
建立表示层(The Presentation Layer)
我们已经建立了应用程序的DAO层和Service层,现在我们需要做的就是将Service的接口暴露给表示层,使表示层能够调用到Service层的接口,并将处理结果展现给用户。
在这一层,我们在本示例中将使用Struts框架编写Portlet 进行展现。