SpringBoot+AOP+自定义注解
为了记录日志的使用常常需要写大量而又重复的代码,而通过注解的形式可以大量的减少代码量;
一.maven引入AOP的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
二.自定义注解
package com.zhou.blog.business.annotation; import com.zhou.blog.business.enums.PlatformEnum; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 日志记录、自定义注解 **/ //定义是用在方法上 @Target({ElementType.METHOD}) // 定义是在运行时生效 @Retention(RetentionPolicy.RUNTIME) public @interface BussinessLog { /** * 业务的名称 */ String value() default ""; /** * 平台,默认为后台管理 */ PlatformEnum platform() default PlatformEnum.ADMIN; /** * 是否将当前日志记录到数据库中 */ boolean save() default true; }
三.定义切面
package com.zhou.blog.business.aspect; import com.zhou.blog.business.annotation.BussinessLog; import com.zhou.blog.business.enums.PlatformEnum; import com.zhou.blog.business.service.SysLogService; import com.zhou.blog.util.AspectUtil; import com.zhou.blog.util.RequestUtil; import lombok.extern.slf4j.Slf4j; 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.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.lang.reflect.Method; /** * AOP切面记录日志 **/ @Slf4j @Aspect @Component public class BussinessLogAspect { @Autowired private SysLogService logService; @Pointcut(value = "@annotation(com.zhou.blog.business.annotation.BussinessLog)") /* * @Pointcut语法详解 * https://blog.csdn.net/qq_26860451/article/details/100554377 */ public void pointcut() { } @Around("pointcut()") public Object writeLog(ProceedingJoinPoint point) throws Throwable { //环绕通知=前置+目标方法执行+后置通知,proceed方法就是用专于启动目标方法执行的。 //先执行业务 Object result = point.proceed(); try { //handle(point); /* * *执行的内容 * */ } catch (Exception e) { log.error("日志记录出错!", e); } return result; } private void handle(ProceedingJoinPoint point) throws Exception { Method currentMethod = AspectUtil.INSTANCE.getMethod(point); //获取操作名称 BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class); boolean save = annotation.save(); PlatformEnum platform = annotation.platform(); String bussinessName = AspectUtil.INSTANCE.parseParams(point.getArgs(), annotation.value()); String ua = RequestUtil.getUa(); log.info("{} | {} - {} {} - {}", bussinessName, RequestUtil.getIp(), RequestUtil.getMethod(), RequestUtil.getRequestUrl(), ua); if (!save) { return; } logService.asyncSaveSystemLog(platform, bussinessName); } }
四.使用注解的方法
package com.zhou.blog.controller; import com.zhou.blog.business.annotation.BussinessLog; import com.zhou.blog.business.entity.User; import com.zhou.blog.business.service.SysUserService; import com.zhou.blog.framework.object.ResponseVO; import com.zhou.blog.util.PasswordUtil; import com.zhou.blog.util.ResultUtil; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author ZHOU * @date 2020/5/3 23:14 */ @RestController @RequestMapping("/user") public class RestUserController { @Autowired private SysUserService userService; @PostMapping(value = "/add")
//使用自定义注解 @BussinessLog("添加用户") public ResponseVO add(User user) { User u = userService.getByUserName(user.getUsername()); if (u != null) { return ResultUtil.error("该用户名["+user.getUsername()+"]已存在!请更改用户名"); } try { user.setPassword(PasswordUtil.encrypt(user.getPassword(), user.getUsername())); userService.insert(user); return ResultUtil.success("成功"); } catch (Exception e) { e.printStackTrace(); return ResultUtil.error("error"); } } }