1. 在spring xml配置文件中添加配置,包含:model、listener
  2. 在model中增加需要写入数据库对应表的model
  3. 在auditLog.xml配置文件中配置自己项目中,需要进行日志记录的model类shortName,以及相关属性。

相关代码如下:

首先spring xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <context:annotation-config />
<context:component-scan base-package="com.cqta" /> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
</list>
</property>
</bean> <bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
<property name="driver" value="${driver}" />
<property name="driverUrl" value="${driverUrl}" />
<property name="user" value="${user}" />
<property name="password" value="${password}" />
<property name="maximumActiveTime" value="600000" />
<property name="maximumConnectionCount" value="500" />
<property name="minimumConnectionCount" value="5" />
<property name="prototypeCount" value="5" />
<property name="simultaneousBuildThrottle" value="5" />
<property name="maximumConnectionLifetime" value="36000000" />
</bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingLocations">
<list>
<value>classpath*:com/cqta/dev/model/system/*.hbm.xml</value>
<value>classpath*:com/cqta/dev/model/authority/*.hbm.xml</value>
<value>classpath*:com/cqta/dev/model/question/*.hbm.xml</value>
<value>classpath*:com/cqta/dev/model/communication/*.hbm.xml</value>
<value>classpath*:com/cqta/dev/model/teacherwork/*.hbm.xml</value>
<value>classpath*:com/cqta/dev/model/workstation/*.hbm.xml</value>
<value>classpath*:com/cqta/dev/model/acupuncture/*.hbm.xml</value>
<value>classpath*:com/cqta/dev/model/online/*.hbm.xml</value>
<value>classpath*:com/cqta/dev/model/log/*.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect} </prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
<prop key="hibernate.cache.use_query_cache ">true</prop>
<prop key="hibernate.connection.autocommit">true</prop>
</props>
</property>
<property name="eventListeners" >
<map>
<entry>
<key>
<value>post-insert</value>
</key>
<ref bean="auditlogEvent" />
</entry>
<entry>
<key>
<value>post-update</value>
</key>
<ref bean="auditlogEvent" />
</entry>
<entry>
<key>
<value>post-delete</value>
</key>
<ref bean="auditlogEvent" />
</entry>
</map>
</property>
<property name="packagesToScan" value="com.cqta.dev.model." />
</bean>
<bean id="auditlogEvent" class="com.cqta.dev.web.util.LogAuditListener"></bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean> <aop:config proxy-target-class="true"> </aop:config>
<!-- 如果Service层出现新的pacage,需要在此处添加配置 -->
<aop:config proxy-target-class="true">
<aop:advisor pointcut="execution(public * com.cqta.dev.service.system..*.*(..))" advice-ref="txAdvice" />
<aop:advisor pointcut="execution(public * com.cqta.dev.service.authority..*.*(..))" advice-ref="txAdvice" />
<aop:advisor pointcut="execution(public * com.cqta.dev.service.workstation..*.*(..))" advice-ref="txAdvice" />
<aop:advisor pointcut="execution(public * com.cqta.core.dao..*.*(..))" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="del*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
</beans>

然后LogAuditListener.java代码

package com.cqta.dev.web.util;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import org.hibernate.event.PostDeleteEvent;
import org.hibernate.event.PostDeleteEventListener;
import org.hibernate.event.PostInsertEvent;
import org.hibernate.event.PostInsertEventListener;
import org.hibernate.event.PostUpdateEvent;
import org.hibernate.event.PostUpdateEventListener;
import org.springframework.security.core.userdetails.User;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException; import com.cqta.dev.model.log.Log;
import com.cqta.dev.model.log.LogAudit;
import com.cqta.dev.service.online.TxtContentService;
import com.cqta.dev.web.util.AppContextUtils; public class LogAuditListener implements PostInsertEventListener,PostUpdateEventListener, PostDeleteEventListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private static String INSERT="添加";
private static String UPDATE="修改";
private static String DELETE="删除";
private static Map<String,LogAudit> logAuditMap=new HashMap<String, LogAudit>();
/**
* 添加操作 日志
*/
public void onPostInsert(PostInsertEvent event) {
Class<?> clazz = event.getEntity().getClass();
try {
Log log=null;
if (logAuditMap.size() > 0) {
LogAudit logAudit=logAuditMap.get(clazz.getSimpleName());
if (logAudit != null) {
log=newLog(logAudit,INSERT);
StringBuilder content = new StringBuilder(INSERT + logAudit.getDescription());//操作说明
User user = null; //操作人
user = SecurityUserHolder.getCurrentUser();
Object[] newState = event.getState();
String[] fields = event.getPersister().getPropertyNames();
if (newState != null && fields != null && newState.length == fields.length ) {
for (int i = 0; i < fields.length; i++) {
if(logAudit.getProperty().containsKey(fields[i])){
content.append( "\""+logAudit.getProperty().get(fields[i])+ "\" "+newState[i]);
}
}
}
log.setDescription(content.toString());
log.setActionUserName(user!=null?user.getUsername():null);
saveOperate(log);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 修改操作 日志
*/
public void onPostUpdate(PostUpdateEvent event) {
Class<?> clazz = event.getEntity().getClass();
try {
Log log=null;
if (logAuditMap.size() > 0) {
LogAudit logAudit=logAuditMap.get(clazz.getSimpleName());
if (logAudit != null) {
log =newLog(logAudit,UPDATE);
String content = UPDATE + logAudit.getDescription(); //操作说明
User user = null; //操作人
user = SecurityUserHolder.getCurrentUser();
log.setActionUserName(user!=null?user.getUsername():null);
Object[] oldState = event.getOldState(); //获取旧值
Object[] newState = event.getState(); //获取更改后的值
String[] fields = event.getPersister().getPropertyNames(); //获取对象属性
if("User".equals(clazz.getSimpleName())){ //当对象是用用户时 将用户 单独拿出来 判断用户登录和修改密码
if(oldState != null && newState != null && fields != null && oldState.length == newState.length && oldState.length == fields.length){
boolean ref=false; //是否为登录操作
for (int i = 0; i < fields.length; i++) {
if(fields[i]=="lastlogintime" && oldState[i]!=newState[i]){ //登录操作 最后一次登录时间被修改
ref=false;break ;
}else if(fields[i]=="password" && oldState[i]!=newState[i]){ //登录操作 最后一次登录时间被修改
content = "修改密码";
ref=true;
}
if(logAudit.getProperty().containsKey(fields[i])&&! oldState[i].equals(newState[i])){
content += "{将 \"" + logAudit.getProperty().get(fields[i]) + "\" : \""+oldState[i]+ "\" 改为 \"" + String.valueOf(newState[i]) + "\"}";
ref=true;
}
}
if(ref){
log.setDescription(content);
saveOperate(log);
}
}
//如果修改的model不是USER
}else if (oldState != null && newState != null && fields != null && oldState.length == newState.length && oldState.length == fields.length ) {
for (int i = 0; i < fields.length; i++) { if(logAudit.getProperty().containsKey(fields[i])&&! oldState[i].equals(newState[i])){
content += "{将 \"" + logAudit.getProperty().get(fields[i]) + "\" : \""+oldState[i]+ "\" 改为 \"" + String.valueOf(newState[i]) + "\"}";
}
}
log.setDescription(content);
saveOperate(log);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除操作 日志
*/
public void onPostDelete(PostDeleteEvent event) {
Class<?> clazz = event.getEntity().getClass();
try {
Log log=null;
if (logAuditMap.size() > 0) {
LogAudit logAudit=logAuditMap.get(clazz.getSimpleName());
if (logAudit != null) {
log=newLog(logAudit,DELETE);
log.setDescription(DELETE+logAudit.getDescription());
User user = null; //操作人
user = SecurityUserHolder.getCurrentUser();
log.setActionUserName(user!=null?user.getUsername():null);
saveOperate(log);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} public Log newLog(LogAudit audit,String operation){
Log log=new Log();
log.setAction(operation);
log.setCommand(audit.getOperate());
log.setActiontime(new Date());
return log;
}
/**
* 生成日志
* @param session
* @param entry
*/
private void saveOperate(final Log entry) {
//在新的线程中打开hibernate session,解决页面数据不同不问题.
new Thread(new Runnable() {
public void run() {
TxtContentService txtContentService = (TxtContentService) AppContextUtils.getBean("txtContentService");
txtContentService.saveObject(entry);
}
}).start();
}
/**
* 读取需做日志记录的XML配置文件
* @return
*/ static{
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc = builder.parse(LogAudit.class.getClassLoader().getResourceAsStream("auditLog.xml")); // 获取到xml文件
Element root = doc.getDocumentElement(); // 获取根元素
NodeList logAudits = root.getElementsByTagName("entity");
LogAudit log =null;
for (int i = 0; i < logAudits.getLength(); i++) {
Element ss = (Element) logAudits.item(i);
log= new LogAudit();
log.setClazz(ss.getAttribute("clazz")); //实体类
log.setDescription(ss.getAttribute("description")); //操作说明
log.setOperate(ss.getAttribute("operate")); //操作项
NodeList propertys = ss.getElementsByTagName("property");//属性
Map<String,String> proMap=new HashMap<String,String>();
for(int j = 0; j < propertys.getLength(); j++){
Element e = (Element) propertys.item(j);
proMap.put(e.getAttribute("name"), e.getTextContent());
}
log.setProperty(proMap);
logAuditMap.put(ss.getAttribute("clazz"), log);
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

最后auditLog.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<entities >
<!-- 记录的日志的实体类 -->
<entity clazz="User" description="用户" operate="用户管理">
<property name="username">用户名</property>
<property name="type">人员类型</property>
<property name="realname">真实姓名</property>
</entity>
<entity clazz="Datadictionary" description="数据字典" operate="数据字典管理">
<property name="name">分类名称</property>
<property name="optionName">选项名称</property>
<property name="mtype">所属类型</property>
</entity> </entities>

末尾附上相关model代码

Log.class

package com.cqta.dev.model.log;

import java.util.Date;

public class Log {
private int id;
private String action;// 用户所执行的数据操作:增|删|改
private String command;//执行的操作
private Date actiontime;// 执行此操作的时间
private String actionUserName;//操作者姓名
private int actionUserId;//操作者姓名
private String description;//操作说明
public String getAction() {
return action;
} public void setAction(String action) {
this.action = action;
} public String getCommand() {
return command;
} public void setCommand(String command) {
this.command = command;
} public Date getActiontime() {
return actiontime;
} public void setActiontime(Date actiontime) {
this.actiontime = actiontime;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getDescription() {
return description;
} public void setDescription(String description) {
this.description = description;
} public String getActionUserName() {
return actionUserName;
} public void setActionUserName(String actionUserName) {
this.actionUserName = actionUserName;
} public int getActionUserId() {
return actionUserId;
} public void setActionUserId(int actionUserId) {
this.actionUserId = actionUserId;
} }

Log.hbm.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.cqta.dev.model.log.Log" table="log" >
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="action" type="string">
<column name="action">
</column>
</property>
<property name="command" type="string">
<column name="command">
</column>
</property>
<property name="description" type="string">
<column name="description">
</column>
</property>
<property name="actionUserId" type="java.lang.Integer">
<column name="actionUserId">
</column>
</property>
<property name="actionUserName" type="string">
<column name="actionUserName">
</column>
</property>
<property name="actiontime" type="date">
<column name="actiontime">
</column>
</property> </class>
</hibernate-mapping>

LogAudit.class

package com.cqta.dev.model.log;

import java.util.Map;

public class LogAudit {
private String description;//操作说明
private String clazz;//需要记录日志的类
private String operate;////操作项
private Map<String,String> property;
public String getDescription() {
return description;
} public void setDescription(String description) {
this.description = description;
} public String getOperate() {
return operate;
} public void setOperate(String operate) {
this.operate = operate;
} public String getClazz() {
return clazz;
} public void setClazz(String clazz) {
this.clazz = clazz;
} public Map<String,String> getProperty() {
return property;
} public void setProperty(Map<String,String> property) {
this.property = property;
}
}

mysql.sql-log

CREATE TABLE `log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`action` varchar(255) DEFAULT NULL,
`command` varchar(255) DEFAULT NULL,
`actiontime` date DEFAULT NULL,
`actionUserName` varchar(255) DEFAULT NULL,
`actionUserId` int(11) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

/*
Navicat MySQL Data Transfer

Source Server : server
Source Server Version : 50602
Source Host : localhost:3306
Source Database : zy_dev

Target Server Type : MYSQL
Target Server Version : 50602
File Encoding : 65001

Date: 2014-12-15 16:55:42
*/

SSH基于Hibernate eventListener 事件侦听器的操作日志自动保存到数据库的更多相关文章

  1. JavaScript DOM高级程序设计 4.3控制事件流和注册事件侦听器--我要坚持到底!

    一.事件流 我们通过下面一个实例,进行说明. <body> <h1>Event Flow</h1> <ul id="nav"> &l ...

  2. js事件流、事件处理程序/事件侦听器

    1.事件流 事件冒泡 IE的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档). 事件捕获 ...

  3. Android事件侦听器回调方法浅谈

    http://developer.51cto.com/art/201001/180846.htm Android事件侦听器作为视图View类的接口,其中包含有不少回调方法,比如:onClick():o ...

  4. javascript中事件总结&通用的事件侦听器函数封装&事件委托

    前言: JAVASCRIPT与HTML之间的交互是通过事件来实现的.事件,就是文档或浏览器窗口中发生的一些特定交互瞬间.可以使用侦听器( 或处理程序 )来预定事件,以便事件发生时执行相应的代码.这种在 ...

  5. 052_末晨曦Vue技术_处理边界情况之程序化的事件侦听器

    程序化的事件侦听器 点击打开视频讲解更详细 现在,你已经知道了 $emit 的用法,它可以被 v-on 侦听,但是 Vue 实例同时在其事件接口中提供了其它的方法.我们可以: 通过 $on(event ...

  6. 【JavaScript代码实现二】通用的事件侦听器函数

    // event(事件)工具集,来源:github.com/markyun markyun.Event = { // 页面加载完成后 readyEvent : function(fn) { if (f ...

  7. Unity3D 自定义事件(事件侦听与事件触发)

    先来看下效果图,图中点击 Cube(EventDispatcher),Sphere(EventListener)以及 Capsule(EventListener)会做出相应的变化,例子中的对象相互之间 ...

  8. java里的MouseLisetener接口的使用过程==========需要用组件是来注册侦听器

    总结:通过匿名类来实现鼠标的监听或者  通过实现接口的方法都可以的 从此是实现MouseListener接口的方式 package com.a.b; import java.awt.Color; im ...

  9. 异常将上下文初始化事件发送到类的侦听器实例.[org.springframework.web.context.ContextLoaderListener] org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class p

    严重: 异常将上下文初始化事件发送到类的侦听器实例.[org.springframework.web.context.ContextLoaderListener]org.springframework ...

随机推荐

  1. VS2010里, using System.Data.OracleClient; 不可用

    当我试图去引用System.Data.OracleClient 这个命名空间时,VS 显示不存在 但是在对象浏览器里却可以找到这个命名空间及里边的对象 另外好像也没有区分清楚 using 和Refer ...

  2. Theoretical comparison between the Gini Index and Information Gain criteria

    Knowledge Discovery in Databases (KDD) is an active and important research area with the promise for ...

  3. Python开发入门与实战21-订阅事件(subscribe)

    21. 订阅事件(subscribe) 新用户关注微信公众平台,将产生一个订阅事件,即subscribe事件,在新用户关注公众平台后为新用户提供一些简明扼要的公众号说明 事件推送(event): 接收 ...

  4. Mvc api HelpPage 与注释

    一.添加包Microsoft.AspNet.WebApi.HelpPage可以自动给api生成帮助页面,url:/help 二.help加注释: 1. 2. public static class H ...

  5. (转) 浅析HTML5在移动应用开发中的使用

    (转)浅析HTML5在移动应用开发中的使用 (原)http://www.iteye.com/magazines/67   2012-03-07  来自 UECD.163.com  编辑 wangguo ...

  6. 将JavaScript 插入网页的方法

    将JavaScript 插入网页的方法 使用Javascript代码. 插入JavaScript 与在网页中插入CSS的方式相似.使用下面的代码可以在网页中插入JavaScript: ... 其中的. ...

  7. Eclipse下.project和.classpath作用(转)

    classpath作用 定义项目的结构,如src.output.con.lib等. 源文件的具体位置(kind="src") 运行的系统环境(kind="con" ...

  8. iOS中修改头部tabBarButton 默认按钮的颜色和默认字体颜色

    +(void)initialize { //初始化设置主题 UINavigationBar *navBar = [UINavigationBar appearance]; [navBar setBac ...

  9. JDom2的Xpath使用

    /** * XPath获取属性值 * @param root * @param xPath * @return */ public static String getXPathAttributeVal ...

  10. MFC 屏幕截图方法

    //获取当前屏幕的并且保存图片 LRESULT CFeetScanView::SaveViewBMP(WPARAM wParam, LPARAM lParam) { CRect rect; this- ...