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. 10款html5开发工具,实用+好用

    利用HTML5工具不仅可以帮助设计师和开发者创建更具吸引力的网站,还能增加网站的可用性和可访问性.本文收集了10款HTML5开发工具让你在网页中搭建特效.动画.视频.音频等诸多功能,为你节省更多开发时 ...

  2. [Linux-脚本]排序、统计、合并命令

    1.排序命令 - sort: sort可以帮我们进行排序,排序顺序按照LANG(语系环境变量)确定.据观察,sort排序以行为单位进行.排序以第一个不相同的字符决定先后顺序(只与第一个不相同的字符相关 ...

  3. 数据库:mongodb与关系型数据库相比的优缺点 (转)

    与关系型数据库相比,MongoDB的优点:①弱一致性(最终一致),更能保证用户的访问速度:举例来说,在传统的关系型数据库中,一个COUNT类型的操作会锁定数据集,这样可以保证得到“当前”情况下的精确值 ...

  4. 集成SDK查看包架构指令

    1.查看支持构架的命令是lipo -info xxxxx.a 2.合并真机和模拟器的库的命令是 lipo -create xxxx_iphoneos.a xxxx_simulator.a -outpu ...

  5. Go语言并发编程示例 分享(含有源代码)

    GO语言并发示例分享: ppt http://files.cnblogs.com/files/yuhan-TB/GO%E8%AF%AD%E8%A8%80.pptx 代码, 实际就是<<Go ...

  6. 【笔记】Service的使用

    一.创建Service 1.创建一个myService类,来继承Service.重写其中的方法,包括:onCreate(),onStartCommend(),onDestroy(),onBind()方 ...

  7. META元素使用的简单学习

    meta标签是我们学习html时容易忽略的标签,其实它的作用很大,下面就一些网上关于meta标签的讲解内容做一个简单的归纳. META标签共有两个属性,它们分别是Http-equiv属性和Name属性 ...

  8. 基于.NET的CAD二次开发学习笔记一:CAD开发入门

    1.AutoCAD .NET API由不同的DLL文件组成,它们提供用于访问图形文件或AutoCAD应用程序的包含丰富的类.结构.方法和事件.每一个DLL文件都定义不同的使用基于功能的库组织组件的命名 ...

  9. C++深拷贝与浅拷贝

    当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用.也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用.以下情况都会调用拷贝构造函数: (1)一个对 ...

  10. java异步式Socket响应数据获取方案

    项目中存在 云中央控制器需要使用多个Socket连接多个云终端控制器的需求. 由于终端数量大,就对整个中央控制器提出了并发的要求,然而获取Socket响应的过程是一个持续阻塞的过程,存在性能风险.而常 ...