如何用代码控制Quartz的启停

http://www.iteye.com/topic/440687

Spring中如何使用Quartz就不必说了,这里说说如果动态设定cron。
这个要解决3个问题:
1.将用户输入转换为Cron表达式
2.安全的重启quartz
3.程序启动的时候,从数据库中读取cron(而非spring配置文件中写死的那个)。
因为derpvail急着用,所以先说第3个。
动态读取数据库中的Cron,作为CronTriggerBean的属性
从数据库中读取cron,需要做一个CronExpressionFactoryBean,它是一个Spring的FactoryBean,可以读取数据库,并创建一个CronExpression对象:
Java代码
public class CronFactoryBean implements FactoryBean {
private static Logger logger = LoggerFactory.getLogger(CronFactoryBean.class);
@Autowired
@Qualifier("defaultFreq")
private String defaultCron;
/**
* 用于取得CRON表达式.
*/
@Autowired(required = true)
private CronManager cronManager;


/**
* 从数据库中取得CRON表达式,如果数据库中没有则取缺省值.
* @see EmailConstants#DEFALUT_CRON
*/
@Override
public Object getObject() throws Exception {
//如何读取数据库,就省了
String cronEx = cronManager.getCronExpression();
if(StringUtils.isBlank(cronEx)) {
return new CronExpression(defaultCron);
}
return new CronExpression(cronEx.trim());
}

@SuppressWarnings("unchecked")
@Override
public Class getObjectType() {
return CronExpression.class;
}

@Override
public boolean isSingleton() {
return true;
}

}

public class CronFactoryBean implements FactoryBean {
private static Logger logger = LoggerFactory.getLogger(CronFactoryBean.class);
@Autowired
@Qualifier("defaultFreq")
private String defaultCron;
/**
* 用于取得CRON表达式.
*/
@Autowired(required = true)
private CronManager cronManager;


/**
* 从数据库中取得CRON表达式,如果数据库中没有则取缺省值.
* @see EmailConstants#DEFALUT_CRON
*/
@Override
public Object getObject() throws Exception {
//如何读取数据库,就省了
String cronEx = cronManager.getCronExpression();
if(StringUtils.isBlank(cronEx)) {
return new CronExpression(defaultCron);
}
return new CronExpression(cronEx.trim());
}

@SuppressWarnings("unchecked")
@Override
public Class getObjectType() {
return CronExpression.class;
}

@Override
public boolean isSingleton() {
return true;
}

}


然后呢,就是吧这个CronExpression对象注入到CronTriggerBean,但是CronTriggerBean的setCronExpression方法是重载的,本人不知道如何注入重载方法,所以只好继承了CronTriggerBean,添加了一个setCron方法,一遍于Spring的注入:
Java代码
/**
* FIXME:因为目前不知道如何实现重载方法的注入,而<code>CronTrigger</code>
* 的<code>setCronExpression</code>既可以用<code>CronExpression</code>
* 对象作为参数也可以用String作为参数,这就产生了不确定性。所以,我们extends了
* <code>CronTriggerBean</code>,提供{@link #setCron(CronExpression)}
* 方法,避免这种不确定性。
* @author Sam
*
*/
public class CronTriggerBeanEx extends CronTriggerBean {
/**
* 调用父类的{@link CronTriggerBean#setCronExpression(CronExpression)}
* 方法.
*/
public void setCron(CronExpression cronExpression) {
this.setCronExpression(cronExpression);
}
}

/**
* FIXME:因为目前不知道如何实现重载方法的注入,而<code>CronTrigger</code>
* 的<code>setCronExpression</code>既可以用<code>CronExpression</code>
* 对象作为参数也可以用String作为参数,这就产生了不确定性。所以,我们extends了
* <code>CronTriggerBean</code>,提供{@link #setCron(CronExpression)}
* 方法,避免这种不确定性。
* @author Sam
*
*/
public class CronTriggerBeanEx extends CronTriggerBean {
/**
* 调用父类的{@link CronTriggerBean#setCronExpression(CronExpression)}
* 方法.
*/
public void setCron(CronExpression cronExpression) {
this.setCronExpression(cronExpression);
}
}


然后就是在spring中配置这两个Bean了,和普通的quartz类似,只不过cronExpression属性改为了cron属性:
Xml代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans default-lazy-init="false">
<bean id="seismicEmailCronTrigger"
class="datashare.email.admin.jobs.CronTriggerBeanEx">
<property name="jobDetail" ref="seismicEmailJobDetail" />
<property name="cron">
<bean class="datashare.email.admin.jobs.CronFactoryBean">
</property>
</bean>
</property>
</bean>
</beans>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans default-lazy-init="false">
<bean id="seismicEmailCronTrigger"
class="datashare.email.admin.jobs.CronTriggerBeanEx">
<property name="jobDetail" ref="seismicEmailJobDetail" />
<property name="cron">
<bean class="datashare.email.admin.jobs.CronFactoryBean">
</property>
</bean>
</property>
</bean>
</beans>

注意default-lazy-init="false",这样,quartz就可以在项目启动的时候,读取数据库中的cron了。
先写到这里,开会了....
安全的重启quartz
貌似网上的文章都不太对,下面的这方法可以正常运行,在此之前,你应该把ApplicationContext注入,可以用ApplicationContextAware接口,也可以用@Autowired注解:
Java代码
@Autowired(required = true)
private ApplicationContext ctx;

/**
* 如果cron改变,则重新启动Quartz任务。

* @param signCron 用户输入的CRON,你可以把它先存入数据库
* @throws ApplicationException 如果CRON无法解析,或原来的任务无法关闭,以及无法启动新任务.
*/
private void restartJobs(String signCron) {
if(StringUtils.isBlank(signCron)) {
logger.warn("CRON未设定。");
return;
}
//trim一下,难保没有空格
signCron = signCron.trim();
//得到trigger

CronTrigger signCronTrigger = (CronTrigger) ctx.getBean("signEmailCronTrigger", CronTrigger.class);
//如果频率都有变,则不必重新启动.
if(signCron.equals(signCronTrigger.getCronExpression())) {
logger.info("前兆和测震发送频率都未改变,Quartz不必重新启动.");
return;
}
//[b]下面是关键[/b]
//得到SchedulerFactoryBean的实例,注意beanName前面的&符号
SchedulerFactoryBean schedulerFactory = (SchedulerFactoryBean) ctx.getBean("&emailSchedulerFactory");
try {
//重新设定trigger
signCronTrigger.setCronExpression(signCron);
schedulerFactory.destroy(); //关闭原来的任务
schedulerFactory.afterPropertiesSet(); //启动新的任务
logger.info("XXX任务启动成功.");
} catch (ParseException e) {
throw new ApplicationException("Cron表达式解析错误." + e.getMessage());
} catch (SchedulerException e) {
e.printStackTrace();
throw new ApplicationException("关闭定时任务出现异常.");
} catch (Exception e) {
e.printStackTrace();
throw new ApplicationException("启动定时任务出现异常.");
}
}
//我原来的代码和这个略有不同,这段代码没有调试过(在JE上编辑的),不过应该可以运行

@Autowired(required = true)
private ApplicationContext ctx;

/**
* 如果cron改变,则重新启动Quartz任务。

* @param signCron 用户输入的CRON,你可以把它先存入数据库
* @throws ApplicationException 如果CRON无法解析,或原来的任务无法关闭,以及无法启动新任务.
*/
private void restartJobs(String signCron) {
if(StringUtils.isBlank(signCron)) {
logger.warn("CRON未设定。");
return;
}
//trim一下,难保没有空格
signCron = signCron.trim();
//得到trigger

CronTrigger signCronTrigger = (CronTrigger) ctx.getBean("signEmailCronTrigger", CronTrigger.class);
//如果频率都有变,则不必重新启动.
if(signCron.equals(signCronTrigger.getCronExpression())) {
logger.info("前兆和测震发送频率都未改变,Quartz不必重新启动.");
return;
}
//[b]下面是关键[/b]
//得到SchedulerFactoryBean的实例,注意beanName前面的&符号
SchedulerFactoryBean schedulerFactory = (SchedulerFactoryBean) ctx.getBean("&emailSchedulerFactory");
try {
//重新设定trigger
signCronTrigger.setCronExpression(signCron);
schedulerFactory.destroy(); //关闭原来的任务
schedulerFactory.afterPropertiesSet(); //启动新的任务
logger.info("XXX任务启动成功.");
} catch (ParseException e) {
throw new ApplicationException("Cron表达式解析错误." + e.getMessage());
} catch (SchedulerException e) {
e.printStackTrace();
throw new ApplicationException("关闭定时任务出现异常.");
} catch (Exception e) {
e.printStackTrace();
throw new ApplicationException("启动定时任务出现异常.");
}
}
//我原来的代码和这个略有不同,这段代码没有调试过(在JE上编辑的),不过应该可以运行

先写到这里,开会了,其实下一个问题我也没有什么好办法....

将用户输入转换为Cron表达式,这个问题我已经解决了。
因为我的都是定时发布任务,时间形如:2008-08-08 11:08:28这样的形式,所以转换方法参照cron的表达式还是很好写的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Quartz 是一个开源的、基于 Java 实现的定时任务调度框架,可以非常方便地实现定时任务的调度和管理。 下面是一个使用 Quartz 实现定时任务的示例代码: 1. 导入相关依赖包 ```xml <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version> </dependency> ``` 2. 创建 Job 类 ```java public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 定时任务执行的逻辑代码 System.out.println("Hello Quartz!"); } } ``` 3. 创建 Trigger ```java // 创建一个每分钟执行一次的 Trigger Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger1", "group1") .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(60) .repeatForever()) .build(); ``` 4. 创建 Scheduler ```java // 创建 Scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.start(); // 创建 JobDetail JobDetail jobDetail = JobBuilder.newJob(MyJob.class) .withIdentity("job1", "group1") .build(); // 将 Trigger 和 JobDetail 注册到 Scheduler 中 scheduler.scheduleJob(jobDetail, trigger); ``` 完整的示例代码如下: ```java import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; public class QuartzDemo { public static void main(String[] args) throws SchedulerException { // 创建 Scheduler Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.start(); // 创建 JobDetail JobDetail jobDetail = JobBuilder.newJob(MyJob.class) .withIdentity("job1", "group1") .build(); // 创建一个每分钟执行一次的 Trigger Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("trigger1", "group1") .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(60) .repeatForever()) .build(); // 将 Trigger 和 JobDetail 注册到 Scheduler 中 scheduler.scheduleJob(jobDetail, trigger); } public static class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 定时任务执行的逻辑代码 System.out.println("Hello Quartz!"); } } } ``` 这个示例代码中创建了一个每分钟执行一次的定时任务,你可以根据需要修改 Trigger 的执行规则来实现不同的定时任务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值