005SpringBoot使用aop切面

2019-10-31  本文已影响0人  桃子味的白开水

在使用统一日志管理,权限认证时,我们使用aop切面,会很方便。

1) POM添加引用

<!--引用AOP-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2) 定义一个切面类

package com.springboot.myspring.aspect;

import java.util.Arrays;

import javax.servlet.http.HttpServletRequest;

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.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;

import lombok.extern.slf4j.Slf4j;

@Aspect
@Component
@Slf4j
public class LogAspectService {
        //申明一个切点 里面是 execution表达式
    @Pointcut("execution(public * com.springboot.myspring.Controller.*.*(..))")
    private void controllerAspect(){
        
    }
        //在控制器方法执行之前执行
    @Before(value="controllerAspect()")
    public void controllerMethodBefore(JoinPoint joinPoint){
        ServletRequestAttributes requestAttributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request=requestAttributes.getRequest();
        log.info("==================请求内容==============");
        log.info("请求地址:"+request.getRequestURL().toString());
        log.info("请求方式:"+request.getMethod());
        log.info("请求类方法:"+joinPoint.getSignature());
        log.info("请求类方法参数:"+Arrays.toString(joinPoint.getArgs()));
        log.info("==================请求内容==============");
        
    }
        //在方法执行完结后打印返回内容
    @AfterReturning(returning="o",pointcut="controllerAspect()")
    public void controllerMethodAfter(Object o){
        log.info("==================返回内容==============");
        log.info("Response内容:"+JSON.toJSONString(o));
        log.info("==================返回内容==============");
    }
}

测试结果


image.png

3) 详细解释

@Aspect将一个类定义为一个切面类
@Pointcut 定义一个方法为切点里面的内容为一个表达式,下面详细介绍
@Before 在切点前执行方法,内容为指定的切点
@After 在切点后,return前执行,
@AfterReturning 在切入点,return后执行,如果想对某些方法的返回参数进行处理,可以在这操作
@Around 环绕切点,在进入切点前,跟切点后执行
@AfterThrowing 在切点后抛出异常进行处理

@Pointcut注解使用:

上面代码中,我们定义了一个切点,该切点只进行处理指定路径的:

@Pointcut("execution(public * com.example.DemoApplication.*(..))")
private void controllerAspect(){}
现在,我们在定义一个处理其他路径下的切点:

@Pointcut("execution(public * com.demo.*.*(..))")
private void controllerDemo(){}
以上切点,都是分别处理不同的内容,如果我们需要一个切点来处理他们两者,我们可以这么配置:

@Pointcut(value = "controllerAspect()||controllerDemo()")
private void all(){}
在@Pointcut注解内,直接引用其它被@Pointcut注解过的方法名称,这样,该切点就可以处理两个路径下的方法

@Pointcut注解中的execution表达式: public * com.demo.*.*(..)

第一个 public 表示方法的修饰符,可以用*代替
第一个 * 表示 返回值,*代表所有
com.demo.* 包路径,.*表示路径下的所有包
第三个.* 表示路径下,所有包下的所有类的方法
(..) 表示不限方法参数

4)自定义注解实现aop功能

创建一个自定义注解


image.png

在想要拦截的地方加上自定义注解


image.png
在aspect类中进行拦截,注意这里需要名字要写全。
image.png
上一篇 下一篇

猜你喜欢

热点阅读