最近在做ssh项目时,有一个操作日志的功能,我是用xml配置的方式实现的,在这里做一下记录:
创建日志注解
package com.zking.crm.aop;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 操作日志注解
* @author lenovo
* @date 2018年12月27日 10:03:08
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemLog {
//对操作的描述
String action() default "";
}
创建切面通知类
package com.zking.crm.aop;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import com.opensymphony.xwork2.ActionContext;
import com.zking.crm.biz.ILogBiz;
import com.zking.crm.entity.User;
public class OperationLogAspect{
private ILogBiz iLogBiz;
public ILogBiz getiLogBiz() {
return iLogBiz;
}
public void setiLogBiz(ILogBiz iLogBiz) {
this.iLogBiz = iLogBiz;
}
/**
* 环绕通知
* @param pjp
* @return
*/
public Object around(ProceedingJoinPoint pjp){
try {
//开始时间
long beginTime = System.currentTimeMillis();
//执行目标方法
Object proceed = pjp.proceed();
//执行时长 (毫秒)
long time = System.currentTimeMillis()-beginTime;
saveSystemLog(pjp, proceed, time);
return proceed;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
/**
* 保存日志
* @param joinPoint
* @param time
*/
private void saveSystemLog(ProceedingJoinPoint joinPoint, Object proceed, long time) {
/* 得到request对象
* HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
*
* 得到response对象
* HttpServletResponse response = (HttpServletResponse) ActionContext.getContext().get(ServletActionContext.HTTP_RESPONSE);
*/
//得到session
Map<String,Object> session = (Map<String,Object>)ActionContext.getContext().getSession();
//得到session中当前登录的用户
Object obj = session.get("ActiveUser");
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Map<String, String[]> sysLogMap = new HashMap<>();
/**
* 下面为我的日志表字段
* log_id 日志id(主键)
operate_user 操作的用户
operate_do 操作的动作
log_method 操作调用的方法
log_params 操作方法的参数
operate_time 操作耗时
operate_create_date 日志操作的时间
operate_flag 操作是否成功(1、成功, 2、失败)
*/
SystemLog sysLog = method.getAnnotation(SystemLog.class);
if(sysLog!=null) {
// 注解上的描述
sysLogMap.put("operate_do", new String[] {sysLog.action()});
}
// 获取目标类名
String className = joinPoint.getTarget().getClass().getName();
// 获取方法名
String methodName = signature.getName();
sysLogMap.put("log_method", new String[] {className+"."+methodName});
// 请求的参数
Object[] args = joinPoint.getArgs();
if (args != null && args.length != 0 && args[0] != null) {
sysLogMap.put("log_params", new String[] {Arrays.toString(args)});
}
//由于登录时,session中是不存在当前的登录用户,所以取用请求参数中登录的用户名
if(obj!=null) {
User user=(User)obj;
sysLogMap.put("operate_user", new String[] {user.getUser_name()});
}else {
sysLogMap.put("operate_user", new String[] {((User)args[0]).getUser_name()});
}
sysLogMap.put("operate_time", new String[] {time+""});
if(proceed!=null && proceed!="0") {
sysLogMap.put("operate_flag", new String[] {"1"});
}else {
sysLogMap.put("operate_flag", new String[] {"2"});
}
// 保存系统日志
iLogBiz.addLog(sysLogMap);
};
}
AspectJ配置文件
<bean id="logDao" class="com.zking.crm.dao.LogDao" parent="baseDao"></bean>
<bean id="logBiz" class="com.zking.crm.biz.impl.LogBizImpl">
<property name="ld" ref="logDao"></property>
</bean>
<!-- 切面类 -->
<bean id="operationLogAspect" class="com.zking.crm.aop.OperationLogAspect">
<property name="iLogBiz" ref="logBiz"></property>
</bean>
<aop:config>
<!-- 切面 -->
<aop:aspect ref="operationLogAspect">
<!-- 定义切点 -->
<aop:pointcut expression="@annotation(com.zking.crm.aop.SystemLog)" id="pt"/>
<!-- 声明环绕通知 -->
<aop:around method="around" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
在AspectJ配置文件中定义了切点的切入位置为加了@SystemLog注解的方法中(即标有@SystemLog注解的方法才会保存到数据库中)