J2EE Struts框架课程设计实训项目《BBS论坛系统》——在项目中应用Hibernate中的监听器和拦截器等组件技术

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

基于J2EE Struts框架的课程设计实训项目——《BBS论坛系统》——在项目中应用Hibernate中的监听器和拦截器等组件技术
1.1.1应用Hibernate中的监听器(事件)
1、Hibernate中的监听器
(1)主要的作用
该事件系统可以用来替代拦截器,也可以作为拦截器的补充来使用;而且Session接口的每个方法都有相对应的事件。

比如 LoadEvent,FlushEvent等等(可以查阅XML配置文件的DTD,以及org.hibernate.event包来获得所有已定义的事件的列表)。

因此,可以应用Hibernate中的监听器来生成审计日志,审计主要是对数据库中重要数据的更新历史进行记录。

数据库系统所提供的触发器技术也可以用于生成审计日志,但是它不支持跨数据库平台,所以一般用Hibernate中的监听器。

(2)org.hibernate.event包中所定义的各个事件类
(3)事件的产生和激活
当某个方法被调用时,Hibernate Session会生成一个相对应的事件并激活所有配置好的事件监听器。

系统预设的监听器实现的处理过程就是被监听的方法要做的(被监听的方法所做的其实仅仅是激活监听器,“实际”的工作是由监听器完成的)。

当然,开发者也可以自由地选择实现一个自己定制的监听器(比如,实现并注册用来处理处理LoadEvent的LoadEventListener接口),来负责处理所有的调用Session的load()方法的请求。

(4)对事件监听器的编程要求
事件监听器应该被看作是单例(singleton)对象,也就是说,所有同类型的事件的处理
共享同一个事件监听器实例,因此在事件监听器类中不应该保存有任何状态(也就是不应该使用成员变量)。

(5)事件监听器的编程方法
1)用户定制的监听器应该实现与所要处理的事件相对应的接口,或者从一个合适的基类继承(甚至是从Hibernate自带的默认事件监听器类继承)。

2)然后再注册自定义事件监听器(编程式或者声明式)
通过编程使用Configuration对象来注册或者也可以在Hibernate的XML格式的配置文件中进行声明(但不支持在Properties格式的配置文件声明监听器)以代替系统默认的事件监听器。

当然,也可以采用<event>标签俩进行定义各个事件监听器。

2、Hibernate 3中的新特性 Event-listener
能够取得运行期详细信息,除了能记录粗粒度的实体的保存删除操作外,还能精确追踪对实体字段修改、实体关联/级联关系的变更,能记录更新前的值、更新后的值,可以生成详细日志。

灵活解耦,跨数据库,不影响原有代码。

Hibernate3中定义了很多的事件,涵盖了持久化过程中不同的生命周期。

简单说Session的一个方法(load, flush...)分别对应一个事件,当该方法被调用时,就会触发一个相应的事件,这个事件会被我们预先定义的事件监听器收到,再进行相应的处理。

这种方式来做审计日志是再适合不过。

但也有个缺点就是这样的Event-listener是脱离主容器(比如Spring IoC环境)单独实例化的,无法访问主容器的资源(比如要取得当前登录的用户信息就会比较麻烦)。

PostInsertEventListener(插入后事件),PostUpdateEventListener(更新后事件),PostDeleteEventListener(删除后事件)。

3、在项目中应用Hibernate中的监听器
POBeanLoadEventListener、包名称为com.px1987.webbbs.hibernatelistener
继承org.hibernate.event.def.DefaultLoadEventListener类
4、编程POBeanLoadEventListener类中相关的程序代码
package com.px1987.webbbs.hibernatelistener;
import org.hibernate.HibernateException;
import org.hibernate.event.LoadEvent;
import org.hibernate.event.LoadEventListener;
import org.hibernate.event.def.DefaultLoadEventListener;
public class POBeanLoadEventListener extends DefaultLoadEventListener { public POBeanLoadEventListener() {
}
public void onLoad(LoadEvent event, LoadEventListener.LoadType loadType) throws HibernateException {
String targetClassNameLoaded=event.getEntityClassName();
if(targetClassNameLoaded.equals("erInfoPO")){ System.out.println("targetClassNameLoaded="+targetClassNameLoaded);
}
super.onLoad(event, loadType);
}
}
5、配置POBeanLoadEventListener监听器
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<listener type="load" class=
"com.px1987.webbbs.hibernatelistener.POBeanLoadEventListener"/>
</session-factory>
</hibernate-configuration>
为什么我们在监听器类POBeanLoadEventListener中已经实现了特定监听器的接口(本例为LoadEventListener),在注册的时候还要明确指出我们要注册哪个事件(type="load")的监听器呢?
这是因为一个监听器类可能实现多个不同的监听器接口,在注册的时候开发者可以明确指定要监听的事件,从而可以启用或者禁用对某个事件的监听而达到更加灵活(因为实现了多个接口、但在具体的应用时并不一定要监听这些类型的事件,可以再次选择!)。

6、测试POBeanLoadEventListener监听器的功能效果
1.1.2利用Hibernate中的拦截器组件实现对数据库表的删除行为进行日志记录
1、Hibernate中的拦截器组件技术
(1)应用的目的
Hibernate中所提供的拦截器组件技为开发人员提供了从会话(session)回调(callback)应用程序(application)的机制,这种回调机制可以允许应用程序在持久化对象被保存、更新、删除或是加载之前,检查并(或)修改其属性。

但是拦截器的使用会降低性能。

(2)编程方法
可以直接实现Interceptor接口,也可以(最好)继承自EmptyInterceptor类
(3)Interceptor接口中的部分方法的定义说明
2、Hibernate3中的拦截器
可以在hibernate对象操作的时候获取最为详细的运行期信息,字段名,原始值,修改后值等等。

3、调用拦截器的方法
(1)save()
(2)update()
(3)saveOrUpdate()
(4)flush()
4、拦截器可以有两种
通过Session启用局部拦截器,而通过Configuration启用全局拦截器。

(1)Session范围内的
当使用某个重载的SessionFactory.openSession()使用Interceptor作为参数调用打开一个session的时候,就指定了Session范围内的拦截器。

Session session = sf.openSession( new UserInfoInterceptor () );
(2)SessionFactory范围内的
SessionFactory范围内的拦截器要通过Configuration中注册,而这必须在创建SessionFactory之前。

在这种情况下,给出的拦截器会被这个SessionFactory所打开的所有session使用了;除非session打开时明确指明了使用的拦截器。

SessionFactory范围内的拦截器,必须是线程安全的,因为多个session可能并发使用这个拦截器,要因此小心不要保存与session相关的状态。

new Configuration().setInterceptor( new UserInfoInterceptor () );
5、在项目中应用Hibernate框架中的Session范围内的拦截器组件
(1)添加一个Hibernate中的拦截器组件类
类名称为UserInfoInterceptor,包名称为com.px1987.webbbs.hibernateinterceptor、并且继承于org.hibernate.EmptyInterceptor类
(2)编程该UserInfoInterceptor拦截器组件类中相关的功能实现代码
(3)修改HibernateUtil类并添加下面的方法
public static Session currentSession(Interceptor someOneInterceptor){ Session currentSession = (Session) threadLocal.get();
if (currentSession == null){
currentSession = sessionFactory.openSession(someOneInterceptor);
threadLocal.set(currentSession);
}
return currentSession;
}
(4)修改UserManageDAOHibernateImple类中的deleteOneUserInfo方法
public boolean deleteOneUserInfo(String registerUserID)
throws WebBBSException{ boolean OKOrNot=false;
Session session=null;
Transaction tx=null;
try{
session = HibernateUtil.currentSession(new UserInfoInterceptor());
tx = session.beginTransaction();
UserInfoPO oneUserTODeleted=
(UserInfoPO)session.get(UserInfoPO.class,registerUserID);
if(oneUserTODeleted==null){
throw new WebBBSException("在数据库表中不存在指定userID="+registerUserID+"的数据顶目!");
}
session.delete(oneUserTODeleted);
mit();
OKOrNot=true;
}
catch (HibernateException e){
}
finally {
HibernateUtil.closeSession();
}
return OKOrNot;
}
6、测试该Session范围内的拦截器组件的功能效果
(1)启动TestUserManageDAOHibernateImple的测试用例类,其执行的结果如下
(2)TestUserManageDAOHibernateImple测试用例类的代码示例
package com.px1987.webbbs.hibernatedaotest;
import com.px1987.webbbs.config.ClassNameConfig;
import com.px1987.webbbs.dao.*;
import com.px1987.webbbs.exception.*;
import com.px1987.webbbs.util.*;
import junit.framework.TestCase;
import java.util.*;
//import org.springframework.context.ApplicationContext;
//import org.springframework.context.support.FileSystemXmlApplicationContext; public class TestUserManageDAOHibernateImple extends TestCase {
UserManageDAOInterface oneUserManageDAOJDBCImple=null;
String userManageDAOJDBCImpleClassName=null;
/* Spring没有与Hibernate进行集成时
*/
protected void setUp() throws Exception{
super.setUp();
userManageDAOJDBCImpleClassName=
ClassNameConfig.getProperty("userManageDAOJDBCImple.className");
oneUserManageDAOJDBCImple=new UserManageDAOFactory().
newUserManageDAOBean(userManageDAOJDBCImpleClassName);
}
/* Spring没有与Hibernate进行集成时
protected void setUp() throws Exception{
super.setUp();
//根据实际来决定
String springXMLPath=
"D:/aaa/StrutsWebBBS+Spring/WebBBS/WebRoot/WEB-INF/SpringLinkHibernate.xml";
ApplicationContext applicationContext =
new FileSystemXmlApplicationContext(springXMLPath);
oneUserManageDAOJDBCImple=(UserManageDAOInterface)
applicationContext.getBean("userInfoManageDAOImpleBean");
}
*/
protected void tearDown() throws Exception{
oneUserManageDAOJDBCImple=null;
super.tearDown();
}
public void testSelectOneUserInfoData() throws WebBBSException{
//应该根据数据库表中的实际数据来决定
String registerUserID="2";
UserInfoPO returnOneUserInfoPO=
oneUserManageDAOJDBCImple.selectOneUserInfo(registerUserID);
//由于所给定的ID是数据库表中存在的一个用户,因此能够返回该对象
this.assertNotNull(returnOneUserInfoPO);
}
public void testSelectAllBaseUserInfo() throws WebBBSException{
ArrayList allBaseUserInfos=oneUserManageDAOJDBCImple.selectAllBaseUserInfo();
this.assertNotNull(allBaseUserInfos);
Iterator allItem=allBaseUserInfos.iterator();
while(allItem.hasNext()){
UserInfoBasePO oneUserInfoBasePO=(UserInfoBasePO)allItem.next();
this.assertNotNull(oneUserInfoBasePO);
String registerUserName=oneUserInfoBasePO.getUserName();
this.assertNotNull(registerUserName);
}
}
public void testSelectAllRegisterUserNameInfo() throws WebBBSException { String userName="adm";
ArrayList returnAllRegisterUserNameInfos=
oneUserManageDAOJDBCImple.selectAllRegisterUserNameInfo(userName);
this.assertNotNull(returnAllRegisterUserNameInfos);
Iterator allItem=returnAllRegisterUserNameInfos.iterator();
while(allItem.hasNext()){
String oneUserName=(String)allItem.next();
this.assertNotNull(oneUserName);
}
}
public void testSelectAllUserInfo() throws WebBBSException {
ArrayList allRegisterUserInfos=oneUserManageDAOJDBCImple.selectAllUserInfo();
allRegisterUserInfos=oneUserManageDAOJDBCImple.selectAllUserInfo();
allRegisterUserInfos=oneUserManageDAOJDBCImple.selectAllUserInfo();
allRegisterUserInfos=oneUserManageDAOJDBCImple.selectAllUserInfo();
this.assertNotNull(allRegisterUserInfos);
Iterator allItem=allRegisterUserInfos.iterator();
while(allItem.hasNext()){
UserInfoPO oneRegisterUserInfoPO=(UserInfoPO)allItem.next();
this.assertNotNull(oneRegisterUserInfoPO);
String registerUserName=oneRegisterUserInfoPO.getUserName();
this.assertNotNull(registerUserName);
}
}
public void testSelectOneUserInfo() throws WebBBSException{
String userName="admin"; //应该根据数据库表中实际的数据值来决定
String userPassWord="admin"; // admin的“MD5加密后的结果”
UserInfoPO returnOneUserInfoPO=
oneUserManageDAOJDBCImple.selectOneUserInfoData(userName, userPassWord);
this.assertNotNull(returnOneUserInfoPO);
}
public void testSelectOneUserInfoByName() throws WebBBSException{ String userName="admin"; //应该根据数据库表中的实际数据来决定
UserInfoPO returnOneUserInfoPO=
oneUserManageDAOJDBCImple.selectOneUserInfoByName(userName);
//由于所给定的userName是数据库表中存在的一个用户,因此能够返回该对象this.assertNotNull(returnOneUserInfoPO);
}
public void testDoGetMaxIDUserInfo() throws WebBBSException {
UserInfoPO returnOneUserInfoPO=
oneUserManageDAOJDBCImple.doGetMaxIDUserInfo();
this.assertNotNull(returnOneUserInfoPO);
}
public void testSelectSomeBaseUserInfo() throws WebBBSException{
String HQLQuery="from erInfoBasePO";
ArrayList allBaseUserInfos=
oneUserManageDAOJDBCImple.selectSomeBaseUserInfo(HQLQuery);
this.assertNotNull(allBaseUserInfos);
Iterator allItem=allBaseUserInfos.iterator();
while(allItem.hasNext()){
UserInfoBasePO oneUserInfoBasePO=(UserInfoBasePO)allItem.next();
this.assertNotNull(oneUserInfoBasePO);
String registerUserName=oneUserInfoBasePO.getUserName();
this.assertNotNull(registerUserName);
}
}
public void testSelectSomeUserInfo() throws WebBBSException {
String HQLQuery="from erInfoPO";
ArrayList allReturnedUserInfos=
oneUserManageDAOJDBCImple.selectSomeUserInfo(HQLQuery);
this.assertNotNull(allReturnedUserInfos);
Iterator allItem=allReturnedUserInfos.iterator();
while(allItem.hasNext()){
UserInfoPO oneRegisterUserInfoPO=(UserInfoPO)allItem.next();
this.assertNotNull(oneRegisterUserInfoPO);
String registerUserName=oneRegisterUserInfoPO.getUserName();
this.assertNotNull(registerUserName);
}
}
public void testSelectTotalRegisterUserCounter() throws WebBBSException { int returnTotalRegisterUserCounter=
oneUserManageDAOJDBCImple.selectTotalRegisterUserCounter();
this.assertTrue(returnTotalRegisterUserCounter>0);
}
public void testSelectUserSomePropertyInfo() throws WebBBSException {
String HQLQuery="select oneUserInfo.id,erName from erInfoPO as oneUserInfo";
ArrayList allReturnedUserInfos=
oneUserManageDAOJDBCImple.selectUserSomePropertyInfo(HQLQuery);
this.assertNotNull(allReturnedUserInfos);
Iterator allItem=allReturnedUserInfos.iterator();
while(allItem.hasNext()){
Object[] oneRegisterUserPropertyInfo=(Object[])allItem.next();
this.assertNotNull(oneRegisterUserPropertyInfo);
}
}
/*
public void testDeleteOneUserInfo() throws WebBBSException{
// 该方法应该只执行一次
String registerUserID="5"; //应该根据数据库表中的实际数据来决定
boolean returnBoolean=
oneUserManageDAOJDBCImple.deleteOneUserInfo(registerUserID);
this.assertTrue(returnBoolean);
}
public void testBatchDeleteUserInfo() throws WebBBSException{
ArrayList deletedUserIDs=new ArrayList();
String userIDOne="1"; //应该根据数据库表中的实际数据来决定
String userIDTwo="-331012897";
String userIDThree="-265590631";
deletedUserIDs.add(userIDOne);
deletedUserIDs.add(userIDTwo);
deletedUserIDs.add(userIDThree);
boolean returnBoolean=
oneUserManageDAOJDBCImple.batchDeleteUserInfo(deletedUserIDs);
this.assertTrue(returnBoolean);
}
public void testInsertOneUserInfo() throws WebBBSException{
UserInfoPO oneUserInfoPO=new UserInfoPO();
Date nowDate=new Date();
//不需要设置该值,可以由Hibernate自动来实现添加
oneUserInfoPO.setId(new Integer((int)nowDate.getTime()).toString());
oneUserInfoPO.setUserName("张三");
oneUserInfoPO.setUserPassWord("1234");
oneUserInfoPO.setUserType(1);
oneUserInfoPO.setAliaoName("网上张飞");
oneUserInfoPO.setPassWordAsk("Who Are You?");
oneUserInfoPO.setUserImage("../webResource/PersonImage/Chang.gif");
oneUserInfoPO.setRegisterTime(new Date().toLocaleString());
oneUserInfoPO.setPassWordAnswer("zhang");
oneUserInfoPO.setUserMail("trainict@");
oneUserInfoPO.setUserSex(1);
oneUserInfoPO.setUserBirthDay("2007-01-25");
oneUserInfoPO.setUserComeFrom("北京");
oneUserInfoPO.addOneContactMethod("userQQCode","QQ1234567890");
oneUserInfoPO.addOneContactMethod("userICQCode","ICQ1234567890");
oneUserInfoPO.addOneContactMethod("userMSNCode","MSN1234567890");
oneUserInfoPO.setUserResume("我是网络飞人");
oneUserInfoPO.setUserSign("12345678900");
oneUserInfoPO.setEmailVisible(1);
oneUserInfoPO.setAcceptAdvise(1);
boolean actualReturn=
oneUserManageDAOJDBCImple.insertOneUserInfo(oneUserInfoPO);
this.assertTrue(actualReturn);
}
public void testUpdateOneUserInfo() throws WebBBSException{ UserInfoPO newOneRegisterUserInfoPO=new UserInfoPO();
String registerUserId="3"; //应该根据数据库表中的实际的数据值来决定//设置需要修改的某个用户的ID以定位其记录
newOneRegisterUserInfoPO.setId(registerUserId);
newOneRegisterUserInfoPO.setUserName("张三");
//本测试的数据只是对原来的数据改变了此值
newOneRegisterUserInfoPO.setUserPassWord("12345678");
newOneRegisterUserInfoPO.setUserType(1);
newOneRegisterUserInfoPO.setAliaoName("网上张飞");
newOneRegisterUserInfoPO.setPassWordAsk("Who Are You?"); newOneRegisterUserInfoPO.setUserImage("../webResource/PersonImage/Chang.gif");
newOneRegisterUserInfoPO.setRegisterTime(new Date().toLocaleString());
newOneRegisterUserInfoPO.setPassWordAnswer("zhang");
newOneRegisterUserInfoPO.setUserMail("trainict@");
newOneRegisterUserInfoPO.setUserSex(1);
newOneRegisterUserInfoPO.setUserBirthDay("2007-01-25");
newOneRegisterUserInfoPO.setUserComeFrom("北京");
newOneRegisterUserInfoPO.setUserResume("我是网络飞人");
newOneRegisterUserInfoPO.setUserSign("12345678900");
newOneRegisterUserInfoPO.setEmailVisible(1);
newOneRegisterUserInfoPO.setAcceptAdvise(1);
Map newContactMethod = new HashMap(); //可以在此改变用户的联系方式newContactMethod.put("userQQCode","QQ1234567890");
newContactMethod.put("userICQCode","ICQ1234567890");
newContactMethod.put("userMSNCode","MSN1234567890");
newOneRegisterUserInfoPO.setContactMethod(newContactMethod);
boolean actualReturn=
oneUserManageDAOJDBCImple.updateOneUserInfo(newOneRegisterUserInfoPO);
this.assertTrue(actualReturn);
// 本方法执行完成后可以查看数据库表中的数据状态是否发生了变化}
public void testUpdateOneUserPassWord() throws WebBBSException { String newPassWord="1234";
String registerUserId="3"; //应该根据数据库表中的实际的数据值来决定
boolean actualReturn=
oneUserManageDAOJDBCImple.updateOneUserPassWord(newPassWord,
registerUserId);
this.assertTrue(actualReturn);
}
*/
}。

相关文档
最新文档