2011-09-20 54 views
2

我正在寻找一个lib,允许我做寻找持久性计时器的Spring应用程序

  1. 定义将一次在一个特定的时间在未来被调用的工人(不需要再像featrure时间表/ cron的),即一个定时器
  2. 工人应接受该枝条一些参数/输入
  3. 所有应在DB(或文件)中的工人
  4. 工人应该由弹簧进行管理持久性的上下文 - - spring应该实例化worker,以便可以使用dependen注入资本投资者入境计划
  5. 能够通过API动态创建定时器并不仅仅是静态通过Spring XML豆

不错的:

  1. 支持集群,即有多个节点可以承载一个工人。每家商店在中jobn数据库将引起一个工作invokaction在点头的一个

我已经研究几个备选方案都不符合要求:

  • 石英

时使用org.springframework.scheduling.quartz.JobDetailBean使石英创建您的工人实例(而不是春天),所以你不能得到依赖注射,(这将导致我使用服务定位器,我想避免)

while using org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean while you can not get a context。你的工人暴露使用MethodInvokingJobDetailFactoryBean中不能使用持久性时,不接受任何arguments.In另外一个公共方法(形成的Javadoc)

注:通过这个FactoryBean创建JobDetails不是序列,因此不适合持续工作商店。您需要将您自己的Quartz Job实现为每个需要持久作业委托给特定服务方法的情况的精简包装器。

  • Spring的计时器和简单的JDK计时器不支持的持久性/集群功能

我知道我可以使用DB和Spring(甚至JDK)定时器IMPL的事情我自己,但我更喜欢使用一个3r党的lib。

有什么建议吗?

回答

3

如果你要创建的工作细节,以产生触发/求职信息在运行时,仍然能够使用Spring DI上的豆你可以参考this blog post,它显示了如何与ObjectFactoryCreatingFactoryBean结合使用SpringBeanJobFactory使用Spring注入的bean在运行时创建Quartz触发对象。

+1

正是我需要的。谢谢 –

0

你的要求3和4对我来说并没有什么意义:你怎么能把整个包(工人+工作)序列化为它神奇地醒来并且完成它的工作?运行系统中的某些东西是否应该在适当的时候进行操作?难道这不就是工作人员吗?

我的方法是:创建一个Timer,Spring可以实例化并注入依赖项。然后这个定时器会从持久存储中加载它的工作/任务,安排它们执行并执行它们。你的课程可以是围绕java.util.Timer的包装,而不是处理调度内容。您必须自己实现与群集相关的逻辑,以便只有一个定时器/工作者可以执行该工作/任务。

+0

请注意,我需要每个工作只进行一次重复没有调用。每个工人不改变其状态(即jobDataMap)。从持久性POV我需要:存储作业定义(何时触发以及要做什么)以及在调度期间不会调用的jobDataMap –

+0

您的计时器“bean”与DB一起可以强制执行单个执行。 “获胜”计时器(即实际执行任务)被记录在数据库中,以防止其他计时器获得任务;成功的任务执行也被记录下来。其余的确实取决于你的需求:定时器是否应该为数据库查询新任务?新任务如何提交?当任务不按错误执行时应该发生什么?其他定时器是否应该接管?该任务应该立即执行还是以后执行? – vagelis

0

对于那些对石英替代品感兴趣的人,请看db-schedulerhttps://github.com/kagkarlsson/db-scheduler)。持久性任务/执行时间表保存在单个数据库表中。保证只能由群集中的调度程序执行一次。

  1. 是的,请参阅下面的代码示例。

  2. 目前仅限于单个字符串标识符,无格式限制。调度程序可能会在未来得到扩展,并为作业细节/参数提供更好的支持。

  3. 执行时间和上下文在数据库中是持久的。计划程序启动时,将任务名称绑定到工作人员。只要实现了接口,该工作人员就可以被Spring实例化。

  4. 参见3)。

  5. 是的,看下面的代码示例。

代码示例:

private static void springWorkerExample(DataSource dataSource, MySpringWorker mySpringWorker) { 

    // instantiate and start the scheduler somewhere in your application 
    final Scheduler scheduler = Scheduler 
      .create(dataSource) 
      .threads(2) 
      .build(); 
    scheduler.start(); 

    // define a task and a handler that named task, MySpringWorker implements the ExecutionHandler interface 
    final OneTimeTask oneTimeTask = ComposableTask.onetimeTask("my-onetime-task", mySpringWorker); 

    // schedule a future execution for the task with a custom id (currently the only form for context supported) 
    scheduler.scheduleForExecution(LocalDateTime.now().plusDays(1), oneTimeTask.instance("1001")); 
} 


public static class MySpringWorker implements ExecutionHandler { 
    public MySpringWorker() { 
     // could be instantiated by Spring 
    } 

    @Override 
    public void execute(TaskInstance taskInstance, ExecutionContext executionContext) { 
     // called when the execution-time is reached 
     System.out.println("Executed task with id="+taskInstance.getId()); 
    } 
} 
+0

请添加免责声明,您是作者。 – lexicore

相关问题