几个月前,我们开始重新设计Drools最低级别的可执行模型 ,并使最终用户可以使用Java 8 API进行访问。 为了证明这种方法的灵活性,我尝试将其与反应流集成在一起,尤其是将该流用作Drools的数据源。
为了说明这是如何工作的,我创建了一个简单的温度服务器,该服务器提供RxJava Observable , 每秒发射给定镇的温度,并在5秒钟后终止。 还有第二种工厂方法,该方法允许合并更多的这些Observable,以使一个Observable可以同时发射一个以上城镇的温度。
public class TempServer {
public static Observable<TempInfo> getFeed(String town) {
return Observable.create(subscriber ->
Observable.interval(1, TimeUnit.SECONDS)
.subscribe(i -> {
if (i > 5) subscriber.onCompleted();
try {
subscriber.onNext(TempInfo.fetch(town));
} catch (Exception e) {
subscriber.onError(e);
}
}));
}
public static Observable<TempInfo> getFeeds(String... towns) {
return Observable.merge(Arrays.stream(towns)
.map(TempServer::getFeed)
.collect(toList()));
}
}
其中TempInfo.fetch方法仅返回-20至50度之间的随机温度
public TempInfo(String town, int temp) {
this.town = town;
this.temp = temp;
}
public static TempInfo fetch(String town) {
return new TempInfo(town, random.nextInt(70) - 20);
}
使用前一篇文章中介绍的Java 8 DSL的改进版本,我定义了以下2条规则:
Variable<TempInfo> temp = any( TempInfo.class );
Variable<Person> person = any( Person.class );
Rule r1 = rule("low temp")
.view(
subscribe(temp, "tempFeed"),
expr(temp, t -> t.getTemp() < 0),
input(person, "persons"),
expr(person, temp, (p, t) -> p.getTown().equals(t.getTown()))
)
.then(on(person, temp)
.execute((p, t) -> System.out.println(p.getName() + " is freezing in " + p.getTown() + " - temp is " + t.getTemp())));
Rule r2 = rule("high temp")
.view(
subscribe(temp, "tempFeed"),
expr(temp, t -> t.getTemp() > 30),
input(person, "persons"),
expr(person, temp, (p, t) -> p.getTown().equals(t.getTown()))
)
.then(on(person, temp)
.execute((p, t) -> System.out.println(p.getName() + " is sweating in " + p.getTown() + " - temp is " + t.getTemp())));
在这里,我使用2种不同的数据源:一个被动的数据源,可以将其视为事实的存储:
DataStore persons = storeOf(new Person("Mark", 37, "London"),
new Person("Edson", 35, "Toronto"),
new Person("Mario", 40, "Milano"));
可以绑定到特定的Drools KieSession与
bindDataSource(ksession, "persons", persons);
以及从上面实现的TempServer中获取的一个响应式
Observable<TempInfo> tempFeed = TempServer.getFeeds( "Milano", "London", "Toronto" );
也可以以类似的方式绑定到相同的KieSession
bindRxObservable( ksession, "tempFeed", tempFeed );
完成此操作后,您可以触发这两个规则并获得如下输出:
Mark is freezing in London - temp is -9
Edson is sweating in Toronto - temp is 42
Mario is sweating in Milano - temp is 42
Mario is sweating in Milano - temp is 49
Mark is freezing in London - temp is -17
Edson is sweating in Toronto - temp is 40
Edson is sweating in Toronto - temp is 47
Mario is freezing in Milano - temp is -14
Mark is freezing in London - temp is -8
Mark is freezing in London - temp is -17
- 可在此处找到运行此示例的完整测试用例。
翻译自: https://www.javacodegeeks.com/2015/11/using-a-rective-stream-as-a-data-source-for-drools.html