java 有一个带有“crontab 语法”的 EJB 调度任务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7361889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Have an EJB schedule tasks with "crontab syntax"
提问by aksamit
I am trying to figure out the possibilities I have to solve the following problem.
我试图找出解决以下问题的可能性。
a) I want to have a database table that uses "crontab syntax" to schedule tasks, the structure would be something like this:
a) 我想要一个使用“crontab 语法”来调度任务的数据库表,结构将是这样的:
|-Id-|---Crontab Syntax---|---------Task----------| | 1 | 30 * * * * * | MyClass.TaskA(args[]) | | 2 | 0 1 * * 1-5 * | MyClass.TaskB(args[]) | | | | |
The above table will be modified at any time by an external application. Tasks added or removed should instantly affect the scheduler.
上表将随时被外部应用程序修改。添加或删除的任务应立即影响调度程序。
b) The scheduler itself should reside on a Java application server. It should constantly be synched with the active scheduled tasks in the database table. Whenever a schedule event occurs it should trigger/call an EJB with the value in 'Task' as argument.
b) 调度器本身应该驻留在 Java 应用服务器上。它应该不断与数据库表中的活动计划任务同步。每当调度事件发生时,它应该以“Task”中的值作为参数触发/调用 EJB。
I am not looking for an answer to the above problem. But rather some input in what frameworks can be used for the crontab parsing and in what manner the EJB representing the scheduler should be deployed.
我不是在寻找上述问题的答案。而是关于哪些框架可用于 crontab 解析以及代表调度程序的 EJB 应以何种方式部署的一些输入。
Thanks in advance.
提前致谢。
回答by David Blevins
See the EJB 3.1 @Schedule
API. The API we chose for the spec is a little closer to Quartz syntax than cron -- tiny variances between the two.
请参阅 EJB 3.1 @Schedule
API。我们为规范选择的 API 比 cron 更接近 Quartz 语法——两者之间的差异很小。
Here's an annotation example:
这是一个注释示例:
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();
}
}
Full source for this here
这里的完整来源
You can do the same thing programmatically via the ScheduleExpressionclass which is just a constructable version of the above annotation. Here's what the above example would look like if the schedule was done in code:
您可以通过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();
}
}
The source for this example is here
这个例子的来源是here
Side note, both examples are runnable in a plain IDE and have test cases that use the Embeddable EJBContainerAPI also new in EJB 3.1.
旁注,这两个示例都可以在普通 IDE 中运行,并且具有使用EJB 3.1 中的新功能Embeddable EJBContainerAPI 的测试用例。
@Schedule vs ScheduleExpression
@Schedule 与 ScheduleExpression
- @Schedule
- Statically configured
- Many schedule methods are possible
- Not possible to pass arguments
- Cannot be cancelled
- @日程
- 静态配置
- 许多调度方法是可能的
- 无法传递参数
- 不能取消
The above is all done in the deployment descriptor and is therefore limited to only things that can be configured in advance. The more dynamic version uses the following signature of the TimerService:
以上都是在部署描述符中完成的,因此仅限于可以提前配置的内容。更动态的版本使用 TimerService 的以下签名:
TimerService.createCalendarTimer(javax.ejb.ScheduleExpression, javax.ejb.TimerConfig)
TimerService.createCalendarTimer(javax.ejb.ScheduleExpression, javax.ejb.TimerConfig)
- ScheduleExpression
- Dynamically created
- Exactly one @Timeout supports all ScheduleExpression
- The timeout method must take
javax.ejb.Timer
as a parameter - Arguments can be passed
- The caller wraps arguments in a TimerConfig.setInfo(Serializable)object
- The @Timeout method accesses them via Timer.getInfo()
- Can be cancelled by the caller or the @Timeout method
- 调度表达式
- 动态创建
- 正好一个@Timeout 支持所有的 ScheduleExpression
- 超时方法必须
javax.ejb.Timer
作为参数 - 可以传递参数
- 调用者将参数包装在TimerConfig.setInfo(Serializable)对象中
- @Timeout 方法通过Timer.getInfo()访问它们
- 可以由调用者或@Timeout 方法取消
Also note that there is an interceptor @AroundTimeout
annotation that functions identically to @AroundInvoke
and allows interceptors to participate in the bean's timer functionality.
另请注意,有一个拦截器@AroundTimeout
注释,其功能与拦截器的功能相同,@AroundInvoke
并允许拦截器参与 bean 的计时器功能。
回答by mikek
EJB has its own built in timers, but you'll have to write the boilerplate code to translate cron parsing. The parsing of the cron instructions themselves should be trivial.
EJB 有自己内置的timers,但是您必须编写样板代码来转换 cron 解析。cron 指令本身的解析应该是微不足道的。
If you're not afraid of venturing outside of EJB, Quartz is as lexicore mentioned an excellent option.
如果您不害怕在 EJB 之外冒险,那么 Quartz 就像 lexicore 提到的那样是一个很好的选择。