Java EE调度程序

Java EE应用程序服务器具有本机调度支持,并且在大多数应用程序中,不需要包括外部依赖项,例如著名的Quartz调度程序库。

Java EE 6和7完整配置文件中提供的Java EE 6计时器服务为我们提供了许多选项来定义调度间隔,以及如果停止并重新启动包含调度程序的应用程序会发生什么情况。

Java EE调度程序可以是:

  • 持久的 :应用程序服务器在应用程序关闭时保存计划事件,以免丢失事件
  • 自动 :简单的调度程序定义,大多数细节由应用程序服务器处理
  • 程序化的 :我们可以完全控制所有调度程序参数。

为了确定哪个是最佳选择,我们应该首先回答以下问题:

1.是否可以错过一些调度事件?

如果我们停止或重新启动应用程序(例如在更新过程中),则调度程序将停止,并且某些调度事件可能会丢失。

可以将调度程序配置为保存错过的事件,并在应用程序再次启动时执行它们。 应用程序服务器使用内部数据库(通常是Derby之类的Java DB)来存储丢失的事件。

这是一个持久的调度程序。

注意 :应用程序服务器将在应用程序(重新)启动时生成所有丢失的事件。 事件突发的频率和延迟是可配置的。 有关详细信息,请参见应用程序服务器文档。

我们还可以选择不保留计划事件,如果应用程序未运行,则计划事件将丢失。

在非持久性情况下,调度程序生命周期与应用程序相同:它在应用程序启动时创建,然后在应用程序关闭时销毁。

相反,持久性调度程序可以保留到应用程序重新启动; 当应用程序未运行时,它只是在休眠。

如何选择?

如果计划的功能对业务至关重要,并且我们不能错过任何事件,那么持久性计划程序就是您的理想之选。

在所有其他情况下,非持久性调度程序更轻便(不使用数据库)并且易于管理(更新应用程序时的障碍更少,因为在应用程序重新启动时不会出现调度事件;在应用程序启动时始终会创建新的调度程序)。

2.该应用程序将在群集中运行吗?

在集群中,我们的应用程序有多个实例正在运行(每个集群节点一个实例),并且所有实例都有自己的调度程序副本。

但是我们只需要在所有群集节点之间运行一个调度程序,否则我们将拥有同一事件的多个副本。

每个应用程序服务器都有自己的方式来处理“多个调度程序实例”问题(例如,请参阅WebSphere的[link 2]),但是通常,当我们使用集群时,要求调度程序应该是持久的。

3.调度间隔在生产时是否可以编程?

要回答的另一个重要问题:在部署应用程序后,我们是否应该能够更改调度?

如果调度参数(它的频率)是固定的,则自动调度程序是最佳解决方案,因为它的编码非常简单:只需一个注释(如果您喜欢旧方法,则可以少写XML行)。

相反,如果调度程序应该以某种方式可配置,则最好的解决方案是编程调度程序,它使我们能够在应用程序启动期间定义所有调度程序参数,并从属性文件,数据库或我们正在使用的任何配置解决方案中读取它们。

记得:

  • 自动调度程序计划是在构建时定义的
  • 在应用程序启动时定义了程序化调度程序计划

自动排程器

定义自动调度程序非常容易:

  1. 创建在启动时执行的单例EJB
  2. 创建一个将在每次调度事件时调用的方法

注意:完整的代码可以在文章项目中找到[请参见链接3]。

第一步:

@Startup
@Singleton
public class MyScheduler

@ javax.ejb.Startup批注要求EJB容器在应用程序启动时创建EJB(以及我们的调度程序)。

@ javax.ejb.Singleton批注强制EJB容器仅创建一个实例。

重要提示:调度程序由应用程序服务器(EJB容器)使用; 应用程序代码的其余部分永远不要实例化它。

然后,我们需要在安排事件时调用的方法:

@Schedule(/** scheduling parameters */)
public void doSomeThing() {..}

该方法应为public,并返回void。

@ javax.ejb.Schedule注释定义:

  • 计划间隔,以cron格式[请参见链接4]
  • 调度程序的名称(应用程序中可以有许多调度程序)
  • 一个持久的布尔标志,它定义调度程序是否持久

例如:

@Schedule(
    minute = "*/15",
    hour = "*",
    info = "15MinScheduler",
    persistent = false )

它定义了每15分钟运行一次的非持久性调度程序。

有关完整示例,请参见文章项目[链接3]中的AutomaticPersistentSchedulerAutomaticNonPersistentScheduler类。

注意 :还有@Schedules批注[请参见链接1],该批注允许定义多个@Schedule定义。

当存在无法在单个cron定义中表达的计划要求时,此功能很有用。

程序调度器

程序化调度程序的构建更为复杂,但是它为我们提供了定义调度程序参数的完全自由。

我们还有更多步骤:

  1. 创建在启动时执行的单例EJB
  2. 查找TimerService资源
  3. 在EJB初始化时创建调度程序
  4. 创建一个@Timeout方法

第一步与自动调度程序相同:

@Startup
@Singleton
public class MyScheduler

然后(第二步),我们需要查找应用程序服务器计时器服务,但是注入可以帮助我们:

@Resource
private TimerService timerService;

在应用程序启动时,EJB容器将注入一个TimerService实例,该实例允许我们与Timer服务进行交互。 例如,我们可以列出(甚至删除)为应用程序定义的所有调度程序。

在我们的例子中,Timer服务将用于创建新的调度程序,如下所示(第三步):

String minuteSchedule = "*/15";
String hourSchedule = "*";
ScheduleExpression schedule = new ScheduleExpression()
 .minute(minuteSchedule)
 .hour(hourSchedule);

javax.ejb.ScheduleExpression定义cron [参见链接4]时间表,例如@Schedule批注。

@ScheduleScheduleExpression之间非常重要的区别在于,第一个固定在构建时:要更改调度参数(例如,从每15分钟更改为每30分钟),我们需要更改类代码,然后再次构建和部署应用程序。

在后一种情况下(SchedulerExpression),可以在应用程序启动时定义和更改计划参数(在示例中变量minutesSchedule和hourSchedule上方)并进行更改,例如,从以下示例中读取minutesSchedule和hourSchedule:
属性文件或连接的DBMS。

TimerConfig timerConfig = new TimerConfig();
timerConfig.setInfo("ProgrammaticPersistentScheduler");
timerConfig.setPersistent(true);

javax.ejb.TimerConfig为我们提供了定义调度程序名称的选项(setInfo(String))以及是否为持久性名称(setPersistent(boolean))。

通过使用ScheduleExpression和TimerConfig实例,我们可以使用Timer服务创建调度程序(更精确地说是日历计时器)。

timerService.createCalendarTimer(schedule, timerConfig);

createCalendarTime()方法返回一个javax.ejb.Timer实例,该实例可用于查询计时器,例如下一个将来的事件何时发生甚至破坏。
调度程序。

最后一步是在类中定义一个方法,该方法将在每次调度事件时调用

@Timeout
public void doSomeThing() {..}

该方法应为public,并返回void。

我们已经启动并运行了调度程序。

结论

Java EE标准为我们提供了许多选择来定义计划程序,该计划程序以周期性和重复的方式运行我们的代码。 不需要其他项目依赖项。

链接

  1. 计时器服务API上的Oracle Java EE6教程
  2. IBM WebSphere 8.x使用EJB计时器服务为企业bean创建计时器
  3. GitHub上的文章项目
  4. Cron在Wikipedia上

翻译自: https://www.javacodegeeks.com/2016/10/java-ee-schedulers.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值