1. 程式人生 > >Springboot中使用資料庫配置Quartz定時任務

Springboot中使用資料庫配置Quartz定時任務

在實際專案開發過程中,定時任務幾乎是必不可少的。作為Java程式設計師用的最多的任務排程框架非Quartz莫屬了。 
在Quartz中配置任務的方式很多,比較常見的就有基於註解配置、基於XML等配置檔案進行配置和通過資料庫進行配置三種配置方式,具體應該使用哪種方式來對定時任務進行配置需要根據你的實際業務場景來進行選擇,這不是本文要討論的重點,本文僅對如何使用資料庫實現對定時任務的動態靈活配置進行簡單示例和介紹。
為簡單起見,本文使用了Spring Jpa來進行資料庫操作。當應用啟動時,TaskInitService類會從資料庫中讀取定時任務並進行載入。由於所有的定時任務都被儲存在資料庫中,使用者可以通過相應的前端任務展示頁面方便地對定時任務進行檢視和管理,一旦有任務被修改,Scheduler排程器中的任務也會同步更新並立刻生效。專案的完整目錄層次如下圖所示。

新增依賴配置

為了使用Quartz和JPA,需要在工程POM檔案中引入它們的Maven依賴,此外本示例工程中還使用到了lombok和commons-lang兩個輔助工具包。
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.4.1.RELEASE</version>
	</parent>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- 新增MYSQL資料庫驅動依賴 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<!-- 新增spring jpa依賴 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<!-- 新增quartz依賴 -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.3.0</version>
		</dependency>
		<!-- 新增lombok依賴 -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
		<!-- 新增commons-lang3依賴 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.7</version>
		</dependency>
	</dependencies>
在application.properties配置檔案中除了要定義MYSQL資料庫連線資訊外,還需要新增如下JPA相關配置。
########################################################
### Java Persistence Api --  Spring jpa setting  #######
########################################################
# Specify the DBMS
spring.jpa.database = MYSQL
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# stripped before adding them to the entity manager)
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

建立定時任務實體類

定義兩個任務實體類:TaskCronJob和TaskSimJob,用來與資料庫中的表建立對映關係。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Data;

/**
 * 基於Cron觸發器的定時任務實體類
 * 
 * @author pengjunlee
 *
 */
@Data
@Entity
@Table(name="task_cron_job")
public class TaskCronJob {

	// Job主鍵
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	// cron表示式
	private String cron;

	// Job名稱
	private String jobName;

	// Job相關的類全名
	private String jobClassName;

	// Job描述
	private String jobDescription;

	// Job編號
	private String jobNumber;

	// Job是否啟用
	private Boolean enabled;

	public TaskCronJob(String cron, String jobName, String jobClassName, String jobDescription, String jobNumber) {
		super();
		this.cron = cron;
		this.jobName = jobName;
		this.jobClassName = jobClassName;
		this.jobDescription = jobDescription;
		this.jobNumber = jobNumber;
	}

	public TaskCronJob() {
	}
}

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Data;

/**
 * 基於simple觸發器的定時任務實體類
 * 
 * @author pengjunlee
 *
 */
@Data
@Entity
@Table(name="task_sim_job")
public class TaskSimJob {

	// Job主鍵
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	// 間隔時間
	private Integer intervalTime;

	// Job名稱
	private String jobName;

	// Job相關的類全名
	private String jobClassName;

	// Job描述
	private String jobDescription;

	// Job編號
	private String jobNumber;

	// Job是否啟用
	private Boolean enabled;

	public TaskSimJob(Integer intervalTime, String jobName, String jobClassName, String jobDescription,
			String jobNumber) {
		super();
		this.intervalTime = intervalTime;
		this.jobName = jobName;
		this.jobClassName = jobClassName;
		this.jobDescription = jobDescription;
		this.jobNumber = jobNumber;
	}

	public TaskSimJob() {
	}

}

對應的資料庫欄位及其格式如下圖所示。


任務實體持久化

通過上面定義的定義的兩個任務實體類TaskCronJob和TaskSimJob,實現了使用Java的普通物件(POJO)與資料庫表建立對映關係(ORM),接下來使用JPA來實現持久化。定義好的TaskCronJobRepository和TaskSimJobRepository均繼承自CrudRepository,用來實現基本的持久化操作。
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import com.pengjunlee.task.bean.TaskCronJob;

@Repository
public interface TaskCronJobRepository extends CrudRepository<TaskCronJob, Long>
{

}
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import com.pengjunlee.task.bean.TaskSimJob;

@Repository
public interface TaskSimJobRepository extends CrudRepository<TaskSimJob, Long>
{

}

建立排程器工廠

TaskSchedulerFactory排程器工廠類用來生產Scheduler排程器物件,一般情況下應將其實現為單例。
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

/**
 * 排程器工廠類,應當在Spring中將該類配置為單例
 */
@Component
@Slf4j
public class TaskSchedulerFactory {

	private volatile Scheduler scheduler;

	/**
	 * 獲得scheduler例項
	 */
	public Scheduler getScheduler() {
		Scheduler s = scheduler;
		if (s == null) {
			synchronized (this) {
				s = scheduler;
				if (s == null) {
					// 雙重檢查
					try {
						SchedulerFactory sf = new StdSchedulerFactory();
						s = scheduler = sf.getScheduler();
					} catch (Exception e) {
						log.error("Get scheduler error :" + e.getMessage(), e);
					}
				}
			}
		}

		return s;
	}
}

TaskUtils工具類

TaskUtils工具類負責為定時任務生產JobKey和TriggerKey。
import org.quartz.JobKey;
import org.quartz.TriggerKey;

import com.pengjunlee.task.bean.TaskCronJob;
import com.pengjunlee.task.bean.TaskSimJob;

/**
 * 任務管理模組的工具類
 */
public class TaskUtils
{
	
	/**
	 * 基於cron排程的Job的預設組名
	 */
	public static final String CRON_JOB_GROUP_NAME = "cron_task_group";

	/**
	 * 基於simple排程的Job的預設組名
	 */
	public static final String SIM_JOB_GROUP_NAME = "sim_task_group";

    /**
     * 產生JobKey
     * 
     * @param job
     * @return
     */
    public static JobKey genCronJobKey(TaskCronJob job)
    {
        return new JobKey(job.getJobName().trim(), CRON_JOB_GROUP_NAME);
    }

    /**
     * 產生TriggerKey
     * 
     * @param job
     * @return
     */
    public static TriggerKey genCronTriggerKey(TaskCronJob job)
    {
        return new TriggerKey("trigger_" + job.getJobName().trim(), CRON_JOB_GROUP_NAME);
    }

    /**
     * 產生JobKey
     * 
     * @param job
     * @return
     */
    public static JobKey genSimJobKey(TaskSimJob job)
    {
        return new JobKey(job.getJobName().trim(), SIM_JOB_GROUP_NAME);
    }

    /**
     * 產生TriggerKey
     * 
     * @param job
     * @return
     */
    public static TriggerKey genSimTriggerKey(TaskSimJob job)
    {
        return new TriggerKey("trigger_" + job.getJobName().trim(), SIM_JOB_GROUP_NAME);
    }

    /**
     * 判斷是否兩個trigger key是否相等
     * 
     * @param tk1
     * @param tk2
     * @return
     */
    public static boolean isTriggerKeyEqual(TriggerKey tk1, TriggerKey tk2)
    {
        return tk1.getName().equals(tk2.getName()) && ((tk1.getGroup() == null && tk2.getGroup() == null)
                || (tk1.getGroup() != null && tk1.getGroup().equals(tk2.getGroup())));
    }
}

建立定時任務服務類

TaskCronJobService和TaskSimJobService通過呼叫上面定義好的TaskCronJobRepository和TaskSimJobRepository兩個持久化類,在儲存定時任務到資料庫時實現了對排程器中定時任務的同步更新
import javax.annotation.Resource;
import javax.transaction.Transactional;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.stereotype.Service;

import com.pengjunlee.task.TaskSchedulerFactory;
import com.pengjunlee.task.bean.TaskCronJob;
import com.pengjunlee.task.repository.TaskCronJobRepository;
import com.pengjunlee.task.util.TaskUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 基於Cron的定時任務服務類
 * 
 * @author pengjunlee
 */
@Service
@Slf4j
public class TaskCronJobService
{

    @Resource
    private TaskCronJobRepository cronJobRepository;

    @Resource
    private TaskSchedulerFactory schedulerFactory;

    // 在對任務進行儲存時需同步更新排程器中的定時任務配置
    @Transactional
    public void save(TaskCronJob taskCronJob)
    {
        try
        {
            TaskCronJob job = findOne(taskCronJob.getId());
            TriggerKey triggerKey = TaskUtils.genCronTriggerKey(job);
            Scheduler scheduler = schedulerFactory.getScheduler();
            JobKey jobKey = TaskUtils.genCronJobKey(job);
            // 如果不同則代表著CRON表示式已經修改
            if (!job.getCron().equals(taskCronJob.getCron()))
            {
                CronTrigger newTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey)
                        .withSchedule(CronScheduleBuilder.cronSchedule(taskCronJob.getCron()).withMisfireHandlingInstructionDoNothing()).build();
                // 更新任務
                scheduler.rescheduleJob(triggerKey, newTrigger);
            }
            if (!job.getEnabled().equals(taskCronJob.getEnabled()))
            {
                // 如果狀態為0則停止該任務
                if (!taskCronJob.getEnabled())
                {
                    /* scheduler.unscheduleJob(triggerKey); */
                    scheduler.pauseJob(jobKey);
                    /* scheduler.deleteJob(jobKey); */
                }
                else
                {
                    Trigger trigger = scheduler.getTrigger(triggerKey);
                    // trigger如果為null則說明scheduler中並沒有建立該任務
                    if (trigger == null)
                    {
                        Class<?> jobClass = Class.forName(job.getJobClassName().trim());
                        @SuppressWarnings("unchecked")
                        JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) jobClass).withIdentity(jobKey)
                                .withDescription(job.getJobDescription()).build();
                        trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey)
                                .withSchedule(CronScheduleBuilder.cronSchedule(taskCronJob.getCron()).withMisfireHandlingInstructionDoNothing())
                                .build();

                        scheduler.scheduleJob(jobDetail, trigger);
                    }
                    else
                    {
                        // 不為null則說明scheduler中有建立該任務,更新即可
                        CronTrigger newTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey)
                                .withSchedule(CronScheduleBuilder.cronSchedule(taskCronJob.getCron()).withMisfireHandlingInstructionDoNothing())
                                .build();
                        scheduler.rescheduleJob(triggerKey, newTrigger);
                    }
                }
            }
            job.setCron(taskCronJob.getCron());
            job.setEnabled(taskCronJob.getEnabled());

            cronJobRepository.save(job);
        }
        catch (Exception e)
        {
            log.error("定時任務重新整理失敗...");
            log.error(e.getMessage());
        }
    }

    public TaskCronJob findOne(Long id)
    {
        return cronJobRepository.findOne(id);
    }

    public Iterable<TaskCronJob> findAll()
    {
        return cronJobRepository.findAll();
    }

}
import javax.annotation.Resource;
import javax.transaction.Transactional;

import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.stereotype.Service;

import com.pengjunlee.task.TaskSchedulerFactory;
import com.pengjunlee.task.bean.TaskSimJob;
import com.pengjunlee.task.repository.TaskSimJobRepository;
import com.pengjunlee.task.util.TaskUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 基於Cron的定時任務服務類
 * 
 * @author pengjunlee
 */
@Service
@Slf4j
public class TaskSimJobService
{

    @Resource
    private TaskSimJobRepository simJobRepository;

    @Resource
    private TaskSchedulerFactory schedulerFactory;

    // 在對任務進行儲存時需同步更新排程器中的定時任務配置
    @Transactional
    public void save(TaskSimJob taskSimJob)
    {
        try
        {
            TaskSimJob job = findOne(taskSimJob.getId());
            TriggerKey triggerKey = TaskUtils.genSimTriggerKey(job);
            Scheduler scheduler = schedulerFactory.getScheduler();
            JobKey jobKey = TaskUtils.genSimJobKey(job);
            // 如果不同則代表著CRON表示式已經修改
            if (!job.getIntervalTime().equals(taskSimJob.getIntervalTime()))
            {
                SimpleTrigger newTrigger = TriggerBuilder.newTrigger()
                        .withIdentity(triggerKey).forJob(jobKey).withSchedule(SimpleScheduleBuilder.simpleSchedule()
                                .withIntervalInSeconds(taskSimJob.getIntervalTime()).withMisfireHandlingInstructionIgnoreMisfires().repeatForever())
                        .build();
                // 更新任務
                scheduler.rescheduleJob(triggerKey, newTrigger);
            }
            if (!job.getEnabled().equals(taskSimJob.getEnabled()))
            {
                // 如果狀態為0則停止該任務
                if (!taskSimJob.getEnabled())
                {
                    /* scheduler.unscheduleJob(triggerKey); */
                    scheduler.pauseJob(jobKey);
                    /* scheduler.deleteJob(jobKey); */
                }
                else
                {
                    Trigger trigger = scheduler.getTrigger(triggerKey);
                    // trigger如果為null則說明scheduler中並沒有建立該任務
                    if (trigger == null)
                    {
                        Class<?> jobClass = Class.forName(job.getJobClassName().trim());
                        @SuppressWarnings("unchecked")
                        JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) jobClass).withIdentity(jobKey)
                                .withDescription(job.getJobDescription()).build();
                        trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey)
                                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(taskSimJob.getIntervalTime())
                                        .withMisfireHandlingInstructionIgnoreMisfires().repeatForever())
                                .build();
                        scheduler.scheduleJob(jobDetail, trigger);
                    }
                    else
                    {
                        // 不為null則說明scheduler中有建立該任務,更新即可
                        SimpleTrigger newTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey)
                                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(taskSimJob.getIntervalTime())
                                        .withMisfireHandlingInstructionIgnoreMisfires().repeatForever())
                                .build();
                        scheduler.rescheduleJob(triggerKey, newTrigger);
                    }
                }
            }
            job.setIntervalTime(taskSimJob.getIntervalTime());
            job.setEnabled(taskSimJob.getEnabled());

            simJobRepository.save(job);
        }
        catch (Exception e)
        {
            log.error("定時任務重新整理失敗...");
            log.error(e.getMessage());
        }
    }

    public TaskSimJob findOne(Long id)
    {
        return simJobRepository.findOne(id);
    }

    public Iterable<TaskSimJob> findAll()
    {
        return simJobRepository.findAll();
    }
}

建立定時任務初始化服務類

TaskInitService類負責從資料庫中獲取到需要執行的定時任務並將任務新增到排程器的管理之中。
import static org.quartz.CronExpression.isValidExpression;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.stereotype.Component;

import com.pengjunlee.task.TaskSchedulerFactory;
import com.pengjunlee.task.bean.TaskCronJob;
import com.pengjunlee.task.bean.TaskSimJob;
import com.pengjunlee.task.service.TaskInitService;
import com.pengjunlee.task.util.TaskUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 定時任務初始化服務類
 * @author pengjunlee
 *
 */
@Component
@Slf4j
public class TaskInitService {

	@Resource
	private TaskCronJobService taskCronJobService;

	@Resource
	private TaskSimJobService taskSimJobService;

	@Resource
	private TaskSchedulerFactory schedulerFactory;

	/**
	 * 初始化
	 */
	@PostConstruct
	public void init() {
		Scheduler scheduler = schedulerFactory.getScheduler();
		if (scheduler == null) {
			log.error("初始化定時任務元件失敗,Scheduler is null...");
			return;
		}

		// 初始化基於cron時間配置的任務列表
		try {
			initCronJobs(scheduler);
		} catch (Exception e) {
			log.error("init cron tasks error," + e.getMessage(), e);
		}

		// 初始化基於固定間隔時間配置的任務列表
		try {
			initSimJobs(scheduler);
		} catch (Exception e) {
			log.error("init sim tasks error," + e.getMessage(), e);
		}

		try {
			log.info("The scheduler is starting...");
			scheduler.start(); // start the scheduler
		} catch (Exception e) {
			log.error("The scheduler start is error," + e.getMessage(), e);
		}
	}

	/**
	 * 初始化任務(基於cron觸發器)
	 * 
	 */
	private void initCronJobs(Scheduler scheduler) throws Exception {
		Iterable<TaskCronJob> jobList = taskCronJobService.findAll();
		if (jobList != null) {
			for (TaskCronJob job : jobList) {
				scheduleCronJob(job, scheduler);
			}
		}
	}

	/**
	 * 初始化任務(基於simple觸發器)
	 * 
	 */
	private void initSimJobs(Scheduler scheduler) throws Exception {
		Iterable<TaskSimJob> jobList = taskSimJobService.findAll();
		if (jobList != null) {
			for (TaskSimJob job : jobList) {
				scheduleSimJob(job, scheduler);
			}
		}
	}

	/**
	 * 安排任務(基於simple觸發器)
	 * 
	 * @param job
	 * @param scheduler
	 */
	private void scheduleSimJob(TaskSimJob job, Scheduler scheduler) {
		if (job != null && StringUtils.isNotBlank(job.getJobName()) && StringUtils.isNotBlank(job.getJobClassName())
				&& scheduler != null) {
			if (!job.getEnabled()) {
				return;
			}

			try {
				JobKey jobKey = TaskUtils.genSimJobKey(job);

				if (!scheduler.checkExists(jobKey)) {
					// This job doesn't exist, then add it to scheduler.
					log.info("Add new simple job to scheduler, jobName = " + job.getJobName());
					this.newJobAndNewSimTrigger(job, scheduler, jobKey);
				} else {
					log.info("Update simple job to scheduler, jobName = " + job.getJobName());
					this.updateSimTriggerOfJob(job, scheduler, jobKey);
				}

			} catch (Exception e) {
				log.error("ScheduleCronJob is error," + e.getMessage(), e);
			}
		} else {
			log.error("Method scheduleSimJob arguments are invalid.");
		}
	}

	/**
	 * 安排任務(基於cron觸發器)
	 * 
	 * @param job
	 * @param scheduler
	 */
	private void scheduleCronJob(TaskCronJob job, Scheduler scheduler) {
		if (job != null && StringUtils.isNotBlank(job.getJobName()) && StringUtils.isNotBlank(job.getJobClassName())
				&& StringUtils.isNotBlank(job.getCron()) && scheduler != null) {
			if (!job.getEnabled()) {
				return;
			}

			try {
				JobKey jobKey = TaskUtils.genCronJobKey(job);

				if (!scheduler.checkExists(jobKey)) {
					// This job doesn't exist, then add it to scheduler.
					log.info("Add new cron job to scheduler, jobName = " + job.getJobName());
					this.newJobAndNewCronTrigger(job, scheduler, jobKey);
				} else {
					log.info("Update cron job to scheduler, jobName = " + job.getJobName());
					this.updateCronTriggerOfJob(job, scheduler, jobKey);
				}
			} catch (Exception e) {
				log.error("ScheduleCronJob is error," + e.getMessage(), e);
			}
		} else {
			log.error("Method scheduleCronJob arguments are invalid.");
		}
	}

	/**
	 * 新建job和trigger到scheduler(基於simple觸發器)
	 * 
	 * @param job
	 * @param scheduler
	 * @param jobKey
	 * @throws SchedulerException
	 * @throws ClassNotFoundException
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private void newJobAndNewSimTrigger(TaskSimJob job, Scheduler scheduler, JobKey jobKey)
			throws SchedulerException, ClassNotFoundException {
		TriggerKey triggerKey = TaskUtils.genSimTriggerKey(job);
		// get a Class object by string class name of job;
		Class jobClass = Class.forName(job.getJobClassName().trim());
		JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).withDescription(job.getJobDescription())
				.build();

		SimpleTrigger trigger = null;
		int intervalInSec = job.getIntervalTime();
		if (intervalInSec > 0) {
			// repeat the job every interval seconds.
			trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey).startNow()
					.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(intervalInSec)).build();
		} else {
			// totally execute the job once.
			trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey).startNow()
					.withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(1)).build();
		}

		scheduler.scheduleJob(jobDetail, trigger);
	}

	/**
	 * 更新job的trigger(基於simple觸發器)
	 * 
	 * @param job
	 * @param scheduler
	 * @param jobKey
	 * @throws SchedulerException
	 */
	private void updateSimTriggerOfJob(TaskSimJob job, Scheduler scheduler, JobKey jobKey) throws SchedulerException {
		TriggerKey triggerKey = TaskUtils.genSimTriggerKey(job);
		int intervalInSec = job.getIntervalTime();

		List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);

		for (int i = 0; triggers != null && i < triggers.size(); i++) {
			Trigger trigger = triggers.get(i);
			TriggerKey curTriggerKey = trigger.getKey();

			if (TaskUtils.isTriggerKeyEqual(triggerKey, curTriggerKey)) {
				SimpleTrigger newTrigger = null;
				if (intervalInSec > 0) {
					// repeat the job every interval seconds.
					newTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey).startNow()
							.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(intervalInSec)).build();
				} else {
					// totally execute the job once.
					newTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey).startNow()
							.withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(1)).build();
				}
				scheduler.rescheduleJob(curTriggerKey, newTrigger);
			} else {
				// different trigger key // The trigger key is illegal,
				// unschedule this trigger
				scheduler.unscheduleJob(curTriggerKey);
			}
		}
	}

	/**
	 * 新建job和trigger到scheduler(基於cron觸發器)
	 * 
	 * @param job
	 * @param scheduler
	 * @param jobKey
	 * @throws SchedulerException
	 * @throws ClassNotFoundException
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private void newJobAndNewCronTrigger(TaskCronJob job, Scheduler scheduler, JobKey jobKey)
			throws SchedulerException, ClassNotFoundException {
		TriggerKey triggerKey = TaskUtils.genCronTriggerKey(job);

		String cronExpr = job.getCron();
		if (!isValidExpression(cronExpr)) {
			return;
		}

		// get a Class object by string class name of job;
		Class jobClass = Class.forName(job.getJobClassName().trim());
		JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).withDescription(job.getJobDescription())
				.build();
		CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey)
				.withSchedule(CronScheduleBuilder.cronSchedule(cronExpr).withMisfireHandlingInstructionDoNothing())
				.build();

		scheduler.scheduleJob(jobDetail, trigger);
	}

	/**
	 * 更新job的trigger(基於cron觸發器)
	 * 
	 * @param job
	 * @param scheduler
	 * @param jobKey
	 * @throws SchedulerException
	 */
	private void updateCronTriggerOfJob(TaskCronJob job, Scheduler scheduler, JobKey jobKey) throws SchedulerException {
		TriggerKey triggerKey = TaskUtils.genCronTriggerKey(job);
		String cronExpr = job.getCron().trim();

		List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);

		for (int i = 0; triggers != null && i < triggers.size(); i++) {
			Trigger trigger = triggers.get(i);
			TriggerKey curTriggerKey = trigger.getKey();

			if (TaskUtils.isTriggerKeyEqual(triggerKey, curTriggerKey)) {
				if (trigger instanceof CronTrigger
						&& cronExpr.equalsIgnoreCase(((CronTrigger) trigger).getCronExpression())) {
					// Don't need to do anything.
				} else {
					if (isValidExpression(job.getCron())) {
						// Cron expression is valid, build a new trigger and
						// replace the old one.
						CronTrigger newTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey)
								.withSchedule(CronScheduleBuilder.cronSchedule(cronExpr)
										.withMisfireHandlingInstructionDoNothing())
								.build();
						scheduler.rescheduleJob(curTriggerKey, newTrigger);
					}
				}
			} else {
				// different trigger key ,The trigger key is illegal, unschedule
				// this trigger
				scheduler.unscheduleJob(curTriggerKey);
			}

		}

	}

}

建立定時任務實現類

具體的定時任務實現類需要實現Job介面。
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob implements Job {

	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		System.out.println("執行定時任務:MyJob.execute()...");
	}

}

相關推薦

Springboot使用資料庫配置Quartz定時任務

在實際專案開發過程中,定時任務幾乎是必不可少的。作為Java程式設計師用的最多的任務排程框架非Quartz莫屬了。  在Quartz中配置任務的方式很多,比較常見的就有基於註解配置、基於XML等配置檔案進行配置和通過資料庫進行配置三種配置方式,具體應該使用哪種方式來對定時任

定時任務-----Springboot使用Scheduled做定時任務----http://www.cnblogs.com/lirenqing/p/6596557.html

clas html RR work blog PE date() span org Springboot中使用Scheduled做定時任務---http://www.cnblogs.com/lirenqing/p/6596557.html 已經驗證的方案: pom文件加入依

spring配置quartz定時任務,支援初始化執行,迴圈執行,定點執行等

Spring配置quartz的方式有註解的方式和配置檔案的方式,今天主要說使用配置檔案的方式來實現初始化執行和定點執行 第一步,在pom.xml配置jar包依賴 <!-- 新加quartz依賴 --> <dependency>

SpringBoot使用Scheduling執行定時任務

SpringBoot自帶的 Schedule,可以將它看成一個輕量級的Quartz,而且使用起來比Quartz簡單許多 以下任務都是在單執行緒下執行的 第一步 建立SpringBoot專案 第二步 新增@EnableScheduling開啟定時任務 第三步 設定定時需要執行

Spring 配置quartz定時任務及時間設定

(1)在applicationContext-quartz.xml配置檔案裡面配置好 <!-- 定時任務啟動  定時30推送一次  reportTemporaryService為servi

搭建maven web項目並配置quartz定時任務【業務:對比數據變化內容】 歷程

uid pan 整理 maven項目 factor www .com 參考 初始化 搭建maven web項目並配置quartz定時任務【業務:對比數據變化內容】 歷程2018年03月03日 10:51:10 守望dfdfdf 閱讀數:100更多個人分類: 工作 問題編輯版

SpringBoot實現資料庫配置定時任務

spring-boot 2.0.2.RELEASE,將定時任務配置在資料庫,啟動專案的時候,用mybatis讀取資料庫,例項化物件,並設定定時任務。如果需要新增,減少,修改定時任務,僅需要修改資料庫資料,並重啟專案即可,無需改程式碼。 完整原始碼下載  https://download

ssm配置Quartz定時排程任務

1.首先在你web專案中pom.xml配置相關依賴jar包,非maven專案自行新增對應版本的jar檔案 pom.xml: <!-- quartz定時器相關依賴jar版本 --> <dependency> <groupId>or

Spring整合Quartz定時任務 在集群、分布式系統的應用(Mysql數據庫環境)

foreign log ride bigint post 業務 設置 ade 營業額 Spring整合Quartz定時任務 在集群、分布式系統中的應用(Mysql數據庫環境) 轉載:http://www.cnblogs.com/jiafuwei/p/6145280.

SpringBoot整合Quartz定時任務 的簡單實例 2

哪裏 整合 持久 是否 repeat package prop 創建方式 log (1)什麽是Quartz?(2)Quartz的特點;(3)Quartz專用詞匯說明;(4)Quartz任務調度基本實現原理; 接下來看下具體的內容: (1)什麽是Qua

quartz定時任務_job實現類獲取傳參02

hide sage 打印 exception blog div eve key tex 1.main方法: public static void main(String[] args) throws SchedulerException { // TODO Auto-ge

Spring整合quartz定時任務排程的cronExpression配置說明(轉載)

Spring整合quartz定時任務排程 "* * * * * *" 欄位   允許值   允許的特殊字元 秒   

eclipse搭建springboot學習(13)---定時任務

啟動類 package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplica

利用Windows自帶的定時任務為oracle資料庫定時備份(附oracle資料庫匯出匯入命令)

一、步驟 1、oracle資料庫匯出命令 2、將此命令做成.bat可執行檔案 3、將此可執行檔案放入Windows定時任務中 4、以上三步就已經完成資料庫的定時備份工作,這一步順便說一下如何將oracle資料庫備份檔案再還原到資料庫中 二、實操 1、oracle資料庫匯出命令

spring mvc整合Quartz框架配置定時任務

一、增加所依賴的JAR包     1、增加Spring的Maven依賴 <!--Quartz的Maven依賴 --> <dependency> <groupId>org.quartz-scheduler</group

springboot 2.0 教程-08-定時任務Quartz

閱讀原文:https://blog.bywind.cn/articles/2018/11/28/1543373589258.html 視訊教程:https://www.bilibili.com/video/av35595465 課程原始碼:https://github.com/ibywind/s

利用Windows自帶的定時任務為oracle資料庫定時備份

一、步驟 1、oracle資料庫匯出命令 2、將此命令做成.bat可執行檔案 3、將此可執行檔案放入Windows定時任務中 4、以上三步就已經完成資料庫的定時備份工作,這一步順便說一下如何將oracle資料庫備份檔案再還原到資料庫中 二、實操 1、oracle資

SpringBoot基礎教程3-1-2 Quartz定時任務快速整合

1 概述 Quartz是OpenSymphony開源組織在Job scheduling領域又一個開源專案,Quartz可以用來建立簡單或為執行十個,百個,甚至是好幾萬個Jobs這樣複雜的程式,儘管Qua

SpringBoot基礎教程3-1-3 Quartz定時任務單點持久化

1 概述 實際專案中,複雜的定時任務都會結合持久化,動態改變定時任務狀態,本文將介紹基於Quartz的定時任務單點持久化方式,通過RESTful風格,演示定時任務的CRUD,最後使用Swagger測試。 2 資料庫表說明 //Quartz表 qrtz_calen

【轉載】SpringBoot整合Quartz定時任務

Quartz是完全基於Java的,可用於進行定時任務排程的開源框架,Scheduler是Quartz的大腦,所有任務都是由它來控制。那什麼時候用到Quartz呢,比如現在寫一個介面,公司需要每10分鐘呼叫一次,我們就可以用Quartz。 1.新增SpringBoot整合