欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于Spring AOP的用户日志实现

程序员文章站 2022-07-12 14:57:42
...

1.数据库中建立对应的table   sys_log

基于Spring AOP的用户日志实现

然后生成对应的bean,dao,service等等 

2.在springmvc的配置文件中添加aop的配置

    <!-- 启动AOP AspectJ注解自动代理 -->
    <aop:aspectj-autoproxy />
    <!-- 通知spring使用cglib而不是jdk的来生成代理方法 AOP可以拦截到Controller -->
    <aop:config proxy-target-class="true"></aop:config>

3.自定义注解

package com.mqb.logAbout.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解类
 * @author MQB
 *
 */

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface ArchivesLog {
	
	/**
	 * 操作说明
	 * @return  
	 */
	public String operateContent() default "";
}

关于@Retention,@Target等注解为java的四种元注解中的注解,详细信息可以看张开涛大佬的博客

https://www.iteye.com/blog/wisfly-2289443

4.创建一个切点类

package com.mqb.logAbout.log;

import java.lang.reflect.Method;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

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.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.mqb.bean.User;
import com.mqb.logAbout.annotation.ArchivesLog;
import com.mqb.service.SysLogService;

@Aspect
@Component
public class ArchivesLogAspect {
	
	@Autowired
	private SysLogService slService;
	
	private static final Logger logger=LoggerFactory.getLogger(ArchivesLog.class);
	
	
	/**
	 * 定义一个切入点函数,对controller层
	 * 中有ArchivesLog注解的方法进行拦截
	 */
	@Pointcut("@annotation(com.mqb.logAbout.annotation.ArchivesLog)")
	public void controllerAspect() {}
	
	
	/**
	 * 方法返回后进行操作,记录日志,存入数据库
	 * @param joinPoint		连接点,被拦截的函数
	 * @throws Exception	
	 */
	@Before("controllerAspect()")
	public void doBefore(JoinPoint joinPoint) throws Exception{
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		HttpSession session=request.getSession();
		User user=(User) session.getAttribute("user");
		String ip=request.getRemoteAddr();
		
		try {
			//===========控制台输出===============//
			System.out.println("====前置通知开始====");
			System.out.println("请求方法:"+ (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
			System.out.println("方法描述:"+getControllerMethodDescription(joinPoint));
            System.out.println("请求人:" + user.getName());  
            System.out.println("请求IP:" + ip);
		}catch(Exception e) {
			logger.error("==前置通知异常");
			logger.error("异常信息:{}",e.getMessage());
		}
		
	}
	
	public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {  
        String targetName = joinPoint.getTarget().getClass().getName();  
        String methodName = joinPoint.getSignature().getName();  
        Object[] arguments = joinPoint.getArgs();  
        Class targetClass = Class.forName(targetName);  
        Method[] methods = targetClass.getMethods();  
        String description = "";  
         for (Method method : methods) {  
             if (method.getName().equals(methodName)) {  
                Class[] clazzs = method.getParameterTypes();  
                 if (clazzs.length == arguments.length) {  
                    description = method.getAnnotation(ArchivesLog.class).operateContent();  
                     break;  
                }  
            }  
        }  
         return description;  
    }  
}

@annotation注解只针对方法,若想实现在类上加注解,使类内所有方法都执行切点内的方法,则需要使用@within了

这里还没有存入数据库,只是控制台输出下,看下效果。

5.在需要添加日志的方法中加上注解,如

/**
	 * 跳转到project/waitingList页面
	 * @param model
	 * @return
	 */
	@ArchivesLog(operateContent="查看待审批列表")
	@RequestMapping("/waitingList")
	public ModelAndView waitingList(ModelAndView model) {
		model.setViewName("project/waitingList");
		return model;
	}

6.在这个方法打个断点执行下,可以看到控制的输出

基于Spring AOP的用户日志实现

 

后面只要在控制台输出的位置加上添加到数据库就可以了,后续一些特殊需要的功能就需要自己实现了

参考两位大佬的博客,基本都是模仿他们实现的

https://blog.csdn.net/czmchen/article/details/42392985

https://www.cnblogs.com/mei-m/p/10231792.html

 

相关标签: Java