1.添加sql脚本
- 记得添加aop和lombok依赖
- 运行sql脚本,在数据库中添加存储日志的数据库表
-- 操作日志表
create table operate_log(
id int unsigned primary key auto_increment comment 'ID',
class_name varchar(100) comment '操作的类名',
method_name varchar(100) comment '操作的方法名',
method_desc varchar(100) comment '方法用途',
method_params varchar(1000) comment '方法参数',
return_value varchar(2000) comment '返回值',
operate_user int unsigned comment '操作人ID',
operate_time datetime comment '操作时间',
cost_time bigint comment '方法执行耗时, 单位:ms'
) comment '操作日志表';
2.添加mysql语句
- 用于执行添加日志到数据库
- SUBSTRING(#{returnValue},0,1500) : 如果日志查询到过多的数据会在函数里过滤掉
/**
* 日志
*/
@Mapper
public interface OperateLogMapper {
//插入日志数据
//SUBSTRING(#{returnValue},0,1500)如果查询的的数据量过大需要使用subString函数来截取过多的数据
@Insert("insert into db_health.operate_log (operate_user, operate_time, class_name, method_name,method_desc, method_params, return_value, cost_time) " +
"values (#{operateUser}, #{operateTime}, #{className}, #{methodName},#{methodDesc}, #{methodParams}, SUBSTRING(#{returnValue},0,1500), #{costTime});")
public void insert(OperateLog log);
}
3.添加实体类
- 用于封装查询到的日志数据
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 日志实体类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog {
private Integer id; //ID
private String className; //操作类名
private String methodName; //操作方法名
private String methodDesc; //方法用途
private String methodParams; //操作方法参数
private String returnValue; //操作方法返回值
private Integer operateUser; //操作人ID
private LocalDateTime operateTime; //操作时间
private Long costTime; //操作耗时
}
4.自定义日志注解
- 自定义的作用是标注需要切面的方法
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义注解 日志
*/
@Retention(RetentionPolicy.RUNTIME) //保留到运行阶段
@Target({ElementType.METHOD}) //标注在方法上
public @interface LogAnno {
String methodDesc() default ""; //方法引用
}
5.使用Aop切面
package com.health.aspect;
import com.health.anno.LogAnno;
import com.health.domain.OperateLog;
import com.health.mapper.OperateLogMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
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 javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;
/**
* AOP记录日志的切面
*/
@Aspect
@Component
public class LogAspect {
@Autowired
private HttpServletRequest request;
@Autowired
private OperateLogMapper operateLogMapper;
//切点 标注anno注解的方法都被切中
@Pointcut("@annotation(com.health.anno.LogAnno)")
public void cf(){}
//环绕通知
@Around("cf()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
OperateLog operateLog = new OperateLog();
//获取类名
operateLog.setClassName(pjp.getTarget().getClass().getName());
//获取方法参数
operateLog.setMethodParams(Arrays.toString(pjp.getArgs()));
//import org.aspectj.lang.reflect.MethodSignature; 获取签名
MethodSignature signature = (MethodSignature) pjp.getSignature();
//获取方法名
operateLog.setMethodName(signature.getMethod().getName());
LogAnno logAnno = signature.getMethod().getAnnotation(LogAnno.class);
//获取方法描述
operateLog.setMethodDesc(logAnno.methodDesc());
String token = request.getHeader("token");
Claims claims = JwtUtils.parseJWT(token);
//拿到用户id
Integer id = claims.get("id", Integer.class);
//操作id
operateLog.setOperateUser(id);*/
//操作时间
operateLog.setOperateTime(LocalDateTime.now());
long begin = System.currentTimeMillis();
Object object = pjp.proceed();
long end = System.currentTimeMillis();
//方法执行时间
operateLog.setCostTime(end - begin);
//方法返回信息 如果日志查询到的数据过多需要在sql语句 SUBSTRING(#{returnValue},0,1500),限定添加的字数
operateLog.setReturnValue(object.toString());
//落库
operateLogMapper.insert(operateLog);
return object;
}
}
6.在需要执行的方法上添加@LogAnno(methodDesc = "xxx")注解
@PutMapping
@LogAnno(methodDesc = "修改部门数据")
public Result updateDept(@RequestBody Dept dept){
deptService.updateDept(dept);
return Result.success();
- 前端只要访问带有这个注解的方法,aop就会把数据添加到数据库的日志表中.