系统的异步操作日志记录 :自定注解+AOP+异步
创始人
2025-05-28 10:02:45

操作日志的记录是通过AOP+自定义注解的方式

  1. 在我们的系统中定义了一个Log注解

    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface OperLog {String value() default "";
    }
    
  2. 该注解标记在Contrller接口的方法上,通过切面的方式记录日志,在方法返回和抛异常的时候执行

        /*** 新增员工* @param employee* @param session* @return*/@OperLog(value = "新增员工")@PostMappingpublic R addEmp(@RequestBody Employee employee, HttpSession session) {
    

    基于方法上注解的参数有操作类型( insert update select等)模块名称等
    在AOP切面中构建操作日志的实体类
    基于request中的请求参数和 方法的返回值 方法抛出的异常信息 为操作日志实体类设置属性

    @Component
    @Aspect
    public class OperationAspect {@AutowiredIOperationLogService operationLogService;//1.切入点表达式:标识哪些方法是切入点(需要进行增强的方法)@Pointcut("@annotation(com.itheima.reggie.aspect.annotation.OperLog)")private void operationMethod(){}//3.切面:如何对哪些方法,进行哪些增强@Around("operationMethod()")//2.通知:具体的增强代码public Object operationLogHandle(ProceedingJoinPoint pjp){OperationLog operationLog = new OperationLog();//获取目标方法:MethodSignature signature = (MethodSignature) pjp.getSignature();Method method = signature.getMethod();//获取目标方法上的注解OperLog annotation = method.getAnnotation(OperLog.class);//获取注解属性String value = annotation.value();operationLog.setOperation_action(value);operationLog.setUser_id(ApplicationContext.getEmpId());//获取目标方法的参数:Object[] args = pjp.getArgs();Object result = null;try {//前置增强result = pjp.proceed(args);//执行目标方法//后置增强} catch (Throwable throwable) {//throwable.printStackTrace();//异常增强:可以在此处抛出自定义异常,交由全局异常处理器进行统一异常处理//返回后增强new  AsyncManager().execute(new TimerTask() {@Overridepublic void run() {operationLogService.save(operationLog);}});} finally {//返回后增强new  AsyncManager().execute(new TimerTask() {@Overridepublic void run() {operationLogService.save(operationLog);}});}return result;}
    }
    
  3. 将操作日志实体类入库的操作定义为一个TimeTask任务
    将该任务交由jdk提供的一个ScheduledExecutorService(定时任务线程池)来执行进行插入,这样就避免了系统在插入操作日志时如果出现异常了从而导致业务功能无法正常返回

    /*** 异步管理器:*     内部维护一个线程池*/
    public class AsyncManager {private ScheduledExecutorService  scheduledThreadPool= new ScheduledThreadPoolExecutor(50);/*** 使用内部的一个线程,去执行具体的任务* @param task*/public void execute(TimerTask task){scheduledThreadPool.execute(task); //延迟执行,延迟10毫秒
  4. 效果
    在这里插入图片描述

相关内容

热门资讯

星星闪烁改为比喻句 关于星星闪烁改为比喻句  文字像精灵,只要你用好它,它就会产生让你意想不到的效果。所以无论我们说话还...
近体诗和古体诗的主要区别 近体诗和古体诗的主要区别  在平凡的学习、工作、生活中,许多人对一些广为流传的诗歌都不陌生吧,诗歌富...
七言春联 七言春联汇总  逢春节,无论城市还是农村,家家户户都要挑漂亮的红春联贴于门上,辞旧迎新,增加喜庆的节...
河水哗哗地流着改为拟人句 河水哗哗地流着改为拟人句  拟人修辞方法,就是把事物人格化,将本来不具备人动作和感情的事物变成和人一...
天上的街市阅读答案   我们中国近代诗人郭沫若一首非常有名的作品,叫做《天上的街市》,这篇课文没有出现在我们课本上,所以...