AOP日志
作用:记录你对系统的操作
数据库表结构
1、信息获取
图解:
代码:
package com.itheima.controller;
import com.itheima.ssm.domain.SysLog;
import com.itheima.ssm.service.SysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
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.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;
@Component
@Aspect
@Transactional
public class LogAop {
//配置后,自定注入request
@Autowired
private HttpServletRequest request;
@Autowired
private SysLogService sysLogService;
private Date visitTime;//开始时间
private Class clazz;//访问的类
private Method method;//访问的方法
//前置通知 主要获取开始时间,执行得类是哪一个,执行的是哪一个方法
@Before("execution(* com.itheima.controller.*.*(..))")
public void doBefore(JoinPoint jp) throws Exception {
visitTime=new Date();//当前时间就是开始访问的时间
clazz=jp.getTarget().getClass();//具体要访问的类
String methodName=jp.getSignature().getName();//获取访问的方法的名称
Object[] args = jp.getArgs();//获取访问的方法的参数
//获得具体执行的Method对象
if (args == null || args.length==0) {
method=clazz.getMethod(methodName); //只能获得无参的方法
}else{
Class[] classAres=new Class[args.length];
//把每一个参数的class拿到放在Class数组里
for (int i = 0; i <args.length ; i++) {
classAres[i]=args[i].getClass();
}
clazz.getMethod(methodName,classAres);//获得有参方法
}
}
//后置通知
@After("execution(* com.itheima.controller.*.*(..))")
public void doAfter(JoinPoint jp){
//获得访问时长
long time = new Date().getTime() - visitTime.getTime();
//获得url,通过反射对注解进行操作
String url="";
if(clazz!=null && method!=null && clazz!=LogAop.class ){
//1.获得类上的@RequestMapping("/orders")
RequestMapping clazzAnnotation =(RequestMapping) clazz.getAnnotation(RequestMapping.class);
if (clazzAnnotation != null) {
String[] classValue = clazzAnnotation.value();
//2.获得方法上的@RequestMapping("/。。")
RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
if (methodAnnotation != null) {
String[] methodValue = methodAnnotation.value();
url=classValue[0]+methodValue[0];
}
}
//获取当前的ip
String ip=request.getRemoteAddr();
//获得用户名
//1、从上下文中获得了当前登录的用户
SecurityContext context= SecurityContextHolder.getContext();
User user= (User) context.getAuthentication().getPrincipal();//获得操作对象
String username=user.getUsername(); //获得对象的名称
//将数据封装到SysLog里面
SysLog sysLog=new SysLog();
sysLog.setUsername(username);
sysLog.setExecutionTime(time);
sysLog.setIp(ip);
sysLog.setUrl(url);
sysLog.setMethod("[类名]"+clazz.getName()+"[方法名]"+method.getName());
sysLog.setVisitTime(visitTime);
//调用service完成数据库的插入操作(即日志记录)
sysLogService.save(sysLog);
}
}
}
2、插入数据库
将获取的信息封装后,插入数据库
和之前的商品插入用户插入等方法一样
需要注意的是,使用注解切面@Aspect,不要忘记在配置文件(springmvc.xml)中配置
<aop:aspectj-autoproxy expose-proxy=“true”></aop:aspectj-autoproxy>
遇到的错误,以及解决参考Spring MVC中AOP无效、不起作用