maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
- @Pointcut
定义一个切入点,我这里的切点是 controller 下的所有方法
@Pointcut("execution(public * com.nbyt.controller..*.*(..))")//切入点描述 这个是controller包的切入点
public void controllerLog(){}//签名,可以理解成这个切入点的一个名称
补充:Java路径通配符的写法
Ant 路径通配符支持 ?、*、** 注意通配符匹配不包括目录分隔符 /
“?”:匹配一个字符,如“config?.xml”将匹配“config1.xml”;
“*”:匹配零个或多个字符串,如“cn/*/config.xml”将匹配“cn/javass/config.xml”,但不匹配匹配“cn/config.xml”;而“cn/config-*.xml”将匹配“cn/config-dao.xml”;
“**”:匹配路径中的零个或多个目录,如“cn/**/config.xml”将匹配“cn/config.xml”,也匹配“cn/javass/spring/config.xml”;而“cn/javass/config-**.xml”将匹配“cn/javass/config-dao.xml”,即把“**”当做两个“*”处理。
参考:https://www.cnblogs.com/knowledgesea/p/11199350.html
- @Before
切点之前执行
- @After
切点之后执行
- @Around
切点环绕执行
//执行切面方法,拿到返回值
Object result = joinPoint.proceed();
- @AfterThrowing
捕获异常的类型为Exception,也可以指定异常进行捕获
@AfterThrowing(pointcut = "controllerLog() ", throwing = "ex")
public void doAfterThrowing(JoinPoint joinPoint, Exception ex) {
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
log.error("连接点方法为:" + methodName + ",参数为:" + args + ",异常为:" + ex);
}
案例:打印日志
@Aspect
@Component
@Slf4j
public class WebLogAspect {
private final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
@Pointcut("execution(public * com.nbyt.controller..*.*(..))")//切入点描述 这个是controller包的切入点
public void controllerLog(){}//签名,可以理解成这个切入点的一个名称
@Before("controllerLog()") //在切入点的方法run之前要干的
public void logBeforeController(JoinPoint joinPoint) {
InputMDC.putMDC();
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();//这个RequestContextHolder是Springmvc提供来获得请求的东西
HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
// 记录下请求内容
log.info("################ URL : " + request.getRequestURL().toString());
log.info("################ 请求方式 : " + request.getMethod());
log.info("################ IP : " + request.getRemoteAddr());
log.info("################ 参数 : " + Arrays.toString(joinPoint.getArgs()));
//下面这个getSignature().getDeclaringTypeName()是获取包+类名的 然后后面的joinPoint.getSignature.getName()获取了方法名
log.info("################ 方法 : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
}
@AfterThrowing(pointcut = "controllerLog() ", throwing = "ex")
public void doAfterThrowing(JoinPoint joinPoint, Exception ex) {
InputMDC.putMDC();
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
log.error("连接点方法为:" + methodName + ",参数为:" + args + ",异常为:" + ex);
}
//记录方法参数,方法名,返回值的日志
@Around("execution(public * com.nbyt.controller..*.*(..))")
public Object sysExceptionCatchAndProcess(ProceedingJoinPoint joinPoint) throws Throwable {
this.logBeforeProceed(joinPoint);
Object result = joinPoint.proceed();
this.logAfterProceed(joinPoint, result);
return result;
}
private void logBeforeProceed(ProceedingJoinPoint joinPoint) {
StringBuilder logBuilder = new StringBuilder();
// 方法
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
logBuilder.append("==========方法参数日志。方法:");
this.appendMethodPath(logBuilder, methodSignature);
// 参数名,参数值
String[] argNames = methodSignature.getParameterNames();
Object[] args = joinPoint.getArgs();
if (args != null && args.length > 0) {
logBuilder.append("参数:");
}
Map<String,Object> map = new HashMap<>();
for (int i = 0; i < argNames.length; i++) {
// logBuilder.append(argNames[i]).append("=").append(JSONUtil.toJsonStr(args[i]));
map.put(argNames[i],args[i]);
}
logBuilder.append(JSONUtil.toJsonStr(map));
// logBuilder.append(Arrays.toString(argNames));
// logBuilder.append(Arrays.toString(args));
log.info(logBuilder.toString());
}
private void logAfterProceed(ProceedingJoinPoint joinPoint, Object result) {
StringBuilder logBuilder = new StringBuilder();
// 方法
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
logBuilder.append("==========方法返回日志。方法:");
this.appendMethodPath(logBuilder, methodSignature);
logBuilder.append("返回=").append(JSONUtil.toJsonStr(result));
log.info(logBuilder.toString());
}
private void appendMethodPath(StringBuilder stringBuilder, MethodSignature methodSignature) {
stringBuilder.append(methodSignature.getMethod().getDeclaringClass().toString())
.append(".")
.append(methodSignature.getMethod().getName())
.append(" ");
}
}