码迷,mamicode.com
首页 > 数据库 > 详细

SSH基于Hibernate eventListener 事件侦听器的操作日志自动保存到数据库

时间:2014-12-15 18:34:54      阅读:325      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   io   ar   color   os   sp   

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

相关代码如下:

首先spring xml

bubuko.com,布布扣
<?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>
View Code

然后LogAuditListener.java代码

bubuko.com,布布扣
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();
  }
 }
}
View Code

最后auditLog.xml文件

bubuko.com,布布扣
<?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>
View Code

末尾附上相关model代码

Log.class

bubuko.com,布布扣
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;
    }

}
View Code

Log.hbm.xml

bubuko.com,布布扣
<?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>
View Code

LogAudit.class

bubuko.com,布布扣
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;
}
}
View Code

mysql.sql-log 

bubuko.com,布布扣
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;
View Code

/*
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 事件侦听器的操作日志自动保存到数据库

标签:des   style   blog   http   io   ar   color   os   sp   

原文地址:http://www.cnblogs.com/vanilla-sky/p/4165245.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!