Java 将EJB调度任务与“任务”;crontab语法;

Java 将EJB调度任务与“任务”;crontab语法;,java,jakarta-ee,ejb,crontab,schedule,Java,Jakarta Ee,Ejb,Crontab,Schedule,我试图找出解决以下问题的可能性 a) 我想要一个使用“crontab语法”调度任务的数据库表,其结构如下: |-Id-|---Crontab Syntax---|---------Task----------| | 1 | 30 * * * * * | MyClass.TaskA(args[]) | | 2 | 0 1 * * 1-5 * | MyClass.TaskB(args[]) | | | |

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

a) 我想要一个使用“crontab语法”调度任务的数据库表,其结构如下:

|-Id-|---Crontab Syntax---|---------Task----------| | 1 | 30 * * * * * | MyClass.TaskA(args[]) | | 2 | 0 1 * * 1-5 * | MyClass.TaskB(args[]) | | | | | |-Id-|--Crontab语法-|--Task----------| |1 | 30********MyClass.TaskA(args[])| |2 | 0 1**1-5*| MyClass.TaskB(args[]| | | | | 外部应用程序将随时修改上表。添加或删除的任务应立即影响计划程序

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

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

提前谢谢。

看一看。如果你使用弹簧,那里有很好的支撑。这是一个整洁、可靠的好东西。

EJB有自己的内置功能,但您必须编写样板代码来翻译cron解析。cron指令本身的解析应该很简单


如果您不怕冒险走出EJB,那么正如lexicore所提到的,Quartz是一个很好的选择。

请参阅EJB3.1
@Schedule
API。我们为规范选择的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();
    }
}
这篇文章的完整来源

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

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中运行,并且都有使用EJB3.1中新增的可嵌入API的测试用例

@计划与计划表达式
  • @时间表
    • 静态配置
    • 许多计划方法都是可能的
    • 无法传递参数
    • 不能取消
以上内容都是在部署描述符中完成的,因此仅限于可以提前配置的内容。更具动态性的版本使用TimerService的以下签名:

  • 调度表达式
    • 动态创建
    • 只有一个@Timeout支持所有ScheduleExpression
    • 超时方法必须将
      javax.ejb.Timer
      作为参数
    • 可以传递参数
      • 调用方将参数包装到对象中
      • @Timeout方法通过
    • 可由调用方或@Timeout方法取消

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

感谢您提供的非常描述性的答案。我对ScheduleAPI做了一些实验。然而,我看到这种方法的一个局限性是,我无法将事件安排到具有特定参数的通用方法。所以我只能调度预定义的方法,或者你看到我忽略的一种可能性了吗?ScheduleExpression API就是这样:一个通用方法,每个调度都有特定的参数。我已经更新了答案,试图再强调一点。谢谢。解决了我的问题,无需添加Quartz(这也可以解决任务),如果有新的ScheduleExpression(“0 1**1-5*”/*crontabLine*/)就好了