5

Drools文档提到规则可以使用属性,如date-effectivedate-expires来指定绝对规则有效期。

例如

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 还支持使用间隔 astimer(int:)和 cron as定期重复timer(cron:)的规则,但这意味着在这些点触发规则。

问题:

如果有任何选项如何指定具有时间限制的定期可用(未触发)规则,我很感兴趣。例如,让我们想象一些公司的营业时间 - 只能在正式工作期间进行操作,但不能在下班后进行。

我想要这样的东西,但这不是 Drools 的有效规则

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

是否可以将此类规则扩展为仅在周一至周五上午 8 点至下午 4 点有效?


解决方案(由 Esteban Aliverti 提供):

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

示例: 规则定义

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 );
4

3 回答 3

6

更好的方法是使用calendar而不是timer(cron:). 我设法按照以下步骤完成了与您正在寻找的类似的事情:

创建会话时,您必须创建和配置 Quartz 日历:

//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

希望能帮助到你,

于 2013-02-12T11:16:51.250 回答
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,从而使这种方法更加灵活。

当然,如果你只有几个这样的定时条件,比如“办公时间”,那么使用的解决方案calendars是更可取的。

于 2013-02-13T12:53:20.013 回答
0

根据文档,您可以使用 cron 表达式作为计时器。所以,你可能会使用这样的东西:

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

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

希望能帮助到你,

于 2013-02-12T09:29:20.473 回答