Spring Boot 使用 AOP 记录日志
本文转载自微信公众号「武培轩」,使用作者武培轩 。录日转载本文请联系武培轩公众号。使用
在项目开发中经常,录日日志系统是使用必不可少的,特别是录日管理系统,对于重要的使用操作都会有操作日志,然而这个操作不需要我们在相应的录日方法中一个一个的去实现,这肯定是使用不合适的,这样的录日操作无疑是加大了开发量,高防服务器而且不易维护,使用所以实际项目中总是录日利用AOP(Aspect Oriented Programming)即面向切面编程来记录系统中的操作日志。
下面就来介绍如何在 Spring Boot 中 使用 AOP 记录日志:
加入依赖
首先加入 AOP 依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>创建日志注解类
创建一个日志注解类,使用这样就可以在需要记录日志的录日方法上加上注解就可以记录日志了,注解内容如下:
@Target({ ElementType.PARAMETER,使用 ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AopLogger { String describe() default ""; }配置 AOP 切面
定义一个 AopLoggerAspect 切面类,用 @Aspect 声明该类为切面类。
@Component public class AopLoggerAspect { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Pointcut("@annotation(com.wupx.aop.logger.annotation.AopLogger)") public void aopLoggerAspect() { } /** * 环绕触发 * * @param point * @return */ @Around("aopLoggerAspect()") public Object doAround(ProceedingJoinPoint point) { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes; HttpServletRequest request = servletRequestAttributes.getRequest(); Object result = null; long startTime = System.currentTimeMillis(); try { result = point.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); logger.error(throwable.getMessage()); } String describe = getAopLoggerDescribe(point); if (StringUtils.isBlank(describe)) { describe = "-"; } // 打印请求相关参数 logger.info("========================================== Start =========================================="); logger.info("Describe : { }", describe); // 打印请求 url logger.info("URL : { }", request.getRequestURL()); logger.info("URI : { }", request.getRequestURI()); // 打印 Http method logger.info("HTTP Method : { }", request.getMethod()); // 打印调用 controller 的全路径以及执行方法 logger.info("Class Method : { }.{ }", point.getSignature().getDeclaringTypeName(), point.getSignature().getName()); // 打印请求的 IP logger.info("IP : { }", request.getRemoteAddr()); // 打印请求入参 logger.info("Request Args : { }", point.getArgs()); // 打印请求出参 logger.info("Response Args : { }", result); logger.info("Time Consuming : { } ms", System.currentTimeMillis() - startTime); logger.info("=========================================== End ==========================================="); return result; } /** * 获取注解中对方法的描述信息 * * @param joinPoint 切点 * @return describe */ public static String getAopLoggerDescribe(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); AopLogger controllerLog = method.getAnnotation(AopLogger.class); return controllerLog.describe(); } }其中 「@Pointcut」 是定义一个切点,后面跟随一个表达式,表达式可以定义为某个 package 下的方法,也可以是自定义注解等。服务器托管
「@Around」 为在切入点前后织入代码,并且可以自由的控制何时执行切点。
测试
接下来编写 Controller 层来进行测试:
@RestController @RequestMapping("/user") public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService = userService; } @PostMapping @AopLogger(describe = "添加用户") public String addUser(@RequestBody User user) { UserEntity userEntity = new UserEntity(); BeanUtils.copyProperties(user, userEntity); return userService.addUser(userEntity); } }只需要在接口上填写 @AopLogger 就可以记录操作日志。
启动服务,通过 PostMan 请求 http://localhost:8080/user 接口,输出的日志如下所示:
可以看到把入参、出参以及接口信息都记录了下来,是不是很简单呢,只需要简单几步就可以实现 AOP 日志,大家可以自己实践下。
本文的完整代码在 https://github.com/wupeixuan/SpringBoot-Learn 的 aop-logger 目录下。