在使用统一日志管理,权限认证时,我们使用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
网友评论