1、定义一个注解类
package com.staryea.annotation.operlog;
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 韩俊
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperLog {
// 菜单名称,如数据项
String name();
// 功能名称,如分页查询
String desc();
// 操作类型
OperLogEnum action();
// 是否插入请求参数
boolean isAddParam() default true;
}
2、定义一个切面类来实现功能
package com.staryea.annotation.operlog;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson.JSON;
import com.app.frame.util.Base64Encrypt;
import com.app.frame.util.IpUtil;
import com.app.frame.util.PageData;
import com.staryea.util.DateUtil;
import com.staryea.util.StringUtil;
/**
* 操作日志切面
* @author 韩俊
*/
@Aspect
@Component
public class OperLogAspect {
private static final org.apache.commons.logging.Log logger = LogFactory.getLog(OperLogAspect.class);
@Autowired
private OperLogMapper operLogMapper;
// 切点
@Pointcut("@annotation(com.staryea.annotation.operlog.OperLog)")
public void log() {
}
@Before(value = "log()")
public void logBefore(JoinPoint joinPoint) {
try {
//获取当前类象
Class> clazz = joinPoint.getTarget().getClass();
// 获取当前类的执行的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = clazz.getMethod(signature.getMethod().getName(), signature.getMethod().getParameterTypes());
// 获取注解里的参数
OperLog log = method.getAnnotation(OperLog.class);
// 获取请求参数
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String param = JSON.toJSON(new PageData(request)).toString();
String url = request.getRequestURL().toString();// 获取请求路径
String name = log.name();// 获取菜单名称
String desc = log.desc();// 获取功能名称
String action = log.action().name();// 获取操作类型
boolean isAddParam = log.isAddParam();// 获取是否插入参数
param = isAddParam ? param : null;
String staff = getStaff(request);// 获取操作人
String ip = IpUtil.getIpAddr(request);
// 入库
PageData addPd = new PageData();
addPd.put("id", StringUtil.getUUID());
addPd.put("url", url);
addPd.put("name", name);
addPd.put("desc", desc);
addPd.put("action", action);
addPd.put("param", "{}".equals(param) ? null : param);
addPd.put("ip", ip);
addPd.put("time", DateUtil.getDateTime());
addPd.put("staff", staff);
operLogMapper.add(addPd);
}
catch (Throwable t) {
logger.error("写入操作日志失败!", t);
}
}
// 从token中获取操作人
private String getStaff(HttpServletRequest request) {
try {
if (request.getHeader("Auth-Token") == null) {
return null;
}
String token = Base64Encrypt.decodeBy3DESAndBase64(request.getHeader("Auth-Token"));
if (StringUtil.isNull(token)) {
return null;
}
return token.split("_")[0];
}
catch (Exception e) {
return null;
}
}
}
3、定义一个枚举类
package com.staryea.annotation.operlog;
/**
* 操作日志类型
* @author 韩俊
*/
public enum OperLogEnum {
add,
update,
delete,
query,
upload,
download
}
4、DAO层
package com.staryea.annotation.operlog;
import org.apache.ibatis.annotations.Mapper;
import com.app.frame.util.PageData;
@Mapper
public interface OperLogMapper {
public int add(PageData pd);
}
5、sql
insert into ts_operation_log(
id,
url,
`name`,
`desc`,
action,
param,
ip,
time,
staff
)
values(
#{id},
#{url},
#{name},
#{desc},
#{action},
#{param},
#{ip},
#{time},
#{staff}
)
5、直接在方法上添加自定义注解
7、表结构
CREATE TABLE `ts_operation_log` (
`id` varchar(32) COLLATE utf8_unicode_ci NOT NULL COMMENT '主键',
`url` varchar(4000) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '请求地址',
`name` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '菜单名称,如数据项',
`desc` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '功能,如分页查询',
`action` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '操作类型',
`param` text COLLATE utf8_unicode_ci COMMENT '参数',
`ip` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '操作人ip,可能获取多个,如192.168.4.92,192.168.2.172,因为中间存在nginx,所以除了操作人ip还有中间代理服务器的ip',
`time` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '操作时间',
`staff` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '操作人',
PRIMARY KEY (`id`),
KEY `index_time` (`time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
8、PageData其实就是一个继承了map并且增加了一些构造方法的类,这个地方可以随你用什么东西,new PageData(request)是把请求参数put进对象里,这个你们自己实现就好。获取操作人需要跟自己的系统实际情况获取,我这个是通过页面token解析出来的。