Springboot使用AOP操作日志
有时候项目中会记到操作日志,使用aop来实现会提高效率。
导包
- 首先导入aop的jar包
<!--spring切面aop依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
- 自定义注解
@Target(ElementType.METHOD)//该注解表示自定义注解可以在那些地方使用
@Retention(RetentionPolicy.RUNTIME)//自定义注解何时有效
@Inherited//表示一个类如果使用@Inherited注解标志的注解@MyAnno,该类的子类也会继承到这个注解
@Documented//可以生成文档
public @interface MyAnno {
String value() default "";
}
- 使用自定义注解
- 定义切面类
每次执行标有自定义注解的方法时,会先到切面中执行point.proceed();然后去执行当前执行的方法;
最后将操作日志保存到数据库;
@Component
@Aspect
public class MyAspect {
public static final Logger logger = LoggerFactory.getLogger(MyAspect.class);
@Autowired
private LogServiceImpl logService;
//com.canola.demo.aopinterface.MyAnno 指自定义注解的路径
@Pointcut("@annotation(com.canola.demo.aopinterface.MyAnno))")
public void picut() {
}
@Before(value = "picut()")
public void before() {
logger.info("前置通知");
}
@After(value = "picut()")
public void after() {
logger.info("后置通知");
}
//环绕通知 有了环绕通知,前置和后置可以不用
@Around(value = "picut()")
public void around(ProceedingJoinPoint point) {
long beginTime = System.currentTimeMillis();
try {
//会执行用户当前访问的方法
Object proceed = point.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
//执行方法的时间
long time = System.currentTimeMillis() - beginTime;
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
MyAnno myAnno = method.getAnnotation(MyAnno.class);
Log log = new Log();
if (myAnno != null) {
//注解上的描述
log.setDescri(myAnno.value());
}
//获取类名
String className = point.getTarget().getClass().getName();
//获取方法名
String methodName = signature.getName();
//获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
//获取ip
String ipAddr = IPUtils.getIpAddr(request);
log.setIpAddress(ipAddr);
log.setMethodLog(className + "." + methodName + "()");
log.setRunTime(time);
log.setCreateTime(new Date());
logService.add(log);
logger.info("环绕通知");
}
}
- 数据库记录