引用
https://www.jianshu.com/p/ae9a62588da4
扩充
多规则文件执行
多个drl
文件只要package
相同则表示它们用的是同一个KieBaseModel
,此时获取该KieBaseModel
下的KieSession
调用执行规则引擎时会批量!!
执行该KieBaseModel
下的所有规则
注意:对于规则引擎来说不管是同一份文件里面写多个规则还是分开多个文件写多个规则,最终都是以
package
作为批量执行单位
规则脚本解析过程
//创建整体规则引擎建造者
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
...
//创建规则项目
KieModuleKieProject kProject = kprojectSupplier.apply( memoryKieModule, classLoader );
buildKieProject( results, kProject, trgMfs );
...
//创建规则builder
KnowledgeBuilderImpl kbuilder = ( KnowledgeBuilderImpl ) createKnowledgeBuilder( kBaseModel, kModule );
//将规则文件分配并加载到对应的packageDescr里面,并调用builder解析每个package和及其里面的所有规则
kBuilder.buildPackages(buildPackageDescr());
//根据packageDescr创建packageRegisty作为最后存储规则的地方
PackageRegistry pkgRegistry = getPackageRegistry(packageDescr.getNamespace());
//对包里面的每条规则进行解析
private void compileRulesLevel(PackageDescr packageDescr, PackageRegistry pkgRegistry, List rules) {
boolean parallelRulesBuild = this.kBase == null && parallelRulesBuildThreshold != -1 && rules.size() > parallelRulesBuildThreshold;
if (parallelRulesBuild) {
.....
.....
} else {
for (RuleDescr ruleDescr : rules) {
if (filterAccepts(ResourceChange.Type.RULE, ruleDescr.getNamespace(), ruleDescr.getName())) {
//初始化规则
initRuleDescr(packageDescr, pkgRegistry, ruleDescr);
//创建规则上下文
RuleBuildContext context = buildRuleBuilderContext(pkgRegistry, ruleDescr);
//将规则解析结果存放起来
this.results.addAll(addRule(context));
//将解析后的规则存放到packageRegistry中
pkgRegistry.getPackage().addRule(context.getRule());
}
}
}
}
当运行到上面第10行时,在“创建规则builder”的时候会去加载规则引擎默认的配置文件META-INF/kie.properties.conf
和META-INF/kie.default.properties.conf
,规则引擎中只存在META-INF/kie.default.properties.conf
,非默认配置文件是留给使用者的,如果打算修改里面的配置属性可以在自己项目中创建一份META-INF/kie.properties.conf
,默认配置文件内容如下
drools.maintainTms = true
drools.shadowproxy = true
drools.shadowproxy.exclude =
drools.sequential = false
drools.sequential.agenda = sequential
drools.removeIdentities = false
drools.shareAlphaNodes = true
drools.shareBetaNodes = true
drools.alphaMemory = false
drools.alphaNodeHashingThreshold = 3
drools.compositeKeyDepth = 3
drools.indexLeftBetaMemory = true
drools.indexRightBetaMemory = true
drools.equalityBehavior = IDENTITY
drools.logicalOverride = DISCARD
drools.conflictResolver = org.drools.core.conflict.DepthConflictResolver
drools.consequenceExceptionHandler = org.drools.core.runtime.rule.impl.DefaultConsequenceExceptionHandler
drools.workDefinitions = WorkDefinitions.conf
droools.lrUnlinkingEnabled = false
drools.declarativeAgendaEnabled = false
drools.permgenThreshold = 90
#默认规则引擎解析器
drools.dialect.default = java
drools.dialect.java = org.drools.compiler.rule.builder.dialect.java.JavaDialectConfiguration
drools.dialect.java.compiler = ECLIPSE
drools.dialect.mvel = org.drools.compiler.rule.builder.dialect.mvel.MVELDialectConfiguration
drools.dialect.mvel.strict = true
drools.dialect.mvel.langLevel = 4
#内联函数
drools.accumulate.function.max = org.drools.core.base.accumulators.MaxAccumulateFunction
drools.accumulate.function.maxN = org.drools.core.base.accumulators.NumericMaxAccumulateFunction
drools.accumulate.function.maxI = org.drools.core.base.accumulators.IntegerMaxAccumulateFunction
drools.accumulate.function.maxL = org.drools.core.base.accumulators.LongMaxAccumulateFunction
drools.accumulate.function.min = org.drools.core.base.accumulators.MinAccumulateFunction
drools.accumulate.function.minN = org.drools.core.base.accumulators.NumericMinAccumulateFunction
drools.accumulate.function.minI = org.drools.core.base.accumulators.IntegerMinAccumulateFunction
drools.accumulate.function.minL = org.drools.core.base.accumulators.LongMinAccumulateFunction
drools.accumulate.function.count = org.drools.core.base.accumulators.CountAccumulateFunction
drools.accumulate.function.collectList = org.drools.core.base.accumulators.CollectListAccumulateFunction
drools.accumulate.function.collectSet = org.drools.core.base.accumulators.CollectSetAccumulateFunction
drools.accumulate.function.average = org.drools.core.base.accumulators.AverageAccumulateFunction
drools.accumulate.function.averageBD = org.drools.core.base.accumulators.BigDecimalAverageAccumulateFunction
drools.accumulate.function.sum = org.drools.core.base.accumulators.SumAccumulateFunction
drools.accumulate.function.sumI = org.drools.core.base.accumulators.IntegerSumAccumulateFunction
drools.accumulate.function.sumL = org.drools.core.base.accumulators.LongSumAccumulateFunction
drools.accumulate.function.sumBI = org.drools.core.base.accumulators.BigIntegerSumAccumulateFunction
drools.accumulate.function.sumBD = org.drools.core.base.accumulators.BigDecimalSumAccumulateFunction
drools.accumulate.function.variance = org.drools.core.base.accumulators.VarianceAccumulateFunction
drools.accumulate.function.standardDeviation = org.drools.core.base.accumulators.StandardDeviationAccumulateFunction
drools.evaluator.coincides = org.drools.core.base.evaluators.CoincidesEvaluatorDefinition
drools.evaluator.before = org.drools.core.base.evaluators.BeforeEvaluatorDefinition
drools.evaluator.after = org.drools.core.base.evaluators.AfterEvaluatorDefinition
drools.evaluator.meets = org.drools.core.base.evaluators.MeetsEvaluatorDefinition
drools.evaluator.metby = org.drools.core.base.evaluators.MetByEvaluatorDefinition
drools.evaluator.overlaps = org.drools.core.base.evaluators.OverlapsEvaluatorDefinition
drools.evaluator.overlappedby = org.drools.core.base.evaluators.OverlappedByEvaluatorDefinition
drools.evaluator.during = org.drools.core.base.evaluators.DuringEvaluatorDefinition
drools.evaluator.includes = org.drools.core.base.evaluators.IncludesEvaluatorDefinition
drools.evaluator.starts = org.drools.core.base.evaluators.StartsEvaluatorDefinition
drools.evaluator.startedby = org.drools.core.base.evaluators.StartedByEvaluatorDefinition
drools.evaluator.finishes = org.drools.core.base.evaluators.FinishesEvaluatorDefinition
drools.evaluator.finishedby = org.drools.core.base.evaluators.FinishedByEvaluatorDefinition
drools.evaluator.set = org.drools.core.base.evaluators.SetEvaluatorsDefinition
drools.evaluator.matches = org.drools.core.base.evaluators.MatchesEvaluatorsDefinition
drools.evaluator.soundslike = org.drools.core.base.evaluators.SoundslikeEvaluatorsDefinition
源码在ChainedProperties.class
的构造函数中
private ChainedProperties(String confFileName, ClassLoader classLoader) {
addProperties( System.getProperties() );
loadProperties( "META-INF/kie." + confFileName, classLoader, this.props );
loadProperties( "META-INF/kie.default." + confFileName, classLoader, this.defaultProps);
// this happens only in OSGi: for some reason doing
// ClassLoader.getResources() doesn't work but doing
// Class.getResourse() does
if (this.defaultProps.isEmpty()) {
try {
Class> c = Class.forName( "org.drools.core.WorkingMemory", false, classLoader);
URL confURL = c.getResource("/META-INF/kie.default." + confFileName);
loadProperties(confURL, this.defaultProps);
} catch (ClassNotFoundException e) { }
}
}
配置文件中值得注意的地方是默认的编译器是Eclipse
,首选语言是java
,drl
文件会被分为两部分,一部分是LHS
一部分是RHS
,LHS
将被解析成一段一段的代码片段,RHS
会被解析成java代码并编译成class
类作为符合条件时的执行结果
从上面我们大概了解了规则是如何被加载存放,以及是使用什么编译工具去编译
drl
的RHS
部分的,那么这里我们在深入一点,整一份drl
文本文件是如何去解析并拆分的呢?接下来将对这部分进行解答,也算是一种拓展吧
回到最初规则引擎加载的过程中,在调用buildPackageDescr()
创建规则包时就进行了解析,可以看到是在这一步进行的解析拆解,源码如下
PackageDescr drlToPackageDescr(Resource resource) throws DroolsParserException,
IOException {
PackageDescr pkg;
boolean hasErrors = false;
if (resource instanceof DescrResource) {
pkg = (PackageDescr) ((DescrResource) resource).getDescr();
} else {
final DrlParser parser = new DrlParser(configuration.getLanguageLevel());
pkg = parser.parse(resource);
this.results.addAll(parser.getErrors());
if (pkg == null) {
addBuilderResult(new ParserError(resource, "Parser returned a null Package", 0, 0));
}
hasErrors = parser.hasErrors();
}
if (pkg != null) {
pkg.setResource(resource);
}
return hasErrors ? null : pkg;
}
继续深入源码可以看到DrlParser
在调用paser(resource)
时创建了DRLLexer
,继续查看DRLLexer
创建过程发现他创建了ANTLRStringStream
,至此找到了最终的答案,drl
文件的解析工作使用了第三方工具ANTLR
去做的,源码如下
public static DRLLexer buildLexer(String text, LanguageLevelOption languageLevel) {
return getDRLLexer(new ANTLRStringStream(text), languageLevel);
}
此时查看引入的依赖包可以发现antlr
的相关依赖jar包
drl
文件引入的antlr
格式定义文件路径为src/main/resources/org/drools/compiler/lang/DRL6Lexer.g
,由于文件太长,此处就不贴出来了,想看的可以直接在项目中搜索该文件