使用AOP同一管理日志 web端的访问日志 面向切面编程实现统一管理日志 SpringAOP实现记录日志功能。

前言:

在我们访问网站的时候,每次都会以不同角色,时间,地点,用户,访问的周期时间,访问的IP进行访问,我们可以通过Spring当中面向切面编程,来实现对访问日志的记录,并将它存储进入数据库,本个Demo完全基于SSM框架

一、环境准备

1.1 创建数据库表

在这里插入图片描述

2.2 创建数据库实体类

在这里插入图片描述

再次注意,本Demo完全基于SSM,本篇文章只有关于切面编写的逻辑

二、配置切面

2.1 web配置

  • 在我们的切面类当中会用到Request对象,所以我们需要在web-xml监听requestContextListener

在这里插入图片描述

2.2 获取访问资源的切面类

  • 下面就是我们获取各个访问资源的信息。
@Component
@Aspect
public class LogAop {
    
    
    private Date visitTime; //访问时间
    private Class clazz; //访问的类
    private Method method;
    private String userName;
    private String url;
    private long executeTime; //执行的时间
    private String ip; //Ip地址

	//当我们监听request之后,我们就可以使用IOC为我们生成的req对象。	
    @Autowired
    private HttpServletRequest req;
    @Autowired
    private SystemLogService service;

    @Pointcut("execution(* com.atjianyi.controller.*.*(..))")
    private void P1(){
    
    }

    /**
     * 前置通知
     * @param pjp
     */
    @Before("P1()")
    private void beforAdvice(JoinPoint pjp) throws NoSuchMethodException {
    
    
        Object[] objs = pjp.getArgs();
        //获取访问时间
        visitTime = new Date();
        //获取当前访问
        clazz = pjp.getTarget().getClass();
        //获取方法名称
        String methodName = pjp.getSignature().getName();
        if(clazz!=null&&clazz!=LogAop.class){
    
    
            if(objs!=null && objs.length>0){
    
    
                //有参数的方法
                Class[] argsClass = new Class[objs.length];
                for (int i = 0 ; i<objs.length;i++){
    
    
                    argsClass[i] = objs[i].getClass();
                }
                method = clazz.getMethod(methodName,argsClass);
            }else{
    
    
                //无参数的方法
                method = clazz.getMethod(methodName);
            }
        }
    }


    /**
     * 后置通知
     * @param pjp
     */
    @After("P1()")
    private void afterReturn(JoinPoint pjp) {
    
    
        //执行时间
        executeTime = new Date().getTime() - visitTime.getTime();
        //获取URL(RequestMapping上)
        if(clazz!=null && method !=null && clazz!=LogAop.class){
    
    
            //获取类上和方法上的注解
            RequestMapping classAnnotation = (RequestMapping)clazz.getAnnotation(RequestMapping.class);
            RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
            if(classAnnotation!=null && methodAnnotation!=null){
    
    
                String[] value = classAnnotation.value();
                String[] value1 = methodAnnotation.value();
                url = value[0]+value1[0];
            }
        }
        //获取用户名
        userName = getUserInfoName();
        ip = req.getRemoteAddr(); //获取Ip
        saveSystemLog();
    }

	//保存用户
    private void saveSystemLog(){
    
    
        SystemLog systemLog = new SystemLog();
        systemLog.setSystemLogExecutionTime(executeTime);
        systemLog.setSystemLogIp(ip);
        systemLog.setSystemLogMethod("[类名:]"+clazz.getName()+"[方法:]"+method.getName());
        systemLog.setSystemLogUrl(url);
        systemLog.setSystemLogUserName(userName);
        systemLog.setSystemLogVisitTime(visitTime);

        //调用LogService进行存储
        service.insertSystemLog(systemLog);
    }


    /**
     * 获取用户名
     */
    private String getUserInfoName(){
    
    
        SecurityContext context = SecurityContextHolder.getContext();
        User principal = (User)context.getAuthentication().getPrincipal();
        return principal.getUsername();
    }

}

注意:关于使用注解配置AOP切面时候,最终通知和后置通知的顺寻相反,所以,我们这里的的@after也会是后置通知的执行位置!

猜你喜欢

转载自blog.csdn.net/Janyi_/article/details/114414382