aop日志(记录方法调用日志)

Posted 言_曦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了aop日志(记录方法调用日志)相关的知识,希望对你有一定的参考价值。

一,使用aop记录方法调用日志

  1)使用注解与aop做方法调用日志,只需要把注解添加在要记录的方法上就可以,不会影响代码结构

  2)实现思路 数据库表建立>>配置需要环境>>自定义注解>>定义切点与操作(包含处理逻辑)>>添加注解

二,配置环境

  1)在原来的项目pom文件中添加以下aop需要的依赖

     <springframework>4.0.5.RELEASE</springframework>
        <aspectj>1.8.5</aspectj>

      
        <!-- Spring AOP -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${springframework}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj}</version>
        </dependency>    

 

  2)springmvc配置

  
 xmlns:aop="http://www.springframework.org/schema/aop"

  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-4.0.xsd



<!--
启动AspectJ支持 只对扫描过的bean有效 --> <aop:aspectj-autoproxy proxy-target-class="true" /> <!-- 指定Sping组件扫描的基本包路径 --> <context:component-scan base-package="com.bjsxt.portl"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan>

三,自定义注解

  1)  

import java.lang.annotation.ElementType;
        import java.lang.annotation.Retention;
        import java.lang.annotation.RetentionPolicy;
        import java.lang.annotation.Target;
        /**
         * 日志记录
         * @author heyuan***
         * @date: 2017年11月22日 上午11:41:57
         */
        @Retention(RetentionPolicy.RUNTIME)
        @Target({ElementType.METHOD})
        public @interface Log {
            String name() default ""; //用于写方法作用
        }

四,定义切点与操作

  1)

@Aspect
@Component
public class SeriveLogAop
{

  @Resource
  private OperationLogMapper operationLogMapper;

  @Pointcut("@annotation(com.bjsxt.portal.annotation.SeriveLog)")
  public void SeriveLogAopqd()
  {
    System.out.println("---------->切点");
  }

  @After("SeriveLogAopqd()")
  public void Afters(JoinPoint joinPoint)
  {
    OperationLog operationLog = new OperationLog();
    User user = new User();
    StringBuffer arg = new StringBuffer();

    Object[] args = joinPoint.getArgs();
    for (int i = 0; i < args.length; ++i) {
      System.out.println("\t==>参数[" + i + "]:\t" + args[i].toString());
      arg.append(args[i].toString());
    }

    Signature signature = joinPoint.getSignature();
    String signa = signature.toString();

    MethodSignature ms = (MethodSignature)joinPoint.getSignature();
    Method method = ms.getMethod();

    String name = ((SeriveLog)method.getAnnotation(SeriveLog.class)).name();

    String name2 = method.getName();

    HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();

    user.setuUsername("无登录人");

    String host = request.getRemoteHost();

    String username = user.getuUsername();

    String time = Time.getTime();

    operationLog.setoIp(host);
    operationLog.setuUsername(username);
    operationLog.setoTime(time);
    operationLog.setoMethodname(name2);
    operationLog.setoExplain(name);
    operationLog.setoFullpath(signa);
    operationLog.setoParameter(arg.toString());

    this.operationLogMapper.addOperationLogs(operationLog);
  }
}

五,在需要记录的方法上添加@Log(name="方法描述")

 

六,常用知识

  

注解:

        @Before – 目标方法执行前执行  前置通知 JoinPoint joinPoint

        @After – 目标方法执行后执行      后置通知

        @AfterReturning – 目标方法返回后执行,如果发生异常不执行

        @AfterThrowing – 异常时执行      异常通知 

        @Around – 在执行上面其他操作的同时也执行这个方法  环绕通知 ProceedingJoinPoint pjp   执行方法:pjp.proceed(); 要返回pjp  
joinPoint:方法
    joinPoint.getKind() // method-execution 
    joinPoint.getTarget().toString()// 获取连接点所在的目标对象; [email protected]
    joinPoint.getArgs() //获取连接点方法运行时的入参列表;
        System.out.println("Args:");
        for(int i=0;i<os.length;i++){
            System.out.println("\t==>参数["+i+"]:\t"+os[i].toString());
        }
    joinPoint.getSignature() //获取连接点的方法签名对象;String com.bjsxt.portal.service.impl.UserServiceImpl.getUser(User,HttpServletRequest,HttpSession)
    joinPoint.getSourceLocation() // org.springframework.aop[email protected]161b0ee2
    joinPoint.getStaticPart() //    execution(String com.xxx.portal.service.impl.UserServiceImpl.getUser(User,HttpServletRequest,HttpSession))    
    
    MethodSignature ms=(MethodSignature) joinPoint.getSignature();
        Method method=ms.getMethod();
        method.getAnnotation(Log.class).name();
        //method.getAnnotation(Log.class).name()  获取操作名(@log(name="内容"))
        method.getName(); //获取当前执行方法名
常用方法:
    HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
     request.getSession();
     request.getHost();//获取ip
     
     异常名称: e.getClass().toString()
网络参考资料
@Aspect
        @Component
        public class LogAop {
            
            ThreadLocal<Long> time=new ThreadLocal<Long>();
            ThreadLocal<String> tag=new ThreadLocal<String>();
            
            //切点
            @Pointcut("@annotation(com.bjsxt.portal.annotation.Log)")
            public void logqd() {
                System.out.println("---------->切点");
            }
            
            /**
             * 在所有标注@Log的地方切入
             * @param joinPoint
             * 前置通知
             */
            @Before("logqd()")
            public void beforeExec(JoinPoint joinPoint){
                
                time.set(System.currentTimeMillis());
                tag.set(UUID.randomUUID().toString());
                
                info(joinPoint);
                
                MethodSignature ms=(MethodSignature) joinPoint.getSignature();
                Method method=ms.getMethod();
                //method.getAnnotation(Log.class).name()  获取操作名(@log(name="内容"))
                System.out.println(method.getAnnotation(Log.class).name()+"标记"+tag.get());
            }
            /**
            *后置通知
            */
            @After("logqd()")
            public void afterExec(JoinPoint joinPoint){
                MethodSignature ms=(MethodSignature) joinPoint.getSignature();
                Method method=ms.getMethod();
                System.out.println("标记为"+tag.get()+"的方法"+method.getName()+"运行消耗"+(System.currentTimeMillis()-time.get())+"ms");
            }
            
            /**
            *环绕通知
            */
            @Around("logqd()")
            public Object aroundExec(ProceedingJoinPoint pjp) throws Throwable{
                System.out.println("前");
                Object proceed = pjp.proceed();
                System.out.println("后");
                return proceed;
            }
            
            private void info(JoinPoint joinPoint){
                System.out.println("--------------------------------------------------");
                System.out.println("King:\t"+joinPoint.getKind());
                System.out.println("Target:\t"+joinPoint.getTarget().toString());
                Object[] os=joinPoint.getArgs();
                System.out.println("Args:");
                for(int i=0;i<os.length;i++){
                    System.out.println("\t==>参数["+i+"]:\t"+os[i].toString());
                }
                System.out.println("Signature:\t"+joinPoint.getSignature());
                System.out.println("SourceLocation:\t"+joinPoint.getSourceLocation());
                System.out.println("StaticPart:\t"+joinPoint.getStaticPart());
                System.out.println("--------------------------------------------------");
            }
            
            
        }
        
        
                /**
             * 异常通知
             *@descript
             *@param point
             *@version 1.0
             */
            @AfterThrowing(pointcut = "controllerAspect()", throwing = "e")  
            public  void doAfterThrowing(JoinPoint point, Throwable e) {  
                LogFormMap logForm = new LogFormMap();
                 Map<String, Object> map = null;
                String user = null;
                String ip = null;
                try {
                    ip = SecurityUtils.getSubject().getSession().getHost();
                } catch (Exception ee) {
                    ip = "无法获取登录用户Ip";
                }
                try {
                    map=getControllerMethodDescription(point);
                    // 登录名
                    user = SecurityUtils.getSubject().getPrincipal().toString();
                    if (Common.isEmpty(user)) {
                        user = "无法获取登录用户信息!";
                    }
                } catch (Exception ee) {
                    user = "无法获取登录用户信息!";
                }
                
                logForm.put("accountName",user);
                logForm.put("module",map.get("module"));
                logForm.put("methods","<font color=\"red\">执行方法异常:-->"+map.get("methods")+"</font>");
                logForm.put("description","<font color=\"red\">执行方法异常:-->"+e+"</font>");
                logForm.put("actionTime","0");
                logForm.put("userIP",ip);
                try {
                    logMapper.addEntity(logForm);
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }

 

以上是关于aop日志(记录方法调用日志)的主要内容,如果未能解决你的问题,请参考以下文章

spring aop 方法增加日志记录

AOP实现日志记录功能

AOP实现日志记录功能

springboot-aop面向切面编程

审计日志中的AOP

自定义日志注解 + AOP实现记录操作日志