• 沒有找到結果。

定时器和日历

4 规则

4.4 定时器和日历

4.4.1 定时器

规则用基于 interval(间隔)和 cron 的定时器(timer),替代了被标注过时的 duration 属性。timer 属性的使用示例:

timer ( int: <initial delay> <repeat interval>? ) timer ( int: 30s )

timer ( int: 30s 5m )

timer ( cron: <cron expression> ) timer ( cron:* 0/15 * * * ? )

间隔定时器用 int 来定义,它遵循 java.util.Timer 对象的使用方法。具有延迟和重复执行 的选择。其中第一个参数表示启动之后延迟多长时间执行,第二个参数表示每隔多久执行一 次。

Cron 定时器用 cron 来定义,使用标准的 Unix cron 表达式。示例代码如下:

rule "Send SMS every 15 minutes"

timer (cron:* 0/15 * * * ?) 到模拟的效果,使用了 KieSession 的 fireUntilHalt 方法和 halt 方法。示例代码如下。

规则文件:

package com.rules import java.util.Date import java.util.List

import com.secbro.drools.testTimer.Server

global com.secbro.drools.testTimer.ResultEvent event

rule "timerTest"

timer (cron:0/1 * * * * ?) when

server : Server(times > 10) then

System.out.println("已经尝试"+server.getTimes()+"次,超过预警次数!");

event.getEvents().add(new java.util.Date() + " - 服务器已经尝试" + server.getTimes()

public class Server { // 尝试次数 private int times;

Server(int times) { this.times = times;

}

//省略 getter/setter 方法 }

返回结果 ResultEvent 类:

package com.secbro.drools.testTimer;

import java.util.ArrayList;

import java.util.List;

/**

* Created by zhuzs on 2017/7/21.

*/

public class ResultEvent {

private List<String> events = new ArrayList<>();

//省略 getter/setter 方法 }

测试类:

package com.secbro.drools.testTimer;

import org.junit.Test;

import org.kie.api.KieServices;

import org.kie.api.runtime.KieContainer;

import org.kie.api.runtime.KieSession;

import org.kie.api.runtime.rule.FactHandle;

/**

* Created by zhuzs on 2017/7/21.

*/

public class TimerRulesTest {

@Test

public void timerTest() throws InterruptedException {

final KieSession kieSession = createKnowledgeSession();

ResultEvent event = new ResultEvent();

kieSession.setGlobal("event", event);

final Server server = new Server(1);

new Thread(new Runnable() { public void run() {

kieSession.fireUntilHalt();

} }).start();

FactHandle serverHandle = kieSession.insert(server);

private KieSession createKnowledgeSession() {

KieServices kieServices = KieServices.Factory.get();

<?xml version="1.0" encoding="UTF-8"?>

<kmodule xmlns="http://www.drools.org/xsd/kmodule">

<kbase name="rules" packages="com.rules">

<ksession name="ksession-rule"/>

21:04:17 CST 2017 - 服务器已经尝试 15 次,依旧失败,特发次报警信息!]

很显然,定时器每隔一秒执行一次,当满足规则触发条件时,将结果放入 ResultEvent 中。

4.4.2 日历

日历可以单独应用于规则中,也可以和 timer 结合使用在规则中使用。通过属性 calendars 来定义日历。如果是多个日历,则不同日历之间用逗号进行分割。

在 Drools 中,日历的概念只是将日历属性所选择的时间映射成布尔值,设置为规则的属 性,控制规则的触发。Drools 可以通过计算当期日期和时间来决定是否允许规则的触发。

此示例首先需要引入 quarts 框架:

<dependency>

<groupId>org.opensymphony.quartz</groupId>

<artifactId>quartz</artifactId>

<version>1.6.1</version>

</dependency>

实现 Quarts 的 Calendar 转换为 Drools 的 Calendar 的转换器 CalendarWrapper:

public class CalendarWrapper implements Calendar{

private WeeklyCalendar cal;

public CalendarWrapper(WeeklyCalendar cal) { this.cal = cal;

}

@Override

public boolean isTimeIncluded(long timestamp) { return cal.isTimeIncluded(timestamp);

}

public WeeklyCalendar getCal() { return cal;

}

public void setCal(WeeklyCalendar cal) { this.cal = cal;

}

}

规则文件:

package com.rules

rule "calenderTest"

calendars "weekday"

// timer (int:0 1s) // 可以和 timer 配合使用

when

str : String();

then

System.out.println("In rule - " + drools.getRule().getName());

System.out.println("String matched " + str);

end 测试方法:

@Test

public void timerTest() throws InterruptedException {

final KieSession kieSession = createKnowledgeSession();

WeeklyCalendar weekDayCal = new WeeklyCalendar();

// 默认包含所有的日期都生效

weekDayCal.setDaysExcluded(new boolean[]{false, false, false, false, false, false, false,false,false});

// weekDayCal.setDayExcluded(java.util.Calendar.THURSDAY, true); // 设 置 为 true 则不包含此天,周四

Calendar calendar = new CalendarWrapper(weekDayCal);

kieSession.getCalendars().set("weekday", calendar);

kieSession.insert(new String("Hello"));

kieSession.fireAllRules();

kieSession.dispose();

System.out.println("Bye");

}

protected KieSession createKnowledgeSession() {

KieServices kieServices = KieServices.Factory.get();

KieSessionConfiguration conf = kieServices.newKieSessionConfiguration();

KieContainer kieContainer = kieServices.getKieClasspathContainer();

KieSession kSession = kieContainer.newKieSession("ksession-rule", conf);

return kSession;

}

执行测试方法打印结果:

In rule - calenderTest

String matched Hello Bye

其中测试过程中的注意点已经在代码中进行标注,比如 Calendar 可以和 timer 共同使用;

如何设置 WeeklyCalendar 中哪一天执行,哪一天不执行。

相關文件