Java World似乎总会出现一些接口规范,这样做的好处是可以面向接口编程,可以在实现了该接口的产品/组件之间自由切换,避免被厂商绑架。 本文要介绍的JSR94:Java Rule Engine API ,Java规则引擎API规范。
概述 JSR-94是JCP(Java Community Process)制定的关于Java规则引擎API的规范,包括接口定义和示例代码。于2004年8月发布。 JSR-94定义了javax.rules和javax.rules.admin,前者包含了Java规则引擎运行时(Rumtime)API及异常(Exception)定义,后者包含了规则管理相关的API和异常定义。
规则管理API 规则管理API在javax.rules.admin中定义,主要包括以下类/接口:
Rule:规则实体
RuleExecutionSet:执行集,某个规则对应的动作
LocalRuleExecutionSetProvider:用于从本地创建执行集,如InputStream,Reader等
RuleExectuionSetProvider:用于从本地或远程创建执行集,如xml Element,Serializable等
RuleAdministrator:用于获取ExecutionSetProvider,并管理执行集的注册/注销
规则管理API实现的功能包括:
装载规则(Rule)和执行集(RuleExecutionSet)
执行集的注册/注销,只有注册的执行集对应的规则才能被客户访问
运行时API 运行时API在javax.rules中定义,主要包括以下类/接口:
RuleServiceProviderManager: 通过URL注册/注销RuleServiceProvider
RuleServiceProvider: 提供对RuleRuntime和RuleAdministrator的访问
RuleRuntime: 规则引擎运行时,可以创建规则会话
RuleSession: 规则会话,用于执行规则
RuleExecutionSetMetaData: 执行集元数据,包括name,url,description等。执行集元数据会被RuleSession使用
StatelessRuleSession: 无状态规则会话
StatefulRuleSession: 有状态规则会话
Handle和ObjectFilter: 有状态会话维护会话状态的帮助类
规则引擎运行时API实现的功能包括:
注册/注销规则引擎实例,只有注册的规则引擎实例才能被使用
从注册的规则引擎实例创建Runtime
从Runtime创建会话,包括有状态和无状态两种会话
通过会话执行规则
异常定义 除了前面提到的主要类/接口外,JSR94还规定了规则引擎运行时及管理的一些异常,如下:
代码示例 下面是使用Drools作为规则引擎实例的一个例子,规则文件使用了Drools的drl格式:
JSR94Sample.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 package com.sample;import java.io.FileReader;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import javax.rules.ConfigurationException;import javax.rules.RuleRuntime;import javax.rules.RuleServiceProvider;import javax.rules.RuleServiceProviderManager;import javax.rules.StatelessRuleSession;import javax.rules.admin.LocalRuleExecutionSetProvider;import javax.rules.admin.RuleAdministrator;import javax.rules.admin.RuleExecutionSet;import org.drools.jsr94.rules.RuleServiceProviderImpl;public class JSR94Sample { private static RuleServiceProvider ruleProvider; private static void initProvider () { String uri = RuleServiceProviderImpl.RULE_SERVICE_PROVIDER; Class providerClass = RuleServiceProviderImpl.class ; try { RuleServiceProviderManager.registerRuleServiceProvider(uri, providerClass); ruleProvider = RuleServiceProviderManager.getRuleServiceProvider(uri); }catch (ConfigurationException e){ e.printStackTrace(); } } private static void adminSample () { try { RuleAdministrator admin = ruleProvider.getRuleAdministrator(); HashMap properties = new HashMap(); properties.put("name" , "My Rules" ); properties.put("description" , "A trivial rulebase" ); LocalRuleExecutionSetProvider ruleExecutionSetProvider = admin.getLocalRuleExecutionSetProvider(properties); FileReader reader = new FileReader("bin/sample.drl" ); RuleExecutionSet reSet = ruleExecutionSetProvider.createRuleExecutionSet(reader, properties); admin.registerRuleExecutionSet("mysample" ,reSet,properties); }catch (Exception e){ e.printStackTrace(); } } private static void runtimeSampe () { try { RuleRuntime runtime = ruleProvider.getRuleRuntime(); StatelessRuleSession ruleSession = (StatelessRuleSession)runtime.createRuleSession("mysample" ,null ,RuleRuntime.STATELESS_SESSION_TYPE); Message message1 = new Message(); message1.setMessage("Hello World" ); message1.setStatus(Message.HELLO); Message message2 = new Message(); message2.setMessage("Goodbye World" ); message2.setStatus(Message.GOODBYE); List inputs = new ArrayList(); inputs.add(message1); inputs.add(message2); List<Message> results = ruleSession.executeRules(inputs); for (int i=0 ;i<results.size();i++){ Message msg = results.get(i); System.out.println(msg.message); } ruleSession.release(); }catch (Exception e){ e.printStackTrace(); } } public static void main (String[] args) { initProvider(); adminSample(); runtimeSampe(); } public static class Message { public static final int HELLO = 0 ; public static final int GOODBYE = 1 ; private String message; private int status; public String getMessage () { return this .message; } public void setMessage (String message) { this .message = message; } public int getStatus () { return this .status; } public void setStatus (int status) { this .status = status; } } }
规则文件使用的就是这里 的例子。
实现JSR94的产品 主要的一些实现了JSR94的规则引擎产品如下:
小结 JSR94为规则引擎提供了公用标准API,为实现规则管理API和运行时API提供了指导规范, 目前已经获得很多开源/商业规则引擎产品的支持。 但是JSR94没有对规则的描述语言 进行规范,导致各规则引擎产品大多采用自己私有的描述语言。