Spring下的Quartz的添加动态定时任务

  • Post author:
  • Post category:其他




一.首先明白Spring下Quartz的使用:

需要用到3个类:由上而下依次引用



第一个类

注入了triggers的调度工厂Bean类

org.springframework.scheduling.quartz.SchedulerFactoryBean



第二个类

注入了jobDetail和startDelay及repeatInterval的简单触发器Bean类:

org.springframework.scheduling.quartz.SimpleTriggerBean

或者注入了jobDetail和cronExpression的动态触发器:

org.springframework.scheduling.quartz.CronTriggerBean



第三个类

注入了targetObject和targetMethod的任务详情工厂Bean类:

org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean



二.第一种是静态的定时任务

主要是

SimpleTriggerBean

的属性repatInterval的赋值:设置间隔周期的毫秒值



1.书写详细的配置文件:

<!--备份数据库配置 -->
	<bean id="simpleTrigger_dbbak" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
		<property name="jobDetail" ref="dbbakjob" />
		<property name="startDelay" value="0" /><!-- 调度工厂实例化后,经过0秒开始执行调度 -->
		<property name="repeatInterval" value="36000000" /><!-- 毫秒级计算,900000==每15分钟调度一次 -->
	</bean>
	<bean id="dbbakjob"
		class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject">
			<ref bean="metaDataDbBackupService" />
		</property>
		<property name="targetMethod" value="backupDb" />
		<property name="concurrent" value="true" /><!-- 作业不并发调度 -->
	</bean>



2.service的Bean注入

<!-- 元数据的备份操作 -->
	<bean id="metaDataDbBackupService"
		  class="com.gilight.dep.metadata.service.impl.MetaDataDbBackupServiceImpl">
		<property name="cacheManager" ref="cacheManager"></property>
		<property name="metaDataBaseRepository" ref="metaDataBaseRepository"></property>
		<property name="metaModelQueryService" ref="metaModelQueryService"></property>
	</bean>



3.书写对应的业务类

  • MetaDataDbBackupServiceImpl 业务类需要实现
  • IMetaDataDbBackupService 接口
public class MetaDataDbBackupServiceImpl extends BasicServiceImpl<String> implements
		IMetaDataDbBackupService {
	private static final Logger logger = Logger.getLogger(MetaDataDbBackupServiceImpl.class);
	private IMetaDataBaseRepository metaDataBaseRepository = null;
	private IMetaModelQueryService metaModelQueryService = null;
	public IMetaModelQueryService getMetaModelQueryService() {
		return metaModelQueryService;
	}
	public void setMetaModelQueryService(
			IMetaModelQueryService metaModelQueryService) {
		this.metaModelQueryService = metaModelQueryService;
	}
	public IMetaDataBaseRepository getMetaDataBaseRepository() {
		return metaDataBaseRepository;
	}
	public void setMetaDataBaseRepository(
			IMetaDataBaseRepository metaDataBaseRepository) {
		this.metaDataBaseRepository = metaDataBaseRepository;
	}
	@Override
	public void backupDb() throws Exception {
		String path=(String) CustomizedPropertySpringConfigurer.getContextProperty("jdbc.backuppath");
		int radomInt = new Random().nextInt(999999999);
		String userName = (String) CustomizedPropertySpringConfigurer.getContextProperty("jdbc.username");
		String password=(String) CustomizedPropertySpringConfigurer.getContextProperty("jdbc.password");
		String sid=(String) CustomizedPropertySpringConfigurer.getContextProperty("jdbc.sid");

		MdDbBackup mdDbBackup = new MdDbBackup();
		mdDbBackup.setId(UUIDGenerator.getUUID());

		mdDbBackup.setStartTime(MetaDateUtils.getDefaultUpdateDate());
		mdDbBackup.setFileName(radomInt+".dmp");
		mdDbBackup.setResult(DbBakResultStatus.RUNTIME+"");
		this.getMetaDataBaseRepository().create(mdDbBackup);
		//String pathfile=path+"/"+radomInt;
		if (OracleDatabaseBackup.exportDatabaseTool(userName,password,sid,path,radomInt+"")){
			logger.warn("数据库备份成功");
			mdDbBackup.setResult(DbBakResultStatus.SUCCEED+"");
		}else {
			logger.error("数据库备份失败");
			mdDbBackup.setResult(DbBakResultStatus.FAILED+"");
		}
		mdDbBackup.setEndTime(MetaDateUtils.getDefaultUpdateDate());

		this.getMetaDataBaseRepository().update(mdDbBackup);
	}
}



三、第二种是动态的定时任务

主要是

CronTriggerBean

的cronExpression属性的cron表达式的赋值;



1. 书写详细的配置文件:

<!--动态触发器 org.springframework.scheduling.quartz.CronTriggerBean -->
	<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
		<property name="jobDetail" ref="dbBackUpJob" />
		<property name="cronExpression" value="0 0 12 * * ?" /><!--每天中午12点触发-->
	</bean>
	<bean id="simpleTrigger_dbbak" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
		<property name="jobDetail" ref="dbbakjob" />
		<property name="startDelay" value="0" /><!-- 调度工厂实例化后,经过0秒开始执行调度 -->
		<property name="repeatInterval" value="36000000" /><!-- 毫秒级计算,900000==每15分钟调度一次 -->
	</bean>



2. 其他配置,业务类和上面第一种一样



四、动态地从前台获得cronExpression并存储在数据库;

需要解决的问题是,自定义一个触发器CustomCronTrigger

  1. 需要继承CronTriggerBean;
  2. 当数据库中的cronExpression改变时,停掉并删除原来的定时任务,

    重新添加一个改变后的定时任务,(这个cronExpression一般是周期性的定时任务);
  3. 要注入一个初始化定时任务的业务;



1. 书写详细的配置文件:

<!-- 我的调度工厂 -->
	<bean id="mySchedulerFactoryBean"
		class="org.springframework.scheduling.quartz.SchedulerFactoryBean"
		lazy-init="false">
		<property name="triggers">
			<list>
				<ref local="customCronTrigger" />
			</list>
		</property>
	</bean>
	<!-- 自定义触发器 -->
	<bean id="customCronTrigger" class="com.gilight.dep.metadata.service.impl.CustomCronTrigger">
		<property name="jobDetail" ref="myJobDetail" />
		<property name="initBackupTimeService" ref="initBackupTimeService"></property>
	</bean>
	<!-- 动态备份系统jobDetail -->
	<bean id="myJobDetail"
		class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
		<property name="targetObject">
			<ref bean="systemBackupService" />
		</property>
		<property name="targetMethod" value="backupSystem" />
		<property name="concurrent" value="false" /><!-- 作业不并发调度 -->
	</bean>



2.书写Service的配置文件:

<!-- 系统备份业务 -->
	<bean id="systemBackupService" class="com.gilight.dep.metadata.service.impl.SystemBackupServiceImpl">
		<property name="systemBackupRepository" ref="systemBackupRepository"></property>
		<property name="metaDataDbBackupService" ref="metaDataDbBackupService"></property>
		<property name="mySchedulerFactoryBean" ref="mySchedulerFactoryBean"></property>
		<property name="customCronTrigger" ref="customCronTrigger"></property>
		<property name="myJobDetail" ref="myJobDetail"></property>
	</bean>
	<!--初始化系统备份时间业务 -->
	<bean id="initBackupTimeService" class="com.gilight.dep.metadata.service.impl.InitBackupTimeServiceImpl">
		<property name="systemBackupRepository" ref="systemBackupRepository"></property>
	</bean>



3.对应业务类的关系图

这里写图片描述



4.书写对应的业务类:



(1).初始化系统备份的更新时间实现类
/**
 * 初始化系统备份的更新时间实现类
 *
 */
public class InitBackupTimeServiceImpl implements IInitBackupTimeService{
	private static final Logger logger = Logger.getLogger(InitBackupTimeServiceImpl.class);
	//注入属性
	private ISystemBackupRepository systemBackupRepository = null;
	public ISystemBackupRepository getSystemBackupRepository() {
		return systemBackupRepository;
	}
	public void setSystemBackupRepository(ISystemBackupRepository systemBackupRepository) {
		this.systemBackupRepository = systemBackupRepository;
	}
	/**
	 * 获取CronExpression
	 */
	@Override
	public String getCronExpressionFromDB() throws ServiceException{
		logger.info("-------从数据库初始化最新的系统备份时间---------------");
		try {
			List<MdSystemBackup> list = systemBackupRepository.getAll();
			if(list != null && list.size()>0){
				//返回表达式
				return list.get(0).getCronExpression();
			}
			return "";
		} catch (RepositoryException e) {
			e.printStackTrace();
			throw new ServiceException("从数据库获取最新系统备份时间异常");
		}
	}

}


(2).自定义触发器:

获取初始化系统备份的更新时间

在将cronExpression设置到CronTriggerBean中;

/**
 * 自定义触发器
 * 初始化系统的备份时间
 */
public class CustomCronTrigger extends CronTriggerBean implements Serializable{
	//注入初始化时间业务
	private IInitBackupTimeService initBackupTimeService;
	public IInitBackupTimeService getInitBackupTimeService() {
		return initBackupTimeService;
	}
	public void setInitBackupTimeService(IInitBackupTimeService initBackupTimeService) throws ServiceException{
		this.initBackupTimeService = initBackupTimeService;
		//获取表达式
		String cronExpression = initBackupTimeService.getCronExpressionFromDB();
		if(cronExpression!=null && !cronExpression.equals("")){
			try{//设置表达式
				setCronExpression(cronExpression);  
			}catch(Exception e){
				e.printStackTrace();
				throw new ServiceException("自定义触发器的初始化系统的备份时间异常");
			}
		}
	}
}


(3).这个类很重要


1.首先注入5个属性;
private ISystemBackupRepository systemBackupRepository;//系统备份仓储层
private IMetaDataDbBackupService metaDataDbBackupService;//系统备份业务接口
private Scheduler mySchedulerFactoryBean;//注入调度工厂,类型Scheduler
private CustomCronTrigger customCronTrigger;//注入自定义触发器
private JobDetail myJobDetail;//注入任务详情


2.备份任务的方法backupSystem()


3.保存更新时间的方法
//当前台页面修改了备份时间会访问这个方法
saveBackupTime(String backupTime,String period);
//从触发器中获得原来执行时间和页面传来最新时间对比,如果不同,执行
changeJobDetail(backupTime);


4.改变定时任务的方法changeJobDetail(String backupTime)
//是这个类Scheduler 
mySchedulerFactoryBean;
//注入调度工厂,类型Scheduler
//改变定时任务:删除原来的任务
mySchedulerFactoryBean.deleteJob("myJobDetail", Scheduler.DEFAULT_GROUP);
//添加新任务:其中返回值的Date是触发器下次执行的时间
Date scheduleJob = mySchedulerFactoryBean.scheduleJob(myJobDetail, customCronTrigger);
//开启新任务:mySchedulerFactoryBean.start();
/**
 * 系统备份实现类
 * 修改定时任务
 */
public class SystemBackupServiceImpl extends BasicServiceImpl implements ISystemBackupService{
	private static final Logger logger = Logger.getLogger(SystemBackupServiceImpl.class);
	@Override
	public IResponse getByScope(IContext paramIContext) throws ServiceException {
		return null;
	}
	@Override
	public IModel initModel(IContext paramIContext) throws Exception {
		return null;
	}
	@Override
	public Class getModelClass() {
		return null;
	}
	//==============注入属性===============//
	private ISystemBackupRepository systemBackupRepository;//系统备份仓储层
	private IMetaDataDbBackupService metaDataDbBackupService;//系统备份业务接口
	private Scheduler mySchedulerFactoryBean;//注入调度工厂,类型Scheduler
	private CustomCronTrigger customCronTrigger;//注入自定义触发器
	private JobDetail myJobDetail;//注入任务详情
	
	public ISystemBackupRepository getSystemBackupRepository() {
		return systemBackupRepository;
	}
	public void setSystemBackupRepository(ISystemBackupRepository systemBackupRepository) {
		this.systemBackupRepository = systemBackupRepository;
	}
	public JobDetail getMyJobDetail() {
		return myJobDetail;
	}
	public void setMyJobDetail(JobDetail myJobDetail) {
		this.myJobDetail = myJobDetail;
	}
	public IMetaDataDbBackupService getMetaDataDbBackupService() {
		return metaDataDbBackupService;
	}
	public void setMetaDataDbBackupService(IMetaDataDbBackupService metaDataDbBackupService) {
		this.metaDataDbBackupService = metaDataDbBackupService;
	}
	public CustomCronTrigger getCustomCronTrigger() {
		return customCronTrigger;
	}
	public void setCustomCronTrigger(CustomCronTrigger customCronTrigger) {
		this.customCronTrigger = customCronTrigger;
	}
	public Scheduler getMySchedulerFactoryBean() {
		return mySchedulerFactoryBean;
	}
	public void setMySchedulerFactoryBean(Scheduler mySchedulerFactoryBean) {
		this.mySchedulerFactoryBean = mySchedulerFactoryBean;
	}
	
	/**
	 * 改变定时任务
	 * @param backupTime
	 * @throws ParseException
	 * @throws SchedulerException
	 */
	public void changeJobDetail(String backupTime) throws ParseException, SchedulerException {
		logger.info("-------改变定时任务-------");
		logger.info("原触发器: "+customCronTrigger.toString());
        	//更新触发器执行的时间
		customCronTrigger.setCronExpression(backupTime);
		
		//关闭原任务
		boolean deleteJob = mySchedulerFactoryBean.deleteJob("myJobDetail", Scheduler.DEFAULT_GROUP);
		if(deleteJob){
			//添加新任务;返回值Date是触发器下次执行的时间
			Date scheduleJob = mySchedulerFactoryBean.scheduleJob(myJobDetail, customCronTrigger);
			logger.info("新触发器下次执行的时间: "+scheduleJob);
			logger.info("新触发器: "+customCronTrigger.toString());
			//开启新任务
			mySchedulerFactoryBean.start();
		}
	}
	
	@Override
	public void saveBackupTime(String backupTime,String period) throws ServiceException {
		logger.info("----------开始保存系统更新时间--------------");
		try {
			MdSystemBackup mdSystemBackup = new MdSystemBackup();
			String saveTime = MetaDateUtils.getDefaultUpdateDate();//当前时间
			String status = "1";//初始状态
			String userid = null;//用户id
			mdSystemBackup.setId(UUIDGenerator.getUUID());
			mdSystemBackup.setCronExpression(backupTime);
			mdSystemBackup.setPeriod(period);
			mdSystemBackup.setSaveTime(saveTime);
			mdSystemBackup.setStatus(status);
			mdSystemBackup.setUserid(userid);
			//先清空表数据
			this.getSystemBackupRepository().empty();
			//再保存新数据
			this.getSystemBackupRepository().create(mdSystemBackup);
		} catch (RepositoryException e1) {
			e1.printStackTrace();
		}
		logger.info("----------保存系统更新时间完毕--------------");		
		
		try {// 原触发器的时间
			String cronExpression = customCronTrigger.getCronExpression();
			if (!cronExpression.equals(backupTime)) {
				// 前台时间与原触发器时间不同时,执行改变任务
				changeJobDetail(backupTime);
			}
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 备份job操作
	 */
	public void backupSystem() {
		logger.info("--------开始执行备份任务--------");
		//调用开始备份的方法
		metaDataDbBackupService.startDbbak();
		logger.info("--------备份任务执行完毕--------");
	}
}

2017/10/25/18:14 –By HDNew



版权声明:本文为new_seas原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。