关于spring中的quartz应用

最近做东西遇到这样一个问题。
我的CMS文章模块中,文章生成静态页可以有三种选择(1)立刻发布[color=red](2)定时发布[/color](3)不发布。
所遇到的问题就出在[color=red](2)定时发布[/color]这块。因为每天编辑要编写很多文章,也有很多文章要定时发布。我的架构是struts2+spring2.0+hibernate3.1,所以我想用quartz来实现这个定时发布。像这样的情况,用quartz该如何去做。
我看了网上一些quartz的文章。很多都是转载的,我都跑不起来。
[color=red]最好能给一个这方面的具体例子。代码+注释这种就最好了。
我很需要这方面详细的例子,所以希望大家能说得详细些。[/color]

[b]问题补充:[/b]
zhanglinjian 您好!谢谢你的解答!

您的配置cronExpression表达式是写在配置文件里面,我不想把这个写死。用户可以根据javascript日历自动选择发布时间。格式如:2009-08-08 11:30:05
这样的形式,然后把这个时间写在quartz里面,到了这个时间,程序自动去发布,这是针对每一篇文章的。

请问这个该如何去做?
[b]问题补充:[/b]
cats_tiger,谢谢你的帮助。但是我的问题又做了补充,请您看看有没有什么方法来解决我的问题。

这个就优点麻烦了,网上的没一个是正确的。我回头写一篇Blog吧。下面的代码是如何正确的重启:

[code="java"]
@Autowired(required = true)
private ApplicationContext ctx;

/**

  • 两个任务中的一个cron改变,则重新启动Quartz任务。
  • @param seisCron CRON1
  • @param signCron CRON2
  • @throws ApplicationException 如果CRON无法解析,或原来的任务无法关闭,以及无法启动新任务.
    */
    private void restartJobs(String seisCron, String signCron) {
    if(StringUtils.isBlank(seisCron) || StringUtils.isBlank(signCron)) {
    logger.warn("CRON未设定。");
    return;
    }
    //trim一下,难保数据库里面没有空格
    seisCron = seisCron.trim();
    signCron = signCron.trim();
    //得到两个trigger
    CronTrigger seismicCronTrigger = (CronTrigger) ctx.getBean("seismicEmailCronTrigger", CronTrigger.class);
    CronTrigger signCronTrigger = (CronTrigger) ctx.getBean("signEmailCronTrigger", CronTrigger.class);
    //如果两个频率都没有变,则不必重新启动.
    if(seisCron.equals(seismicCronTrigger.getCronExpression()) &&
    signCron.equals(signCronTrigger.getCronExpression())) {
    logger.info("频率未改变,Quartz不必重新启动.");
    return;
    }

    //得到SchedulerFactoryBean的实例,注意beanName前面的&符号
    SchedulerFactoryBean schedulerFactory = (SchedulerFactoryBean) ctx.getBean("&emailSchedulerFactory");
    try {
    //重新设定trigger
    seismicCronTrigger.setCronExpression(seisCron);
    signCronTrigger.setCronExpression(signCron);
    schedulerFactory.destroy(); //关闭原来的任务
    schedulerFactory.afterPropertiesSet(); //启动新的任务
    logger.info("前兆和测震邮件发送任务启动成功.");
    } 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("启动定时任务出现异常.");
    }

    }

[/code]

--创建作业---
public class MyJob extends QuartzJobBean {
private boolean flag=false;
@Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
// TODO Auto-generated method stub
if(!flag){
flag=true;
//业务逻辑
flag=false;
}

}

}
---创建触发器---调度事务---
<?xml version="1.0" encoding="UTF-8"?>
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">











0 0 15 * * ? //可是定时控制



org.ldsj.util.MyJob //包装作业




//如果作业类中有成员变量,可以在这边初始化



这个简单呀,下面的代码是我从项目中提取的,肯定可以执行的。
[code="xml"]

<bean id="seedProJobDetail" 
      class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject">
        <ref bean="seedpathAction"/>
    </property>
    <property name="targetMethod">
        <value>execSeedPro</value>
    </property>
    <property name="concurrent">
        <value>false</value>
    </property>
</bean>
<!-- seed程序执行触发器(trigger) -->
<bean id="seedProTrigger" 
      class="org.springframework.scheduling.quartz.CronTriggerBean">
    <property name="jobDetail">
        <ref bean="seedProJobDetail"/>
    </property>
    <property name="cronExpression">
        <value>0 0 0/4 * * ?</value>
    </property>
</bean>
<!-- 启动Quartz任务 -->
<bean id="emailSchedulerFactory"
    class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <!-- 使用内存存储,否则可能自动装配dataSource -->
    <property name="dataSource"><null/></property>
    <!-- 系统启动后自动启动任务 -->
    <property name="autoStartup" value="true"/>
    <!-- 延时20秒启动 -->
    <property name="startupDelay" value="20"/>
    <property name="triggers">
        <list>
            <ref local="seedProTrigger"/>
        </list>
    </property>
</bean>

[/code]

还有一个问题,就是如果服务器重新启动,那么原先设置的cron就都恢复原样了。这个解决起来稍微复杂一些了。需要继承CronTriggerBean,添加一个设置Cron的方法,然后写一个CronExpression的FactoryBean,在这个FactoryBean中读取数据库中的Cron。反正有点麻烦了。

你需要解决3个问题:
1.安全的重启Quartz,这个我已经回答了。
2.启动的时候,从数据库中读取Cron,这个我有方法,但是写起来比较多,打算写blog了,如果急需,我可以简单说说。
3.把时间转换为Cron,这个有点麻烦,我们的做法是给客户几个选项,比如:每隔8小时、每隔1天等等,也可以让客户自己编辑cron表达式,给他一个cron的教程,反正cron也比较简单的。在上面重启quartz的代码中,有cron表达式的验证功能。