首页 > 代码库 > SSH基于Hibernate eventListener 事件侦听器的操作日志自动保存到数据库
SSH基于Hibernate eventListener 事件侦听器的操作日志自动保存到数据库
- 在spring xml配置文件中添加配置,包含:model、listener
- 在model中增加需要写入数据库对应表的model
- 在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 事件侦听器的操作日志自动保存到数据库
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。