Spring之AOP

时间:2025-04-01 07:35:36
package com.example.springbootstudy.aop; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; 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 javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; import java.util.Arrays; import java.util.stream.Collectors; /** * 使用AOP切Controller打印日志 * * @author 阿无 * @version 1.0.0 * @since 2024/8/19 - 10:57 */ @Aspect @Component public class LogAspect { private static Log logger = LogFactory.getLog(LogAspect.class); // 记录保存所有controller层的日志 @Pointcut("execution(public * ..*.*(..))") public void pointCutControllerLog(){ } @Around("pointCutControllerLog()") public Object controllerLog(ProceedingJoinPoint point) throws Throwable{ return logCommon(point,null); } // 如果非Controller层也需要保存日志,则可以使用注解的形式 // 另一种写法是 // @Around("@annotation()") @Around("@annotation(sysLogAnno)") public Object sysLog(ProceedingJoinPoint point,SysLogAnno sysLogAnno) throws Throwable{ return logCommon(point,sysLogAnno); } public Object logCommon(ProceedingJoinPoint point,SysLogAnno sysLogAnno) throws Throwable{ Long startTime = System.currentTimeMillis(); LocalDateTime localDateTimeStart = LocalDateTime.now(); String className = point.getTarget().getClass().getName(); String message = sysLogAnno!=null ? sysLogAnno.value():null; String methodName = point.getSignature().getName(); Object[] args = point.getArgs(); // 参数全部转换为字符串并以,分割 否则就是一个空字符串 String argsString = args!=null ? Arrays.stream(args).map(Object::toString) .collect(Collectors.joining(",")) : ""; // 1. 获取request对象 ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); // 1.1 请求方式 String requestMethod = request.getMethod(); // 1.2 请求地址/路径 String requestURI = request.getRequestURI(); // 1.3 访问来源ip String remoteAddr = request.getRemoteAddr(); // 1.4 还可以获取用户登录的信息 我们在这儿暂时不需要 // 可以把Object强转成User类 // Object user_var = ().getAttribute("user_var"); SysLog sysLog = new SysLog(className,methodName, message, argsString, null, null, localDateTimeStart,null,null,requestMethod,requestURI,remoteAddr); Object result = point.proceed(); Long endTime = System.currentTimeMillis(); LocalDateTime localDateTimeEnd = LocalDateTime.now(); // 但凡执行到这儿的就是成功的,异常往上抛就行,交给全局异常处理器 sysLog.setStatus("success"); sysLog.setResult(result!=null ? result.toString():null); sysLog.setLocalDateTimeEnd(localDateTimeEnd); sysLog.setTotalTime(endTime - startTime); // 理论上这个日志应该是保存在es中的应该 logger.info("日志记录正常"); logger.info(sysLog); // 2024-08-19 19:57:03.555 INFO 19756 --- [nio-8080-exec-1] : // SysLog(className=, methodName=testLog, message=LogTestService, // args=1,jay, result=1 jay, status=success, localDateTimeStart=2024-08-19T19:57:03.552, localDateTimeEnd=2024-08-19T19:57:03.555, // totalTime=3, requestMethod=GET, requestURI=/testAnnoLog/1, remoteAddr=127.0.0.1) // 2024-08-19 19:57:03.555 INFO 19756 --- [nio-8080-exec-1] : 日志记录正常 // 2024-08-19 19:57:03.555 INFO 19756 --- [nio-8080-exec-1] : // SysLog(className=, methodName=testAnnoLog, message=null, // args=1,jay, result=1 jay, status=success, localDateTimeStart=2024-08-19T19:57:03.502, localDateTimeEnd=2024-08-19T19:57:03.555, // totalTime=56, requestMethod=GET, requestURI=/testAnnoLog/1, remoteAddr=127.0.0.1) // 这里的结果就是拦截的方法的结果 return result; } }