Quartz学习笔记-Spring整合与简单使用

Quartz 是个开源的作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。Quartz 允许开发人员根据时间间隔来调度作业。它实现了作业和触发器的多对多关系,还能把多个作业与不同的触发器关联。整合了 Quartz 的应用程序可以重用来自不同事件的作业,还可以为一个事件组合多个作业。这里主要记录一下Spring与Quartz的整合集成使用。


quartz.properties

#============================================================================
# Configure Scheduler
#============================================================================
# 当多个调度器实例在一个程序里时,就需要为客户端代码区别每个调度器。
# 如果使用集群特性,必须为在集群里的每个实例用一样的名字,实现逻辑上一样的调度器。
org.quartz.scheduler.instanceName = QuartzScheduler   
# 如果在一个集群里多个实例是一个逻辑上一样的调度器时,每个实例的这项属性必须唯一。
# 可以设置这项为“AUTO”从而自动收集ID。
org.quartz.scheduler.instanceId = AUTO  
# 这个属性设置Scheduler在检测到JobStore到某处的连接(比如到数据库的连接)断开后,
# 再次尝试连接所等待的毫秒数。这个参数在使用RamJobStore无效。
org.quartz.scheduler.dbFailureRetryInterval = 1500
# 如果想要连接到远程的调度器服务,要设置为true,指定一个主机和端口号。
org.quartz.scheduler.rmi.proxy = false

#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

#============================================================================
# Configure JobStore
#============================================================================
# 将Scheduler相关信息保存在RDB中.有两种实现:JobStoreTX和JobStoreCMT
# 前者为Application自己管理事务,后者为Application Server管理事务,即全局事务JTA
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
# 类似于Hibernate的Dialect,用于处理DB之间的差异,StdJDBCDelegate能满足大部分的DB
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 设置数据源,数据源将在应用服务器里被配置和管理
org.quartz.jobStore.dataSource = defaultDS 
# 设置属性为true是让Quartz不去在JDBC连接上调用setAutoCommit(false)这个函数
org.quartz.jobStore.dontSetAutoCommitFalse = false
# 在触发器被认为没有触发之前,调度器能承受一个触发器再次触发的一个毫秒级数字。
# 最大能忍受的触发超时时间,如果超过则认为“失误”
org.quartz.jobStore.misfireThreshold = 60000
# 数据库中表名前缀
org.quartz.jobStore.tablePrefix = QRTZ_
# JobStore处理未按时触发的Job的数量
org.quartz.jobStore.maxMisfiresToHandleAtATime = 10
# JobDataMaps是否都为String类型
org.quartz.jobStore.useProperties = true
# 是否是应用在集群中,当应用在集群中时必须设置为TRUE,否则会出错
org.quartz.jobStore.isClustered = true
# 集群检测间隔,Scheduler的Checkin时间,时间长短影响Failure Scheduler的发现速度
org.quartz.jobStore.clusterCheckinInterval = 20000

#============================================================================
# Configure DataSource
#============================================================================
org.quartz.dataSource.defaultDS.driver = com.mysql.jdbc.Driver
org.quartz.dataSource.defaultDS.URL = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
org.quartz.dataSource.defaultDS.user = root
org.quartz.dataSource.defaultDS.password = 123456
org.quartz.dataSource.defaultDS.maxConnections = 10
org.quartz.dataSource.defaultDS.validationQuery = select 1
org.quartz.dataSource.defaultDS.idleConnectionValidationSeconds = 50
org.quartz.dataSource.defaultDS.validateOnCheckout = false
org.quartz.dataSource.defaultDS.discardIdleConnectionsSeconds = 1000

#============================================================================
# Configure PlugIn
#============================================================================
# Trigger历史日志记录插件
org.quartz.plugin.triggHistory.class = org.quartz.plugins.history.LoggingTriggerHistoryPlugin
org.quartz.plugin.triggHistory.triggerFiredMessage = Trigger \{1\}.\{0\} fired job \{6\}.\{5\} at: \{4, date, HH:mm:ss MM/dd/yyyy}
org.quartz.plugin.triggHistory.triggerCompleteMessage = Trigger \{1\}.\{0\} completed firing job \{6\}.\{5\} at \{4, date, HH:mm:ss MM/dd/yyyy\}.
# Shutdown Hook插件,通过捕捉JVM关闭时的事件,来关闭调度器
org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownhook.cleanShutdown = true


applicationContext-scheduler.xml



	
	
	
		
		
		
		  
	
	
	
	
	
	
	
		 
		 
		 
		 
	 
	
	
	
		  
	

    
    
    	
    	  
    	
    	  
    	
		  
    	
    	
    	
    	  
            
            
            
            
                
                schedulerContextAsMap    
                  
                
          
                      
        	                  
        		
        	          
              
             
    
    
     
    	
    	       
    	
		               
    	
		               
    	
    	          
    	
    	      
            
    
    
      
    	
		       
    	
		       
    	
		      
    	
          
    	
             
    	
          
             
        
        	
        		
        		
        	
        
      
	  


SchedulerFactoryExtBean

public class SchedulerFactoryExtBean extends SchedulerFactoryBean {

	@Override
	public void afterPropertiesSet() throws Exception {
		if (isAutoStartup()) {
			super.afterPropertiesSet();
		}
	}
	
}

Quartz的简单使用

@Service("schedulerBusiness")
public class SchedulerBusinessImpl implements ISchedulerBusiness {
	
	private static final Logger LOG = LoggerFactory.getLogger(SchedulerBusinessImpl.class);
	
	@Resource(name = "schedulerFactory")
	private Scheduler scheduler = null;
	
	@SuppressWarnings("unchecked")
	@Override
	public void insert(String jobGroup, String jobName, String jobClass, String triggerGroup,
			String triggerName, String cron) throws BusinessException {
		LOG.info("Insert Scheduler {} - {} - {} - {} - {} - {} ", jobGroup, jobName, jobClass, 
				triggerGroup, triggerName, cron);
		checkParamNotNull(jobGroup, "任务组名", jobName, "任务名称", jobClass, "任务实现类", cron, "任务Cron表达式");
		try {
			JobKey jobKey = new JobKey(jobName, jobGroup);
			if (scheduler.checkExists(jobKey)) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该任务已经存在");
			} 
			if (StringUtils.isBlank(triggerGroup)) triggerGroup = jobGroup;
			if (StringUtils.isBlank(triggerName)) triggerName = jobName;
			TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroup);
			if (scheduler.checkExists(triggerKey)) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该任务Trigger已经存在");
			}
			CronExpression cronExpression = new CronExpression(cron);
			ScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
			CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey)
					.withSchedule(cronScheduleBuilder).build();
			Class jobClazz = (Class) Class.forName(jobClass);
			JobDetail jobDetail = JobBuilder.newJob().withIdentity(jobKey).ofType(jobClazz)
					.storeDurably(true).requestRecovery(true).build();
			scheduler.scheduleJob(jobDetail, cronTrigger);
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		} 
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void updateJobCron(String jobGroup, String jobName, String cron) throws BusinessException {
		checkParamNotNull(jobGroup, "任务组名", jobName, "任务名称", cron, "任务Cron表达式");
		try {
			JobKey jobKey = new JobKey(jobName, jobGroup);
			if (!scheduler.checkExists(jobKey)) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该任务不存在");
			} 
			List cronTriggers = (List) scheduler.getTriggersOfJob(jobKey);
			if (null == cronTriggers || cronTriggers.size() == 0) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该任务不存在Trigger");
			}
			CronTrigger oldCronTrigger = cronTriggers.get(0);
			CronExpression cronExpression = new CronExpression(cron);
			ScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
			CronTrigger newCronTrigger = oldCronTrigger.getTriggerBuilder().withSchedule(cronScheduleBuilder).build();
			scheduler.rescheduleJob(oldCronTrigger.getKey(), newCronTrigger);
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		} 
	}
	
	@Override
	public void updateTrigger(String triggerGroup, String triggerName, String cron) throws BusinessException {
		checkParamNotNull(triggerGroup, "Trigger组名", triggerName, "Trigger名称", cron, "Cron表达式");
		try {
			TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroup);
			Trigger trigger = scheduler.getTrigger(triggerKey);
			if (null == trigger) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该Trigger不存在");
			}
			CronTrigger oldCronTrigger = (CronTrigger) trigger;
			CronExpression cronExpression = new CronExpression(cron);
			ScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
			CronTrigger newCronTrigger = oldCronTrigger.getTriggerBuilder().withSchedule(cronScheduleBuilder).build();
			scheduler.rescheduleJob(triggerKey, newCronTrigger);
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		} 
	}
	
	@Override
	public void pauseJob(String jobGroup, String jobName) throws BusinessException {
		checkParamNotNull(jobGroup, "任务组名", jobName, "任务名称");
		try {
			JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
			if (!scheduler.checkExists(jobKey)) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该任务不存在");
			}
			scheduler.pauseJob(jobKey);
		} catch (SchedulerException e) {
			LOG.error(e.getMessage(), e);
		}
	}
	
	@Override
	public void pauseTrigger(String triggerGroup, String triggerName) throws BusinessException {
		checkParamNotNull(triggerGroup, "Trigger组名", triggerName, "Trigger名称");
		try {
			TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroup);
			if (!scheduler.checkExists(triggerKey)) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该Trigger不存在");
			}
			scheduler.pauseTrigger(triggerKey);
		} catch (SchedulerException e) {
			LOG.error(e.getMessage(), e);
		}
	}
	
	@Override
	public void resumeJob(String jobGroup, String jobName) throws BusinessException {
		checkParamNotNull(jobGroup, "任务组名", jobName, "任务名称");
		try {
			JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
			if (!scheduler.checkExists(jobKey)) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该任务不存在");
			}
			scheduler.resumeJob(jobKey);
		} catch (SchedulerException e) {
			LOG.error(e.getMessage(), e);
		}
	}
	
	@Override
	public void resumeTrigger(String triggerGroup, String triggerName) throws BusinessException {
		checkParamNotNull(triggerGroup, "Trigger组名", triggerName, "Trigger名称");
		try {
			TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroup);
			if (!scheduler.checkExists(triggerKey)) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该Trigger不存在");
			}
			scheduler.resumeTrigger(triggerKey);
		} catch (SchedulerException e) {
			LOG.error(e.getMessage(), e);
		}
	}
	
	@Override
	public void delete(String jobGroup, String jobName) throws BusinessException {
		checkParamNotNull(jobGroup, "任务组名", jobName, "任务名称");
		try {
			JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
			if (!scheduler.checkExists(jobKey)) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该任务不存在");
			}
			scheduler.deleteJob(jobKey);
		} catch (SchedulerException e) {
			LOG.error(e.getMessage(), e);
		}
	}
	
	@Override
	public JobDTO readJob(String jobGroup, String jobName) throws BusinessException {
		checkParamNotNull(jobGroup, "任务组名", jobName, "任务名称");
		try {
			JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
			if (!scheduler.checkExists(jobKey)) {
				throw new BusinessException(ExceptionCode.PARAM_ERROR, "该任务不存在");
			}
			return readJobDTOByJobKey(jobKey);
		} catch (SchedulerException e) {
			LOG.error(e.getMessage(), e);
		}
		return null;
	}
	
	@Override
	public List readJobs() throws BusinessException {
		List jobDTOList = new ArrayList();
		try {
			GroupMatcher matcher = GroupMatcher.anyJobGroup();
			Set jobKeys = scheduler.getJobKeys(matcher);
			if (null == jobKeys || jobKeys.size() == 0) return jobDTOList;
			for (JobKey jobKey : jobKeys) {
				JobDTO jobDTO = readJobDTOByJobKey(jobKey);
				jobDTOList.add(jobDTO);
			}
		} catch (SchedulerException e) {
			LOG.error(e.getMessage(), e);
		}
		return jobDTOList;
	}
	
	private void checkParamNotNull(Object... params) {
		for (int i = 0, len = params.length; i < len; i++) {
			checkSingleParamNotNull(params[i], (String) params[++i]);
		}
	}
	
	private void checkSingleParamNotNull(Object paramValue, String paramName) {
		boolean isNull = false;
		if (paramValue instanceof String) {
			isNull = StringUtils.isBlank((String) paramValue);
		} else {
			isNull = null == paramValue ? true : false;
		}
		if (isNull) throw new BusinessException(ExceptionCode.PARAM_NULL, paramName + "不能为空");
	}
	
	@SuppressWarnings("unchecked")
	private JobDTO readJobDTOByJobKey(JobKey jobKey) {
		JobDTO jobDTO = new JobDTO();
		try {
			jobDTO.setGroup(jobKey.getGroup());
			jobDTO.setName(jobKey.getName());
			JobDetail jobDetail = scheduler.getJobDetail(jobKey);
			jobDTO.setDescription(jobDetail.getDescription());
			jobDTO.setJobClass(jobDetail.getJobClass().getName());
			jobDTO.setDurable(jobDetail.isDurable());
			jobDTO.setRequestsRecovery(jobDetail.requestsRecovery());
			List triggerList = (List) scheduler.getTriggersOfJob(jobKey);
			for (int i = 0, len = triggerList.size(); i < len; i++) {
				CronTrigger cronTrigger = triggerList.get(i);
				TriggerKey triggerKey = cronTrigger.getKey();
				TriggerDTO triggerDTO = new TriggerDTO();
				triggerDTO.setGroup(triggerKey.getGroup());
				triggerDTO.setName(triggerKey.getName());
				triggerDTO.setDescription(cronTrigger.getDescription());
				triggerDTO.setCronExpression(cronTrigger.getCronExpression());
				triggerDTO.setStartTime(cronTrigger.getStartTime());
				triggerDTO.setEndTime(cronTrigger.getEndTime());
				triggerDTO.setFinalFireTime(cronTrigger.getFinalFireTime());
				Trigger.TriggerState triggerState = scheduler.getTriggerState(triggerKey);
				triggerDTO.setStatus(triggerState.name());
				jobDTO.getTriggers().add(triggerDTO);
			}
		} catch (SchedulerException e) {
			LOG.error(e.getMessage(), e);
		}
		return jobDTO;
	}
	
}


相关信息可以在 https://github.com/fighting-one-piece/repository-public.git 里面查看




你可能感兴趣的:(J2EE,Quartz,Spring,任务调度)