if (e instanceof BadCredentialsException)                  AsyncManager .me () .execute (AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));                  throw new UserPasswordNotMatchException ();                  AsyncManager .me () .execute (AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));                  throw new ServiceException (e.getMessage());          finally              AuthenticationContextHolder .clearContext ();          AsyncManager .me () .execute (AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));

我们可以看到若依封装了一个异步任务管理器,是以饿汉式的单例模式为全局唯一对象。

调用 execute 方法延迟10s执行任务,需要传入一个 Runnable

 public ScheduledFuture<?> schedule(Runnable command,
                                        long delay, TimeUnit unit);

这里传入的是TimerTask,其实现了Runnable接口

 public abstract class TimerTask implements Runnable

A task that can be scheduled for one-time or repeated execution by a Timer.

Timer是一种定时器工具,用来在一个后台线程计划执行指定任务。它可以计划执行一个任务一次或反复多次。 TimerTask一个抽象类,它的子类代表一个可以被Timer计划的任务。

若依使用异步工厂创建TimerTask

  * 异步工厂(产生任务用)   * @author ruoyi  public class AsyncFactory      private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");       * 记录登录信息       * @param username 用户名       * @param status 状态       * @param message 消息       * @param args 列表       * @return 任务task      public static TimerTask recordLogininfor(final String username, final String status, final String message,              final Object... args)          final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));          final String ip = IpUtils.getIpAddr();          return new TimerTask()              @Override              public void run()                  String address = AddressUtils.getRealAddressByIP(ip);                  StringBuilder s = new StringBuilder();                  s.append(LogUtils.getBlock(ip));                  s.append(address);                  s.append(LogUtils.getBlock(username));                  s.append(LogUtils.getBlock(status));                  s.append(LogUtils.getBlock(message));                  // 打印信息到日志                  sys_user_logger.info(s.toString(), args);                  // 获取客户端操作系统                  String os = userAgent.getOperatingSystem().getName();                  // 获取客户端浏览器                  String browser = userAgent.getBrowser().getName();                  // 封装对象                  SysLogininfor logininfor = new SysLogininfor();                  logininfor.setUserName(username);                  logininfor.setIpaddr(ip);                  logininfor.setLoginLocation(address);                  logininfor.setBrowser(browser);                  logininfor.setOs(os);                  logininfor.setMsg(message);                  // 日志状态                  if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))                      logininfor.setStatus(Constants.SUCCESS);                  else if (Constants.LOGIN_FAIL.equals(status))                      logininfor.setStatus(Constants.FAIL);                  // 插入数据                  SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);       * 操作日志记录       * @param operLog 操作日志信息       * @return 任务task      public static TimerTask recordOper(final SysOperLog operLog)          return new TimerTask()              @Override              public void run()                  // 远程查询操作地点                  operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));                  SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);

若依在aop中记录异常日志也是通过异步任务管理器去创建的

      * 拦截异常操作       * @param joinPoint 切点       * @param e 异常      @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")      public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e)          handleLog(joinPoint, controllerLog, e, null);      protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult)              // 获取当前的用户              LoginUser loginUser = SecurityUtils.getLoginUser();              // *========数据库日志=========*//              SysOperLog operLog = new SysOperLog();              operLog.setStatus(BusinessStatus.SUCCESS.ordinal());              // 请求的地址              String ip = IpUtils.getIpAddr();              operLog.setOperIp(ip);              operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));              if (loginUser != null)                  operLog.setOperName(loginUser.getUsername());              if (e != null)                  operLog.setStatus(BusinessStatus.FAIL.ordinal());                  operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));              // 设置方法名称              String className = joinPoint.getTarget().getClass().getName();              String methodName = joinPoint.getSignature().getName();              operLog.setMethod(className + "." + methodName + "()");              // 设置请求方式              operLog.setRequestMethod(ServletUtils.getRequest().getMethod());              // 处理设置注解上的参数              getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);              // 设置消耗时间              operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());              // 保存数据库              AsyncManager.me().execute(AsyncFactory.recordOper(operLog));          catch (Exception exp)              // 记录本地异常日志              log.error("异常信息:{}", exp.getMessage());              exp.printStackTrace();          finally              TIME_THREADLOCAL.remove();

最后在来看一看使用的定时任务线程池

      * 执行周期性或定时任务      @Bean(name = "scheduledExecutorService")      protected ScheduledExecutorService scheduledExecutorService()          return new ScheduledThreadPoolExecutor(corePoolSize,                  new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),//线程创建工厂                  new ThreadPoolExecutor.CallerRunsPolicy())//当前调用者的线程中执行任务              @Override              protected void afterExecute(Runnable r, Throwable t)                  super.afterExecute(r, t);                  Threads.printException(r, t); 复制代码
分类:
后端
  • MobotStone
    18分钟前
  •