1.自定义注解
package com.itheima.anno;
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 "";//方法用途
}
2.实体类
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; //操作耗时
}
3.mapper接口
@Mapper
public interface OperateLogMapper {
//插入日志数据
@Insert("insert into 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}, #{returnValue}, #{costTime});")
public void insert(OperateLog log);
}
4.控制层
package com.itheima.controller;
import com.itheima.anno.LogAnno;
@RestController
public class EmpController {
@Autowired
private EmpService empService;
@GetMapping("/emps/{id}")
@LogAnno(methodDesc = "查询员工")
public Result findById(@PathVariable("id") Integer id){
Emp emp = empService.findById(id);
return Result.success(emp);
}
@PutMapping("/emps")
@LogAnno(methodDesc = "更新员工")
public Result update(@RequestBody Emp emp){
emp.setCreateTime(LocalDateTime.now());
//emp.setUpdateTime(LocalDateTime.now());
empService.update(emp);
return Result.success();
}
}
5.切面类
package com.itheima.aspect;
import com.itheima.anno.LogAnno;
import com.itheima.domain.OperateLog;
import com.itheima.mapper.OperateLogMapper;
import com.itheima.util.JwtUtils;
import io.jsonwebtoken.Claims;
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;
//记录日志的切面
@Aspect
@Component
public class LogAspect {
@Autowired
private HttpServletRequest request;
@Autowired
private OperateLogMapper operateLogMapper;
//切点(标注)
@Pointcut("@annotation(com.itheima.anno.LogAnno)")
public void pt(){}
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
OperateLog operateLog = new OperateLog();
//获取类名
operateLog.setClassName(pjp.getTarget().getClass().getName());
//获取方法参数
operateLog.setMethodParams(Arrays.toString(pjp.getArgs()));
MethodSignature ms = (MethodSignature) pjp.getSignature();
//获取方法名
operateLog.setMethodName(ms.getMethod().getName());//方法名
LogAnno logAnno = ms.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);
operateLog.setOperateUser(id);
//操作时间
operateLog.setOperateTime(LocalDateTime.now());
long start = System.currentTimeMillis();
Object object = pjp.proceed();
long end = System.currentTimeMillis();
//方法执行时间
operateLog.setCostTime(end-start);
//方法返回信息
operateLog.setReturnValue(object.toString());
//落库
operateLogMapper.insert(operateLog);
return object;
}
}