利用idea构建spring boot多项目(六)

发布时间:2018-07-12 浏览次数:2731 文章来源:个人博客

我们再搭建项目后,时常需要进行对程序的一些监控,比如日志,运行时间等,所以需要用到AOP,而spring boot也提供了很好的AOP。

首先,我们进行引入Spring boot的AOP,再web模块的pom.xml中:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

接着创建aop目录:

aop1.png

而LogAspect.java中,代码如下:

package com.demo.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

@Aspect
@Component
public class LogAspect {
    @Pointcut("execution(public * com.demo.controller.*.*(..))")
    public void log(){}

    @Before("log()")
    public void deBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        System.out.println("URL : " + request.getRequestURL().toString());
        System.out.println("HTTP_METHOD : " + request.getMethod());
        System.out.println("IP : " + request.getRemoteAddr());
        System.out.println("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        System.out.println("ARGS : " + Arrays.toString(joinPoint.getArgs()));

    }

    @AfterReturning(returning = "ret", pointcut = "log()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        System.out.println("方法的返回值 : " + ret);
    }

    //后置异常通知
    @AfterThrowing("log()")
    public void throwss(JoinPoint jp){
        System.out.println("方法异常时执行.....");
    }

    //后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
    @After("log()")
    public void after(JoinPoint jp){
        System.out.println("方法最后执行.....");
    }

    //环绕通知,环绕增强,相当于MethodInterceptor
    @Around("log()")
    public Object arround(ProceedingJoinPoint pjp) {
        System.out.println("方法环绕start.....");
        try {
            Object o =  pjp.proceed();
            System.out.println("方法环绕proceed,结果是 :" + o);
            return o;
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        }
    }
}

这样,整个AOP已经完成,我们可以访问之前写的hello world地址,可以发现控制器输出:

aop2.png


但是,倘若我们并不是需要每个方法都进行记录,而是对个别的访问进行记录呢?比如我们对数据库的查询进行记录时间,那么应该怎么做呢?

这里,就需要用到单个注解的方式来实现。

首先,创建注解目录和文件:

aop3.png

再RuntimeActuator.java中,代码如下:

package com.demo.annotation;

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

/**
 * 自定义注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface  RuntimeActuator {
    String note() default "";//传参用,如果不需要可以不写。
}

这样,注解就创建完毕,然后我们定义注解对应的AOP:

再AOP目录下创建RuntimeAspect.java,代码如下:

package com.demo.aop;

import com.demo.annotation.RuntimeActuator;
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.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class RuntimeAspect {
    //这里相当于是定义个全局量
    @Pointcut("@annotation(runtimeActuator)")
    public void serviceStatistics(RuntimeActuator runtimeActuator) {
    }

    @Before("serviceStatistics(runtimeActuator)")
    public void doBefore(JoinPoint joinPoint, RuntimeActuator runtimeActuator) {
        //runtimeActuator.note()是我们自己设置的
        System.out.println("before:"+System.currentTimeMillis() +':'+ runtimeActuator.note());
    }

    @After("serviceStatistics(runtimeActuator)")
    public void doAfter(RuntimeActuator runtimeActuator) {
        System.out.println("after:"+System.currentTimeMillis() +':'+ runtimeActuator.note());
    }
}

至此,整个单个注解的功能就完成了,我们可以给需要的目标加入注解了:

aop4.png

这样,我们运行程序,访问userInfo的地址,就能看到我们单独的切入点:

aop5.png


key-word
springboot多项目 多项目构建 spring boot aop aop