2013-02-11 490 views
5

Drools documentation提到规则可以使用像date-effectivedate-expires这样的属性来指定绝对规则有效期。Drools:时间限制规则

例如

rule "Date-restricted rule" 
    date-effective "20.2.2013 8:00"  # 8 AM 
    date-expires "20.2.2013 16:00"  # 4 PM 
    when 
    then 
end 

Drools的也支持与间隔为timer(int:)和cron为timer(cron:)周期性地重复规则,但它意味着,该规则被在这样的点烧制。

问:

我感兴趣,如果有任何选项如何指定可定期(不启动)与时间限制规则。例如,让我们将某个公司的营业时间形象化 - 只能在正式工作期间执行操作,而不能在下班后执行操作。

,我想这样的事情,但它不是Drools的有效规则

rule "Time-restricted rule" 
    time-effective "8:00"  # 8 AM 
    time-expires "16:00"  # 4 PM 
    when 
    then 
end 

将有可能这样的规则是活跃,只有周一至周五上午8点延长到下午4点?


溶液(埃斯特班Aliverti):

的Drools不具备基于时间的关键词的直接支持,但他们提供使用Quartz库更加强大的日历机构。由StatelessSession创建的StatefulSessionWorkingMemory定义了这些日历的方法,这些日历可以限制可以触发规则的日期和时间。

例子: 规则定义

rule "Business hours only" 
    calendars "business-hours" 
    when 
     SomeAttachedClass() 
    then 
     System.out.println("Rule is fired"); 
end 

日历定义

import org.quartz.impl.calendar.DailyCalendar; 

// stateless session and working memory or directly stateful session 
StatefulKnowledgeSession memory = session.newWorkingMemory(); 
// interested time range is 8-16, also there is many Calendar implementation, not just Daily 
DailyCalendar businessHours = new DailyCalendar(8, 0, 0, 0, 16, 0, 0, 0); 
// by default, defined time is EXCLUDED, the inversion makes it INCLUDED and excludes the rest 
businessHours.setInvertTimeRange(true); 
//convert the calendar into a org.drools.time.Calendar 
org.drools.time.Calendar businessHoursCalendar = QuartzHelper.quartzCalendarAdapter(businessHours); 
//Register the calendar in the session with a name. You must use this name in your rules. 
memory.getCalendars().set("business-hours", businessHoursCalendar); 

回答

6

一个更好的办法是使用calendar而不是timer(cron:)。我设法做同样的事情你在找什么下列步骤:

当你创建你必须创建和配置一个石英日历会话:

//in this case I'm using a DailyCalendar but you can use whatever implementation of Calendar you want 
org.quartz.impl.calendar.DailyCalendar businessHours = new org.quartz.impl.calendar.DailyCalendar("business-hours", 8, 0, 0, 0, 16, 0, 0, 0); 
businessHours.setInvertTimeRange(true); 

//convert the calendar into a org.drools.time.Calendar 
org.drools.time.Calendar businessHoursCalendar = QuartzHelper.quartzCalendarAdapter(businessHours); 

//Register the calendar in the session with a name. You must use this name in your rules. 
ksession.getCalendars().set("business-hours", businessHoursCalendar); 

然后在你的规则,你必须写是这样的:

rule "Rule X" 
    calendars "business-hours" 
when 
    ... 
then 
    ... 
end 

希望它能帮助,

+0

来报告的。令人惊讶的是,这正是我所需要的。非常感谢你的努力! – Gaim 2013-02-13 12:10:39

+0

'QuartzHelper'类在新版本的Drools中不可用;如果你仍然想使用它,你可以从[这里]手动下载(http://grepcode.com/file/repository.jboss.org/nexus/content/repositories/releases/org.drools/drools-api/ 5.1.1 /组织/滴料/运行/帮助/ QuartzHelper.java /)。另外,'org.drools.time.Calendar'已经在更新版本的Drools中变成'org.kie.api.time.Calendar'。 – 2016-10-03 06:57:41

0

根据文档,你可以使用cron表达式作为定时器。那么,你很可能是这样的:

timer(cron: * 8-16 * * 1-5 *) 

免责声明:我没有测试这个!

希望它能帮助,

+0

谢谢您的回答,但根据文档和示例'我4.29'猜测,这将触发规则,这不是我想要的。我想在这段时间里,这条规则是积极的,不一定是解雇的, – Gaim 2013-02-12 09:44:06

+0

你试过了吗?我的意思是,规则只有在满足所有条件时才会触发,唯一可以防止使用定时器的是执行。您无法强制执行规则。 – 2013-02-12 09:49:10

+0

这是我认为它的工作原理:如果符合规则条件,并且您处于有效时间(根据cron表达式),并且您调用fireAllRules(),则您的规则将被执行。如果这些条件中的任何一个不成立,则该规则不会被执行。如果你可以尝试一下,这将是一件好事,所以我们可以确定这种行为。 – 2013-02-12 09:51:29

1

这里是另一种解决方案。也许一个黑客位,但它的工作原理:

您可以创建一个简单的Java类封装当前的时间和这个类的一个实例添加到工作记忆。这个类,称之为TimeFact,有一个像update(long time): voidgetDay(): StringgetTime(): String方法。这个事实然后可以在规则的when部分使用,就像这样:

rule "Foo" 
when 
    TimeFact(day in ("Monday", "Thursday"), time > "16:00:00" && < "17:00:00") 
    [more conditions] 
then 
    [do stuff] 
end 

您将需要更新TimeFact(并通知该更新的规则引擎)射击您的规则之前。不过,它的优势在于规则激活时间可以在规则本身中描述,而不必定义可能的大量数量,从而使这种方法更加灵活。

当然,如果你只有几个这样的定时条件,如“办公时间”,然后使用calendars该解决方案是优选的。