利用Spring的AOP进行日志记录

场景:在用户每次调用Service接口的时候,要求系统自动保存一条操作记录到数据库。记录的内容为:用户名   操作内容  操作时间内

 

现在,我们就来实现这个场景,步骤如下

1、数据库创建日志记录表

CREATE TABLE t_log (  
   id  int NOT NULL PRIMARY KEY  AUTO_INCREMENT,  
   username varchar(100)  comment '用户名',  
   createdate timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建日期',  
   operation varchar(1000) NOT NULL DEFAULT '' COMMENT '用户所做的操作'  
) comment '日志';

 

2、SSH框架中配置该日志记录表实体映射关系

实体类TLog.java:

package edu.po;

import java.sql.Timestamp;

/**
 * TLog entity. @author MyEclipse Persistence Tools
 */

public class TLog implements java.io.Serializable {

	// Fields

	private Integer id;
	private String username;
	private Timestamp createdate;
	private String operation;

	// Constructors

	/** default constructor */
	public TLog() {
	}

	/** full constructor */
	public TLog(String username, Timestamp createdate, String operation) {
		this.username = username;
		this.createdate = createdate;
		this.operation = operation;
	}

	// Property accessors

	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getUsername() {
		return this.username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public Timestamp getCreatedate() {
		return this.createdate;
	}

	public void setCreatedate(Timestamp createdate) {
		this.createdate = createdate;
	}

	public String getOperation() {
		return this.operation;
	}

	public void setOperation(String operation) {
		this.operation = operation;
	}

}

 

实体类和数据库表映射关系TLog.hbm.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="edu.po.TLog" table="t_log" catalog="test">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="native" />
        </id>
        <property name="username" type="java.lang.String">
            <column name="username" length="100" >
                <comment>用户名</comment>
            </column>
        </property>
        <property name="createdate" type="java.sql.Timestamp">
            <column name="createdate" length="0" not-null="true">
                <comment>创建日期</comment>
            </column>
        </property>
        <property name="operation" type="java.lang.String">
            <column name="operation" length="400" not-null="true">
                <comment>用户所做的操作</comment>
            </column>
        </property>
    </class>
</hibernate-mapping>


在applicationContext.xml配置文件的SessionFactory bean中添加TLog.hbm.xml文件的路径配置,如下:

	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<!--
		 添加hibernate配置 
		<property name="configLocation">
		   <value>classpath:hibernate.cfg.xml</value>
		</property>
		-->
		<property name="dataSource" ref="dataSource">
		</property>
		<property name="hibernateProperties">
		    <props>
	           <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>
	           <!--
	           <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
	           -->	           
	           <!--
	           <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
	           -->
	           <prop key="hibernate.show_sql">true</prop>
	           <prop key="hibernate.format_sql">true</prop>
		    </props>
		</property>
		<property name="mappingResources">
		    <list>
		       <value>edu/po/TLog.hbm.xml</value>
		    </list>
		</property>
	</bean>

 

3、保存日志实体的Dao

ILogDao.java:

package edu.dao;

import edu.po.TLog;

public interface ILogDao {
	public void save(TLog log) throws Exception;
}


LogDaoImpl.java:

package edu.dao.impl;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import edu.dao.ILogDao;
import edu.po.TLog;

public class LogDaoImpl extends HibernateDaoSupport implements ILogDao {

	@Override
	public void save(TLog log) throws Exception {
		this.getHibernateTemplate().save(log);
	}

}

 

4、写Aspect切面类

ILogAspect.java:

package edu.log;

import org.aspectj.lang.JoinPoint;

public interface ILogAspect {
	
	
	/**
	 * 有参无返回值的方法
	 * @param point
	 */
	public void logArg(JoinPoint point);
	
	/**
	 *有参并有返回值的方法
	 * @param point
	 * @param returnObj
	 */
	public void logArgAndReturn(JoinPoint point, Object returnObj);
	

}


LogAspectImpl.java:

package edu.log.impl;

import java.sql.Timestamp;
import java.util.Date;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import utils.JsonUtils;
import utils.StringUtils;
import edu.dao.ILogDao;
import edu.log.ILogAspect;
import edu.po.TLog;
import edu.threadlocal.LocalRequestContextHolder;
import edu.vo.UserVO;

public class LogAspectImpl implements ILogAspect {
	
	private Logger logger = Logger.getLogger(LogAspectImpl.class);
	private ILogDao logDao;

	private TLog parseJoinPoint(JoinPoint point) {
		StringBuilder operator = new StringBuilder();
		TLog logEntity = new TLog();
		
		//当前用户信息
		UserVO currentUser = LocalRequestContextHolder.getLocalRequestContext().getCurrentUser();
		if(currentUser != null){
			operator.append("用户:" + currentUser.getUsername() + ",");
			logEntity.setUsername(currentUser.getUsername());
		}
		
		//操作
		operator.append("操作:");
		operator.append(point.getTarget().getClass().getName())
		       .append(".")
			   .append(point.getSignature().getName())
			   .append("方法,");
		operator.append("参数:");
		Object[] args = point.getArgs();
		if (args != null) {
			operator.append("(");
			int i = 1;
			for (Object obj : args) {
				operator.append(obj.getClass()).append(" : ").append(JsonUtils.converToJsonStr(obj));
				if(i == args.length){
					break;
				}
				operator.append(",");
				i++;
			}
			operator.append(")");
		}
		
		logEntity.setOperation(operator.toString());
		logEntity.setCreatedate(new Timestamp(new Date().getTime()));
		
		return logEntity;
	}

	/**
	 * 有参无返回值的方法
	 * 
	 * @param point
	 */
	@Override
	public void logArg(JoinPoint point) {
		TLog logEntity = parseJoinPoint(point);
		save(logEntity);
        logger.info(logEntity.getOperation());
	}

	/**
	 * 有参并有返回值的方法
	 * 
	 * @param point
	 * @param returnObj
	 */
	@Override
	public void logArgAndReturn(JoinPoint point, Object returnObj) {
		TLog logEntity = parseJoinPoint(point);
		StringBuilder opeartor = new StringBuilder();
		opeartor.append(logEntity.getOperation())
		        .append("执行结果是:")
		        .append(returnObj);
		logEntity.setOperation(opeartor.toString());
		save(logEntity);
        logger.info(logEntity.getOperation());
	}


	private boolean save(TLog log) {
		// TODO Auto-generated method stub
		boolean success = true;
		try{
			this.logDao.save(log);
		}catch(Exception e){
			success = false;
			logger.info(StringUtils.getExceptionMessage(e));
		}
		
		return success;
	}

	public ILogDao getLogDao() {
		return logDao;
	}

	public void setLogDao(ILogDao logDao) {
		this.logDao = logDao;
	}
	

}

 

LocalRequestContextHolder的实现见博客:通过ThreadLocal和Filter实现请求上下文【更新】

5、Spring的applicationContext.xml中进行AOP配置

在applicationContext.xml文件中添加以下配置:

	<bean id="logDao" class="edu.dao.impl.LogDaoImpl" scope="singleton">
	    <property name="sessionFactory" ref="sessionFactory">
	    </property>
	</bean>
	<!--利用AOP添加日志记录 -->
	<bean id="logAspectClass" class="edu.log.impl.LogAspectImpl">
	   <property name="logDao" ref="logDao"></property>
	</bean>
	<aop:config>
	    <aop:pointcut id="logPointcut" expression="execution(* edu.service.impl.*.*(..))"/>
	    <aop:aspect id="logAspect" ref="logAspectClass">
	         <aop:after method="logArg" pointcut-ref="logPointcut"/> 
	         <!-- 
	         <aop:after-returning method="logArgAndReturn" arg-names="point,returnObj" returning="returnObj" pointcut-ref="logPointcut"/>
	         -->
	    </aop:aspect> 
	</aop:config>	

项目demo: https://github.com/zengyh/SSHWebProject.git

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值