一,功能点
实现管理员操作数据的记录。效果如下
二,代码实现
基于注解的Aop日志记录
1.Log实体类
package com.vulcan.facade.operationlog.entity;
import lombok.Data;
import org.springframework.data.annotation.Id;
import javax.persistence.Column;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;
/**
* @author lzh
* @version 1.0
* @describe 操作日志
* @date 20190413
* @copyright by lzh
*/
@Data
@Table(name = "*****")
public class OperationLog implements Serializable {
/**
* 主键id
*/
@Id
private Long id;
/**
* 用户id
*/
@Column(name = "user_id")
private Long userId;
/**
* 用户名称
*/
@Column(name = "user_name")
private String userName;
/**
* 描述
*/
@Column(name = "description")
private String description;
/**
* 模块
*/
@Column(name = "module")
private String module;
/**
* 操作详情
*a
*/
@Column(name = "content")
private String content;
/**
* 请求ip
*
*/
@Column(name = "ip")
private String ip;
/**
* 创建时间
*/
@Column(name = "create_time")
private Date createTime;
}
2.定义注解
package com.vulcan.log.annotation;
import java.lang.annotation.*;
/**
* @author lzh
* @date 20190413
* 定义注解
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/**模块*/
String module() default "";
/**描述*/
String description() default "";
}
3.定义切面
package com.vulcan.log.aop;
import com.vulcan.base.BaseController;
import com.vulcan.facade.permission.vo.SessionUserVO;
import com.vulcan.log.annotation.Log;
import com.vulcan.log.service.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* 日志切面
* @author vlzh
* @date 20190413
*/
@Aspect
@Component
public class LogAspect extends BaseController {
@Autowired
private LogService logService;
/**
* 日志切入点
*/
@Pointcut("@annotation(com.vulcan.log.annotation.Log)")
public void logPointCut(){}
@AfterReturning(pointcut = "logPointCut()")
public void doAfter(JoinPoint joinPoint){
/**
* 解析Log注解
*/
SessionUserVO sessionUserVO = getLoginUser();
String methodName = joinPoint.getSignature().getName();
Method method = currentMethod(joinPoint,methodName);
Log log = method.getAnnotation(Log.class);
String module = log.module();
String description = log.description();
logService.put(joinPoint,methodName,module,description,sessionUserVO.getUserName(),sessionUserVO.getId());
}
/**
* 获取当前执行的方法
*
* @param joinPoint 连接点
* @param methodName 方法名称
* @return 方法
*/
private Method currentMethod(JoinPoint joinPoint, String methodName) {
/**
* 获取目标类的所有方法,找到当前要执行的方法
*/
Method[] methods = joinPoint.getTarget().getClass().getMethods();
Method resultMethod = null;
for (Method method : methods) {
if (method.getName().equals(methodName)) {
resultMethod = method;
break;
}
}
return resultMethod;
}
}
4.业务处理:LogService
package com.vulcan.log.impl;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.vulcan.common.util.http.IPUtil;
import com.vulcan.facade.operationlog.entity.OperationLog;
import com.vulcan.facade.operationlog.service.OperationLogService;
import com.vulcan.facade.operationlog.vo.OperationLogVO;
import com.vulcan.log.service.LogService;
import javassist.*;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
@Component
@Slf4j
public class LogServiceImpl implements LogService {
private static final String LOG_CONTENT = "[类名]:%s,[方法]:%s,[参数]:%s,[IP]:%s";
private String username;
@Reference(version = "1.0.0")
private OperationLogService operationLogService;
public String initUsername(String username) {
if(!StringUtils.isEmpty(username)){
this.username = username;
}
return this.username;
}
public void put(JoinPoint joinPoint, String methodName, String module, String description, String userName, Long userId) {
try {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
OperationLog log = new OperationLog();
if (StringUtils.isEmpty(userName)) {
username = "未知用户";
}
String ip = IPUtil.getIpAddress(request);
log.setUserId(userId);
log.setUserName(userName);
log.setModule(module);
log.setCreateTime(new Date());
log.setDescription(description);
log.setIp(ip);
log.setContent(operateContent(joinPoint, methodName, ip, request));
operationLogService.insert(log);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 查询所有日志
* @param pageNum
* @param request
* @return
*/
public List<OperationLogVO> findAllLog(int pageNum, HttpServletRequest request) {
return null;
}
public String operateContent(JoinPoint joinPoint, String methodName, String ip, HttpServletRequest request) throws ClassNotFoundException, NotFoundException {
String className = joinPoint.getTarget().getClass().getName();
Object[] params = joinPoint.getArgs();
String classType = joinPoint.getTarget().getClass().getName();
Class<?> clazz = Class.forName(classType);
String clazzName = clazz.getName();
Map<String,Object > nameAndArgs = getFieldsName(this.getClass(), clazzName, methodName,params);
StringBuffer bf = new StringBuffer();
if (!CollectionUtils.isEmpty(nameAndArgs)){
Iterator it = nameAndArgs.entrySet().iterator();
while (it.hasNext()){
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
String value = JSONObject.toJSONString(entry.getValue());
bf.append(key).append("=");
bf.append(value).append("&");
}
}
if (StringUtils.isEmpty(bf.toString())){
bf.append(request.getQueryString());
}
return String.format(LOG_CONTENT, className, methodName, bf.toString(), ip);
}
private Map<String,Object> getFieldsName(Class cls, String clazzName, String methodName,Object[] args) throws NotFoundException {
Map<String,Object > map=new HashMap<String,Object>();
ClassPool pool = ClassPool.getDefault();
ClassClassPath classPath = new ClassClassPath(cls);
pool.insertClassPath(classPath);
CtClass cc = pool.get(clazzName);
CtMethod cm = cc.getDeclaredMethod(methodName);
MethodInfo methodInfo = cm.getMethodInfo();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
if (attr == null) {
// exception
return map;
}
int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
for (int i = 0; i < cm.getParameterTypes().length; i++){
map.put( attr.variableName(i + pos),args[i]);//paramNames即参数名
}
return map;
}
}
5、mapper
package com.vulcan.facade.mapper;
import com.vulcan.common.core.base.BaseMapper;
import com.vulcan.facade.operationlog.entity.OperationLog;
import org.springframework.stereotype.Repository;
@Repository
public interface LogMapper extends BaseMapper<OperationLog> {
}
三,使用注解在需要的地方记录日志
/**
* @author: lzh
* @description:获取订单列表数据
* @createDate: 14:06 2019/04/04
* @param orderDTO
* @param pagebean
* @return: Result
* @version: 1.0
*/
@Log(module = "订单监控",description = "订单列表")
@RequestMapping(value = "list", method = RequestMethod.POST)
@ResponseBody
public Result getOrderListPage(OrderDTO orderDTO, PageBean pagebean){
log.info("分页查询订单参数queryOrderDTO={},pageBean={}", JSON.toJSONString(orderDTO),JSON.toJSONString(pagebean));
Result result = this.getListOrder(orderDTO,pagebean);
log.info("分页查询订单处理结果result={}", JSON.toJSONString(result));
return result;
}