quartz使用記錄

quartz簡介

Quartz是OpenSymphony開源組織在Job scheduling領域又一個開源項目,它可以與J2EE與J2SE應用程序相結合也可以單獨使用。Quartz可以用來創建簡單或爲運行十個,百個,甚至是好幾萬個Jobs這樣複雜的程序。Jobs可以做成標準的Java組件或 EJBs。Quartz的最新版本爲Quartz 2.2.3。

quartz是一個任務調度系統,當應用程序需要天自動定時的完成一些任務的時候,quartz是首選,當然這些也可以使用timer(定時器)來實現。

quartz核心介紹

使用quartz的一些核心類的介紹:

  • Trigger:用來觸發任務的觸發器
  • Job:任務接口,需要執行的任務類實現這個接口的execute方法,Trigger按照指定的規則觸發後會調用Job的execute方法
  • SimpleScheduleBuilder:創建普通的觸發規則,例如每隔多少時間觸發一次任務
  • CronScheduleBuilder:一般如果觸發的規則比較複雜的話應該使用這個(注:這個類和上面的SimpleScheduleBuilder都是用來創建真正的規則的,他們並不是直接使用)
  • JobDetail:上面的Job類將被它使用
  • Scheduler:任務調度器,將Trigger和JobDetail綁定,調用Scheduler.start()方法之後,就會按照Trigger定義的規則觸發Job了
  • SchedulerFactory:工廠類,使用它的getScheduler()方法可以得到Scheduler對象

使用的CronScheduleBuidler的時間配置鏈接:

http://blog.csdn.net/a355586533/article/details/40348537

使用quartz的一些例子

下面我附上一篇官方demo裏面的例子

package org.quartz.examples.example12;
//注意
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This example is a client program that will remotely 
 * talk to the scheduler to schedule a job.   In this 
 * example, we will need to use the JDBC Job Store.  The 
 * client will connect to the JDBC Job Store remotely to 
 * schedule the job.
 * 
 * @author James House, Bill Kratzer
 */
public class RemoteClientExample {

    public void run() throws Exception {

        Logger log = LoggerFactory.getLogger(RemoteClientExample.class);

        // First we must get a reference to a scheduler
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();

        // define the job and ask it to run
        JobDetail job = newJob(SimpleJob.class)
            .withIdentity("remotelyAddedJob", "default")
            .build();

        JobDataMap map = job.getJobDataMap();
        map.put("msg", "Your remotely added job has executed!");

        Trigger trigger = newTrigger()
            .withIdentity("remotelyAddedTrigger", "default")
            .forJob(job.getKey())
            .withSchedule(cronSchedule("/5 * * ? * *"))
            .build();

        // schedule the job
        sched.scheduleJob(job, trigger);

        log.info("Remote job scheduled.");
    }

    public static void main(String[] args) throws Exception {

        RemoteClientExample example = new RemoteClientExample();
        example.run();
    }

}

注:上面的例子有一個大坑,上面的導包語句使用靜態導包,即:import static,如:

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

上面是靜態導包語句,所在代碼裏面可以直接使用TriggerBuilder的newTrigger()靜態方法,如果沒有靜態導包的話,那麼直接複製官方demo的例子將報錯
下面是SimpleJob類:

package org.quartz.examples.example12;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;

/**
 * <p>
 * A dumb implementation of Job, for unittesting purposes.
 * </p>
 * 
 * @author James House
 */
public class SimpleJob implements Job {

    public static final String MESSAGE = "msg";

    private static Logger _log = LoggerFactory.getLogger(SimpleJob.class);

    /**
     * Quartz requires a public empty constructor so that the
     * scheduler can instantiate the class whenever it needs.
     */
    public SimpleJob() {
    }

    /**
     * <p>
     * Called by the <code>{@link org.quartz.Scheduler}</code> when a
     * <code>{@link org.quartz.Trigger}</code> fires that is associated with
     * the <code>Job</code>.
     * </p>
     * 
     * @throws JobExecutionException
     *             if there is an exception while executing the job.
     */
    public void execute(JobExecutionContext context)
        throws JobExecutionException {

        // This job simply prints out its job name and the
        // date and time that it is running
        JobKey jobKey = context.getJobDetail().getKey();

        String message = (String) context.getJobDetail().getJobDataMap().get(MESSAGE);

        _log.info("SimpleJob: " + jobKey + " executing at " + new Date());
        _log.info("SimpleJob: msg: " + message);
    }



}

javaweb項目中使用quartz的例子

InitializerQuartzServlet類:

public class InitializerQuartzServlet extends HttpServlet{

        private StdSchedulerFactory schedFact = null;

        private Scheduler scheduler = null;

        @Override  
        public void init(ServletConfig cfg) throws javax.servlet.ServletException {  
            super.init(cfg);  
            try {
                schedFact = new StdSchedulerFactory();
                scheduler = schedFact.getScheduler();
                JobDetail jobDetail = JobBuilder.newJob(GenerateDailyDataJob.class).withIdentity("dailyDataJob").build();
                .repeatForever()).startNow().build();
                Trigger trigger = TriggerBuilder.newTrigger()
                        .withIdentity(TriggerKey.triggerKey("dailyTrigger", "dailyTriggerGroup"))
                        .withSchedule(CronScheduleBuilder.cronSchedule("0 0 11 * * ?")).build();
                scheduler.scheduleJob(jobDetail, trigger);
                scheduler.start();
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }  

        @Override  
        public void destroy() {  
            try {
                //
                scheduler.shutdown();
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }  

}

GenerateDailyDataJob類:

public class GenerateDailyDataJob implements Job{

    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {
        System.out.println("hello, world!");
    }

}

因爲實在web項目中使用,而且是每天上午11點就觸發這個任務,所以需要將InitializerQuartzServlet 這個Servlet跟隨容器一起啓動,所以在web.xml中要配置:

  <servlet>  
      <servlet-name>InitializerQuartzServlet</servlet-name>  
      <servlet-class>  
          com.weixin.util.InitializerQuartzServlet  
      </servlet-class>  

      <init-param>  
          <param-name>shutdown-on-unload</param-name>  
          <param-value>true</param-value>  
      </init-param>  

      <!-- 加載及啓動定時任務 true -->  
      <init-param>  
          <param-name>start-scheduler-on-load</param-name>  
          <param-value>true</param-value>  
      </init-param>  

      <!-- 啓動延遲時間 60秒 -->  
      <init-param>  
          <param-name>start-delay-seconds</param-name>  
          <param-value>60</param-value>  
      </init-param>  

      <load-on-startup>1</load-on-startup>  
  </servlet>  

quartz使用中的問題

某次在使用quartz的時候,會觸發多次job,也就是本來應該只執行一次job的時候執行了多次,後來在網上看到,quartz不會跟隨着tomcat關閉而關閉,最後導致的結果是啓動了多少次就開啓了多少個quartz任務(很有可能是我沒調用Scheduler.shutdown()方法),現在我在InitializerQuartzServlet 的destroy聲明週期中調用了Scheduler.shutdown()方法,旨在tomcat容器關閉之後會關閉掉Job任務

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章