上面说到,目前在市场上留下多种规则引擎的产品,同样有多种的规则引擎语言,存在兼容性的问题。因此,我们必须提供一个统一的,标准的接口,来实现规则引擎的具体实现与业务应用系统之间的解耦,就像JDBC能够适应多种数据库一样,JSR 94也就顺势而生。当然,由于在语言级的标准路还很长,因此JSR 94只是在java中接口级别的标准。它的出现可以避免在更换实现产品时,必须重写应用程序逻辑和API调用的噩梦。JSR 94的官方网站为:http://jcp.org/en/procedures/jcp2
SR94 的规则引擎API介绍
我们先来看看包内主要的类,如图jsr94.bmp。
我们可以看到,包主要有javax.rules.admin和javax.rules两个目录,前一个目录,顾名思义,就是规则管理API(the rules administration API),后者是其他用途的API,我们称之为运行时API(the Runtime client API)。
规则管理API,我们从上图可以看到主要包括以下几个类:
RuleExecutionSetProvider类:
里面主要重载三个方法createRuleExecutionSet,从名称中可以看出,这个方法负责创建规则执行集。
LocalRuleExecutionSetProvider类:
与之对应的是 RuleExecutionSetProvider类,一个是远程的,一个是本地的(Local)。
规则执行集可以从如XML streams, input streams等来源中创建。在J2EE环境中,Java规则引擎的管理活动是应用服务器的一部分。因此一般规则库跟服务器不在同一台机器上,RuleExecutionSetProvider类可以从远程的经过汇集和系列化的数据来源中获取。
但一般情况而言,使用远程规则引擎或远程规则数据来源的情况并不多见,RuleExecutionSetProvider创建规则执行集会耗费较大的网络开销,所以一般使用的都是LocalRuleExecutionSetProvider类。
RuleAdministrator类:
四个方法:
- deregisterRuleExecutionSet(String, Map)
- registerRuleExecutionSet(String, RuleExecutionSet, Map)
- getRuleExecutionSetProvider(Map)
- getLocalRuleExecutionSetProvider(Map)
前面两个方法是注册执行集的,第一个参数是URI,作为唯一标识。后面两个是获取远程和本地的RuleExecutionSetProvider。
javax.rules.admin.Rule类
RuleExecutionSet类
这个类就是封装了规则执行集,实例由RuleExecutionSetProvider的createRuleExecutionSet方法创建。
运行时API中比较常用的类有:
RuleServiceProviderManager类:这个类负责注册RuleServiceProvider和获取注册的RuleServiceProvider。分别见方法registerRuleServiceProvider(String, Class)/registerRuleServiceProvider(String, Class, ClassLoader)和getRuleServiceProvider(String)
注册和获取的方法,第一个参数都是RuleServiceProvider的唯一标识。
RuleServiceProvider类:主要的两个方法getRuleAdministrator()和getRuleRuntime(),负责获取RuleRuntime和RuleRuntime的实例。
RuleRuntime类:提供一个createRuleSession(String, Map, int)方法创建rule执行会话。第一个参数就是上面注册RuleServiceProvider和RuleExecutionSet时候的uri,唯一标识。拥有一个唯一标识的RuleServiceProvider和RuleExecutionSet,可以创建多个rule session。第三个参数是一个整数,它用于标示创建有状态的还是无状态的session。
StatefulRuleSession类和StatelessRuleSession类,这两个类都继承了RuleSession类,规则执行会话主要维护规则的执行调用。无状态会话的工作方式就像一个无状态会话bean.客户可以发送单个输入对象或一列对象来获得输出对象.当客户需要一个与规则引擎间的专用会话时,有状态会话就很有用.输入的对象通过addObject() 方法可以加入到会话当中.同一个会话当中可以加入多个对象.对话中已有对象可以通过使用updateObject()方法得到更新.只要客户与规则引擎间的会话依然存在,会话中的对象就不会丢失。
RuleExecutionSetMetadata类:接口提供给客户让其查找规则执行集的元数据(metadata).元数据通过规则会话接口(RuleSession Interface)提供给用户。
总之,规则管理API主要提供装载规则以及与规则对应的动作(执行集 execution sets)以及实例化规则引擎以及对执行集进行维护。规则可以从外部资源中装载,比如说URI,Input streams, XML streams和readers等等。同时,规则引擎API提供了这样一个机制,就是访问RuleServiceProvider和RuleExecutionSet的实例,两者都必须先在服务器上注册,然后才能根据注册中使用的uri来获取。这样,有助于对客户访问运行规则进行控制管理,它通过在执行集上定义许可权使得未经授权的用户无法访问受控规则。而运行时API是提供了一个对规则执行集访问的机制,类似于JDBC的访问方法。类RuleServiceProvider提供了对具体规则引擎实现的运行时和管理API的访问,将其规则引擎实现提供给客户,并获得RuleServiceProvider唯一标识规则引擎的URI.
我们且看,一个规则实现的注册,然后到客户访问和执行规则的步骤。
第一步:先实例化ruleServiceProvider,这个ruleServiceProvider,就是提供具体的规则引擎实现,不同的规则引擎提供商有不同的provider。它的格式标准用法一般是例如:com.mycompany.myrulesengine.rules.RuleServiceProvider,我使用blaze,因此代码片断如下:
- Class ruleServiceProviderClass = Class.forName("com.blazesoft.server.deploy.javax.rules.base.NdRuleServiceProvider");
第二步:注册ruleServiceProvider。上面说到,使用RuleServiceProviderManager,如下:
- RuleServiceProviderManager.registerRuleServiceProvider(uri,ruleServiceProviderClass);
第三步:获取刚才注册的ruleServiceProvider实例(上面说过,要使用ruleServiceProvider的实例,必须先注册)
- RuleServiceProvider ruleServiceProvider = RuleServiceProviderManager.getRuleServiceProvider(uri);
第四步:获取RuleAdministrator的实例,因为注册和管理规则执行集,都是在RuleAdministrator中进行的。
- RuleAdministrator ruleAdministrator = ruleServiceProvider.getRuleAdministrator();
第五步:在Administrator实例中获取rule execution set provider
- HashMap properties = new HashMap();
- properties.put("name", "My Rules");
- properties.put("description", "A trivial rulebase");
- FileReader reader = new FileReader("rules.xml");
- RuleExecutionSetProvider ruleExecutionSetProvider ruleAdministrator.getRuleExecutionSetProvider(properties);
第六步:通过rule execution set provider的实例创建RuleExecutionSet
- RuleExecutionSet res = resp.createRuleExecutionSet(reader, properties);
第七步:注册RuleExecutionSet。
- admin.registerRuleExecutionSet(uri, ruleSet, properties);
下面是创建会话,然后执行规则集。
第八步:获取RuleRuntime 的实例,然后根据RuleRuntime 的实例创建执行会话。
- RuleRuntime runtime = rsp.getRuleRuntime();
- StatelessRuleSession session = (StatelessRuleSession)runtime.createRuleSession(uri, properties,RuleRuntime.STATELESS_SESSION_TYPE);
最后:执行规则集,释放会话资源。
- LinkedList list = new LinkedList();
- list.add(oneObject);
- list.add(anotherObject);
- session.executeRules();
- List results = session.getObjects();
- session.release();
SR94 的规则引擎API的使用实例(继续中...)