Java Web应用结合Quartz实现定时任务

背景

Leader:业务部门想统计我司调用人脸识别、联网核查服务的次数,你负责定期出个报表呗,便于业务人员费用结算。
Coder:OK,我考虑通过定时任务每月1号凌晨汇总上月的数据,生成个excel,让我们组前端小妹整个页面供业务下载就是。

知识储备

关于定时任务,我首先想到Quartz,它是一个完全由Java编写的开源作业调度框架。下面介绍几个核心概念:

  1. Job表示一个工作,要执行的具体内容。此接口中只有一个方法,如下:

    void execute(JobExecutionContext jobExecutionContext)
  2. JobDetail表示一个具体的可执行的调度程序,Job是这个可执行调度程序所要执行的内容。
  3. Trigger代表一个调度参数的配置,什么时候去调。其中CronTrigger比Simple Trigger更常用,不是像SimpleTrigger那样精确指定时间间隔,而是基于日历的作业调度。
  4. Scheduler代表一个调度容器,一个调度容器中可以注册多个JobDetail和Trigger。当Trigger与JobDetail组合,就可以被Scheduler容器调度了。

为了在应用启动时,自动加载定时任务,我采取实现ServletContextListener接口的
方法,ServletContextListener是随Web应用的启动而启动,只初始化一次,随Web应用的停止而销毁。主要使用场景:做一些初始化的工作、设置一些基本的内容(比如公共参数或者是一些固定的对象等)。

实操

  1. 在Web应用中导入相关的jar包。
    Java Web应用结合Quartz实现定时任务_第1张图片
  2. 在web.xml中定义listener。

    
     com.lee.demo01.MyScheduleListener
    
  3. 创建MyJob,实现Job。这里我就打印下日期,实际可改成汇总数据生成excel的动作。

    public class MyJob implements Job {
     @Override
     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
         System.out.println("MyJob starts at " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
     }
    }
  4. 定义启动定时任务和停止定时任务。我在这里的Cron表达式定义为:"0/1 ?",即每秒触发一次,Cron表达式的用法请参考官方文档说明。

    public class MyQuartz {
     private static Scheduler scheduler;
    
     /*
     启动定时任务
      */
     public static void run() throws Exception {
         System.out.println("定时任务启动");
         JobDetail jobDetail = JobBuilder.newJob((Class) MyJob.class).withIdentity("job1", "group1").build();
         CronTrigger cronTrigger = (CronTrigger) TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(CronScheduleBuilder.cronSchedule("0/1 * * * * ?")).build();
         SchedulerFactory schedulerFactory = new StdSchedulerFactory();
         scheduler = schedulerFactory.getScheduler();
         scheduler.scheduleJob(jobDetail, cronTrigger);
         scheduler.start();
     }
    
     /*
     停止定时任务
      */
     public static void stop() throws Exception {
         System.out.println("定时任务停止");
         scheduler.shutdown();
     }
    }
  5. 创建MyScheduleListener,实现ServletContextListener。

    public class MyScheduleListener implements ServletContextListener {
    
     @Override
     public void contextInitialized(ServletContextEvent arg0) {
         System.out.println("定时任务启动");
         try {
             MyQuartz.run();
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
    
     @Override
     public void contextDestroyed(ServletContextEvent arg0) {
         System.out.println("定时任务停止");
         try {
             MyQuartz.stop();
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
    }
  6. 启动Web应用,控制台可以看到定时任务启动和每秒打印的日志。

    定时任务启动
    定时任务启动
    log4j:WARN No appenders could be found for logger (org.quartz.impl.StdSchedulerFactory).
    log4j:WARN Please initialize the log4j system properly.
    log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
    [2022-04-19 04:50:02,072] Artifact MyWeb:war exploded: Artifact is deployed successfully
    [2022-04-19 04:50:02,072] Artifact MyWeb:war exploded: Deploy took 447 milliseconds
    MyJob starts at 2022-04-19 16:50:02
    MyJob starts at 2022-04-19 16:50:03
    MyJob starts at 2022-04-19 16:50:04
    MyJob starts at 2022-04-19 16:50:05
    MyJob starts at 2022-04-19 16:50:06
    MyJob starts at 2022-04-19 16:50:07
    MyJob starts at 2022-04-19 16:50:08
    MyJob starts at 2022-04-19 16:50:09
    MyJob starts at 2022-04-19 16:50:10

补充说明

上面我是将定时任务的调度写在了一个类中,为方便配置Cron表达式,也可以在配置文件中设置。

  1. 在web.xml中添加QuartzInitializerServlet。在Web应用中导入相关的jar包和创建MyJob仍然需要。

    
     QuartzInitializer
     org.quartz.ee.servlet.QuartzInitializerServlet
     
         shutdown-on-unload
         true
     
     
         config-file
         quartz.properties
     
     1
    
  2. 创建配置文件quartz.properties。

    org.quartz.scheduler.instanceName = AUTO
    org.quartz.scheduler.instanceId = AUTO
    org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
    org.quartz.threadPool.threadCount = 5
    org.quartz.threadPool.threadPriority = 5
    org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingJobHistoryPlugin
    org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
    org.quartz.plugin.jobInitializer.fileNames = quartz_jobs.xml
    org.quartz.plugin.jobInitializer.failOnFileNotFound = true
    org.quartz.plugin.jobInitializer.scanInterval = 10
    org.quartz.plugin.jobInitializer.wrapInUserTransaction = false
  3. 创建配置文件quartz_jobs.xml。

    
    
     
         
             job1
             group1
             定时任务
             com.lee.demo01.MyJob
         
         
             
                 trigger1
                 group1
                 job1
                 group1
                 0/1 * * * * ?
             
         
     
    

你可能感兴趣的:(java)