AOP日志系统

自定义一个注解 用于拦截控制层操作

@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemControllerLogApp {
   /**
    * 描述业务操作 例:登录设备
    * @return
    */
   String description() default "";
   String module() default "";
   boolean doBefore() default true;
}

AOP切面

@Aspect
@Component
@Log4j2
public class SystemLogAspect {
   @Resource(name = "taskExecutor")
   private Executor executor;
   @Autowired
   private ApplogService logService;
   @Autowired
   private RedisTemplate<String, Object> redisTemplate;
   @Autowired
   private TokenUtil tokenUtil;
   /**
    * Controller层切点 注解拦截
    */
   @Pointcut("@annotation(com.evergrande.smc.annotation.SystemControllerLogApp)")
   public void controller(){}

   /**
    * 前置通知 用于拦截Controller层记录用户的操作的开始时间:
    * @param joinPoint 切点
    * @throws InterruptedException
    */
   @Before("controller()")
   public void doBefore(JoinPoint joinPoint) throws InterruptedException{
      MethodSignature signature = (MethodSignature) joinPoint.getSignature();
      Method method = signature.getMethod();
      AppLoginResVO appLoginResVO;
      SystemControllerLogApp controllerLog = method.getAnnotation(SystemControllerLogApp.class);
      //do before : 控制器之前执行
      if(controllerLog != null && controllerLog.doBefore()){
         log.info("控制器之前执行插入日志");
         appLoginResVO = tokenUtil.getLoginUser();
         executor.execute(new LogTask(controllerLog,appLoginResVO));
      }

   }

   /**
    * 后置通知 用于拦截Controller层记录用户的操作
    * @param joinPoint 切点
    */
   @SuppressWarnings("unchecked")
   @After("controller()")
   public void doAfter(JoinPoint joinPoint) throws BusinessException {
      MethodSignature signature = (MethodSignature) joinPoint.getSignature();
      Method method = signature.getMethod();
      AppLoginResVO appLoginResVO;
      SystemControllerLogApp controllerLog = method.getAnnotation(SystemControllerLogApp.class);
      //do after : 控制器之后执行
      if(controllerLog != null && !controllerLog.doBefore()){
         log.info("控制器之后执行插入日志");
         String token = ContextManager.getValue(SystemConstant.CURRENT_USER_TOKEN);
         if(token!=null){
            appLoginResVO = (AppLoginResVO)redisTemplate.boundValueOps(token).get();
            executor.execute(new LogTask(controllerLog,appLoginResVO));
         }
      }
   }

   /**
    * 日志执行线程类
    */
   class LogTask implements Runnable, Serializable {
      private SystemControllerLogApp controllerLog = null;
      private AppLoginResVO appLoginResVO;

      public LogTask (SystemControllerLogApp controllerLog,AppLoginResVO appLoginResVO) {
         this.controllerLog = controllerLog;
         this.appLoginResVO = appLoginResVO;
      }

      @Override
      public void run() {
         log.info("异步线程开始执行: 插入日志");
         String loginName = appLoginResVO.getLoginName();
         String realName = appLoginResVO.getRealName();
         String posCode = appLoginResVO.getPosCode();
         String posProjectName = "";
         String posProjectId = "";
         if(appLoginResVO.getPosProject() != null){
            posProjectId = appLoginResVO.getPosProject().getBuGuid();
            posProjectName = appLoginResVO.getPosProject().getProjName();
         }
         String description = controllerLog.description();
         String module = controllerLog.module();
         AppLog applog=new AppLog ();
         applog.setId ( IdWorkerUtil.generateIdStartWithDate ());
         applog.setProjName (posProjectName);
         applog.setPosCode (posCode);
         applog.setLoginName (loginName);
         applog.setRealName (realName);
         applog.setContent ( description );
         applog.setActionDate (new Date());
         applog.setProjGuid(posProjectId);
         applog.setModule(module);
         log.info("执行异步线程新增日志");
         logService.save(applog);
      }
   }


}

记录用户操作

        , httpMethod = "POST")
@SystemControllerLogApp(description = "登陆设备", module= "登陆模块", doBefore = false)
public RestResult login(@RequestBody AppLoginVO appLoginVO) throws BusinessException {
}

异步线程池配置

@Configuration
@EnableAsync
public class TaskPoolConfig {

    @Bean("taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 线程池创建时候初始化的线程数
        executor.setCorePoolSize(10);
        // 线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        executor.setMaxPoolSize(20);
        // 当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setQueueCapacity(200);
        // 允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
        executor.setKeepAliveSeconds(60);
        // 线程池名的前缀:设置好了之后可以方便定位处理任务所在的线程池
        executor.setThreadNamePrefix("taskExecutor-");
        // 设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住
        executor.setAwaitTerminationSeconds(60);
        // 设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 线程池对拒绝任务的处理策略:这里采用了 CallerRunsPolicy策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}

日志表

CREATE TABLE `admin_app_log` (
  `id` varchar(36) NOT NULL COMMENT '主键',
  `proj_guid` varchar(36) DEFAULT NULL COMMENT '所属项目ID',
  `proj_name` varchar(400) DEFAULT NULL COMMENT '项目名称',
  `pos_code` varchar(50) DEFAULT NULL COMMENT '设备编号',
  `login_name` varchar(50) DEFAULT NULL COMMENT '用户账号',
  `real_name` varchar(50) DEFAULT NULL COMMENT '用户名称',
  `module` varchar(50) DEFAULT NULL COMMENT '功能模块',
  `content` varchar(100) DEFAULT NULL COMMENT '操作内容',
  `action_date` datetime DEFAULT NULL COMMENT '操作时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户日志表';

界面展示


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值