1.导入依赖
<!--切面aop-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.19</version>
</dependency>
<!--Spring Security-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.6.9</version>
</dependency>
2.创建数据库表,实体类用来保存日志
实体类
package com.xs.entity;
import lombok.Data;
import java.util.Date;
/**
* @Author 杨
* @CreateDate 2023-06-24 16:06
**/
@Data
public class SysLog {
private int id;
private Date visitTime;
private String username;
private String ip;
private String url;
private Integer executionTime;
private String method;
}
数据库
3.编写工具类来监控日志,并保存到数据库表中
package com.xs.log;
import com.xs.entity.SysLog;
import com.xs.entity.User;
import com.xs.service.SysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.validation.support.BindingAwareModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
//import org.springframework.security.core.userdetails.User;
/**
* @Author 杨
* @CreateDate 2023-06-24 15:56
**/
@Component
@Aspect
public class LogAop {
//注入request
@Autowired
private HttpServletRequest request;
//注入service
@Autowired
private SysLogService sysLogService;
private Date visitTime; //访问时间
private Class clazz; //访问的类
private Method method; //访问的方法
/*
//配置切入点
@Pointcut("execution(* com.itheima.ssm.controller.*.*(..))")
public void pt() {
}*/
//前置通知
@Before("execution(public * com.xs.controller.*.*(..))")
public void doBefore(JoinPoint joinPoint) throws NoSuchMethodException {
visitTime = new Date (); //获取访问时间
clazz = joinPoint.getTarget ().getClass (); //获取访问的类
String methodName = joinPoint.getSignature ().getName (); //获取访问的方法的名称
//获取方法参数
Object[] args = joinPoint.getArgs ();
//通过反射获取Method
if (args == null || args.length == 0) {
method = clazz.getMethod (methodName); //只能获取无参的方法
} else {
Class[] classes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
//Model 类型的参数注入的是BindingAwareModelMap类,这个类是Model接口实现类的ExtendedModelMap类的子类
if(args[i] instanceof BindingAwareModelMap){
//将子类BindingAwareModelMap强转为父类ExtendedModelMap,这个类是Model接口的实现类 clazz.getMethod (methodName, classes); 就不会出现类型转换异常
classes[i] = Model.class;
continue;
}
classes[i] = args[i].getClass ();
}
method = clazz.getMethod (methodName, classes);
}
}
//后置通知 主要获取日志中其它信息,时长、ip、url...
@AfterReturning("execution(public * com.xs.controller.*.*(..))")
public void doAfter() {
//获取url --> /orders/findAll.do
String url = "";
if (clazz != null && method != null && clazz != LogAop.class) {
//1.获取类上 @RequestMapping("/product") 注解中的value值
RequestMapping clazzAnnotation = (RequestMapping) clazz.getAnnotation (RequestMapping.class);
if (clazzAnnotation != null) {
String[] classValue = clazzAnnotation.value ();
//2.获取方法上 @RequestMapping("/findAll.do") 注解中的value值
RequestMapping methodAnnotation = method.getAnnotation (RequestMapping.class);
if (methodAnnotation != null) {
String[] methodValue = methodAnnotation.value ();
//3.获取URL
if (classValue[0] != null && methodValue[0] != null) {
url = classValue[0] + methodValue[0];
}
// String uri = request.getRequestURI ();
//获取执行时间
Long executionTime = new Date ().getTime () - visitTime.getTime ();
//获取ip 需要request获取 --》 获取request需要在web.xml中配置Listener RequestContextListener类 在注入HttpServletRequest
String ip = request.getRemoteAddr ();
//获取操作者用户名(两种方式) 1.从上下文中获取登录的对象 2.也可以从request.getSession中获取
SecurityContext context = SecurityContextHolder.getContext ();
//SecurityContext context = (SecurityContext) request.getSession ().getAttribute ("SPRING_SECURITY_CONTEXT");
//Object principal = context.getAuthentication ().getPrincipal ();
User principal = (User)request.getSession ().getAttribute("user111");
String username = "";
if (principal != null){
username=principal.getUname();
}else {
username = "还没登录";
}
/*if(principal instanceof User){
User user = (User) context.getAuthentication ().getPrincipal ();
//User user = (User) request.getSession ().getAttribute("users");;
username = user.getUname();
}else {
username = "还没登录";
}*/
//封装日志类 SysLog
SysLog sysLog = new SysLog ();
sysLog.setVisitTime (visitTime);
sysLog.setExecutionTime (Math.toIntExact(executionTime));
sysLog.setIp (ip);
sysLog.setUrl (url);
sysLog.setUsername (username);
sysLog.setMethod ("[类名]" + clazz.getName() + "[方法名]" + method.getName());
//调用service
sysLogService.save(sysLog);
}
}
}
}
}