7

我试图找出我必须解决以下问题的可能性。

a) 我想要一个使用“crontab 语法”来安排任务的数据库表,其结构将是这样的:

    |-Id-|---Crontab 语法---|---------任务----------|
    | 1 | 30 * * * * * | MyClass.TaskA(args[]) |
    | 2 | 0 1 * * 1-5 * | MyClass.TaskB(args[]) |
    | | | |

上表将随时被外部应用程序修改。添加或删除的任务应立即影响调度程序。

b) 调度程序本身应该驻留在 Java 应用服务器上。它应该不断地与数据库表中的活动计划任务同步。每当调度事件发生时,它应该以“Task”中的值作为参数触发/调用 EJB。

我不是在寻找上述问题的答案。而是关于哪些框架可用于 crontab 解析以及应以何种方式部署表示调度程序的 EJB 的一些输入。

提前致谢。

4

3 回答 3

28

请参阅 EJB 3.1 @ScheduleAPI。我们为规范选择的 API 比 cron 更接近 Quartz 语法——两者之间的差异很小。

这是一个注释示例:

package org.superbiz.corn;

import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Schedule;
import javax.ejb.Schedules;
import javax.ejb.Singleton;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * This is where we schedule all of Farmer Brown's corn jobs
 */
@Singleton
@Lock(LockType.READ) // allows timers to execute in parallel
public class FarmerBrown {

    private final AtomicInteger checks = new AtomicInteger();

    @Schedules({
            @Schedule(month = "5", dayOfMonth = "20-Last", minute = "0", hour = "8"),
            @Schedule(month = "6", dayOfMonth = "1-10", minute = "0", hour = "8")
    })
    private void plantTheCorn() {
        // Dig out the planter!!!
    }

    @Schedules({
            @Schedule(month = "9", dayOfMonth = "20-Last", minute = "0", hour = "8"),
            @Schedule(month = "10", dayOfMonth = "1-10", minute = "0", hour = "8")
    })
    private void harvestTheCorn() {
        // Dig out the combine!!!
    }

    @Schedule(second = "*", minute = "*", hour = "*")
    private void checkOnTheDaughters() {
        checks.incrementAndGet();
    }

    public int getChecks() {
        return checks.get();
    }
}

这里的完整来源

您可以通过ScheduleExpression类以编程方式执行相同的操作,该类只是上述注释的可构造版本。如果计划是在代码中完成的,上面的示例如下所示:

package org.superbiz.corn;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.ScheduleExpression;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * This is where we schedule all of Farmer Brown's corn jobs
 *
 * @version $Revision$ $Date$
 */
@Singleton
@Lock(LockType.READ) // allows timers to execute in parallel
@Startup
public class FarmerBrown {

    private final AtomicInteger checks = new AtomicInteger();

    @Resource
    private TimerService timerService;

    @PostConstruct
    private void construct() {
        final TimerConfig plantTheCorn = new TimerConfig("plantTheCorn", false);
        timerService.createCalendarTimer(new ScheduleExpression().month(5).dayOfMonth("20-Last").minute(0).hour(8), plantTheCorn);
        timerService.createCalendarTimer(new ScheduleExpression().month(6).dayOfMonth("1-10").minute(0).hour(8), plantTheCorn);

        final TimerConfig harvestTheCorn = new TimerConfig("harvestTheCorn", false);
        timerService.createCalendarTimer(new ScheduleExpression().month(9).dayOfMonth("20-Last").minute(0).hour(8), harvestTheCorn);
        timerService.createCalendarTimer(new ScheduleExpression().month(10).dayOfMonth("1-10").minute(0).hour(8), harvestTheCorn);

        final TimerConfig checkOnTheDaughters = new TimerConfig("checkOnTheDaughters", false);
        timerService.createCalendarTimer(new ScheduleExpression().second("*").minute("*").hour("*"), checkOnTheDaughters);
    }

    @Timeout
    public void timeout(Timer timer) {
        if ("plantTheCorn".equals(timer.getInfo())) {
            plantTheCorn();
        } else if ("harvestTheCorn".equals(timer.getInfo())) {
            harvestTheCorn();
        } else if ("checkOnTheDaughters".equals(timer.getInfo())) {
            checkOnTheDaughters();
        }
    }

    private void plantTheCorn() {
        // Dig out the planter!!!
    }

    private void harvestTheCorn() {
        // Dig out the combine!!!
    }

    private void checkOnTheDaughters() {
        checks.incrementAndGet();
    }

    public int getChecks() {
        return checks.get();
    }
}

这个例子的来源在这里

旁注,这两个示例都可以在普通 IDE 中运行,并且具有使用 EJB 3.1 中新增的可嵌入EJBContainer API 的测试用例。

@Schedule 与 ScheduleExpression

  • @日程
    • 静态配置
    • 许多调度方法是可能的
    • 无法传递参数
    • 无法取消

以上都是在部署描述符中完成的,因此仅限于可以提前配置的内容。更动态的版本使用 TimerService 的以下签名:

TimerService.createCalendarTimer(javax.ejb.ScheduleExpression, javax.ejb.TimerConfig)

  • 调度表达式

另请注意,有一个拦截器@AroundTimeout注释,其功能与拦截器相同,@AroundInvoke并允许拦截器参与 bean 的计时器功能。

于 2011-09-09T18:31:56.373 回答
0

EJB 有自己的内置计时器,但您必须编写样板代码来翻译 cron 解析。对 cron 指令本身的解析应该是微不足道的。

如果您不害怕在 EJB 之外冒险,那么 Quartz 就像 lexicore 提到的那样是一个很好的选择。

于 2011-09-09T12:59:15.557 回答
-1

看看石英。如果你使用 Spring,那里有很好的支持。一个整洁,可靠的好工作的东西。

于 2011-09-09T12:53:21.473 回答