关于java:Java-Web应用结合Quartz实现定时任务

5次阅读

共计 4536 个字符,预计需要花费 12 分钟才能阅读完成。

背景

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 包。
  2. 在 web.xml 中定义 listener。

    <listener>
     <listener-class>com.lee.demo01.MyScheduleListener</listener-class>
    </listener>
  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<? extends Job>) 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 依然须要。

    <servlet>
     <servlet-name>QuartzInitializer</servlet-name>
     <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
     <init-param>
         <param-name>shutdown-on-unload</param-name>
         <param-value>true</param-value>
     </init-param>
     <init-param>
         <param-name>config-file</param-name>
         <param-value>quartz.properties</param-value>
     </init-param>
     <load-on-startup>1</load-on-startup>
    </servlet>
  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。

    <?xml version="1.0" encoding="UTF-8"?>
    <job-scheduling-data xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">
     <schedule>
         <job>
             <name>job1</name>
             <group>group1</group>
             <description> 定时工作 </description>
             <job-class>com.lee.demo01.MyJob</job-class>
         </job>
         <trigger>
             <cron>
                 <name>trigger1</name>
                 <group>group1</group>
                 <job-name>job1</job-name>
                 <job-group>group1</job-group>
                 <cron-expression>0/1 * * * * ?</cron-expression>
             </cron>
         </trigger>
     </schedule>
    </job-scheduling-data>

正文完
 0