几个月前,我们开始重新设计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