引用
擴(kuò)充
多規(guī)則文件執(zhí)行
多個(gè)drl
文件只要package
相同則表示它們用的是同一個(gè)KieBaseModel
慢逾,此時(shí)獲取該KieBaseModel
下的KieSession
調(diào)用執(zhí)行規(guī)則引擎時(shí)會(huì)批量!!
執(zhí)行該KieBaseModel
下的所有規(guī)則
注意:對(duì)于規(guī)則引擎來說不管是同一份文件里面寫多個(gè)規(guī)則還是分開多個(gè)文件寫多個(gè)規(guī)則携丁,最終都是以
package
作為批量執(zhí)行單位
規(guī)則腳本解析過程
//創(chuàng)建整體規(guī)則引擎建造者
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
...
//創(chuàng)建規(guī)則項(xiàng)目
KieModuleKieProject kProject = kprojectSupplier.apply( memoryKieModule, classLoader );
buildKieProject( results, kProject, trgMfs );
...
//創(chuàng)建規(guī)則builder
KnowledgeBuilderImpl kbuilder = ( KnowledgeBuilderImpl ) createKnowledgeBuilder( kBaseModel, kModule );
//將規(guī)則文件分配并加載到對(duì)應(yīng)的packageDescr里面沮协,并調(diào)用builder解析每個(gè)package和及其里面的所有規(guī)則
kBuilder.buildPackages(buildPackageDescr());
//根據(jù)packageDescr創(chuàng)建packageRegisty作為最后存儲(chǔ)規(guī)則的地方
PackageRegistry pkgRegistry = getPackageRegistry(packageDescr.getNamespace());
//對(duì)包里面的每條規(guī)則進(jìn)行解析
private void compileRulesLevel(PackageDescr packageDescr, PackageRegistry pkgRegistry, List<RuleDescr> 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())) {
//初始化規(guī)則
initRuleDescr(packageDescr, pkgRegistry, ruleDescr);
//創(chuàng)建規(guī)則上下文
RuleBuildContext context = buildRuleBuilderContext(pkgRegistry, ruleDescr);
//將規(guī)則解析結(jié)果存放起來
this.results.addAll(addRule(context));
//將解析后的規(guī)則存放到packageRegistry中
pkgRegistry.getPackage().addRule(context.getRule());
}
}
}
}
當(dāng)運(yùn)行到上面第10行時(shí)揖膜,在“創(chuàng)建規(guī)則builder”的時(shí)候會(huì)去加載規(guī)則引擎默認(rèn)的配置文件META-INF/kie.properties.conf
和META-INF/kie.default.properties.conf
绣夺,規(guī)則引擎中只存在META-INF/kie.default.properties.conf
授药,非默認(rèn)配置文件是留給使用者的荆秦,如果打算修改里面的配置屬性可以在自己項(xiàng)目中創(chuàng)建一份META-INF/kie.properties.conf
背捌,默認(rèn)配置文件內(nèi)容如下
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
#默認(rèn)規(guī)則引擎解析器
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
#內(nèi)聯(lián)函數(shù)
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
的構(gòu)造函數(shù)中
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) { }
}
}
配置文件中值得注意的地方是默認(rèn)的編譯器是Eclipse
戳粒,首選語言是java
路狮,drl
文件會(huì)被分為兩部分,一部分是LHS
一部分是RHS
蔚约,LHS
將被解析成一段一段的代碼片段奄妨,RHS
會(huì)被解析成java代碼并編譯成class
類作為符合條件時(shí)的執(zhí)行結(jié)果
從上面我們大概了解了規(guī)則是如何被加載存放,以及是使用什么編譯工具去編譯
drl
的RHS
部分的苹祟,那么這里我們?cè)谏钊胍稽c(diǎn)砸抛,整一份drl
文本文件是如何去解析并拆分的呢?接下來將對(duì)這部分進(jìn)行解答树枫,也算是一種拓展吧
回到最初規(guī)則引擎加載的過程中直焙,在調(diào)用buildPackageDescr()
創(chuàng)建規(guī)則包時(shí)就進(jìn)行了解析,可以看到是在這一步進(jìn)行的解析拆解砂轻,源碼如下
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;
}
繼續(xù)深入源碼可以看到DrlParser
在調(diào)用paser(resource)
時(shí)創(chuàng)建了DRLLexer
箕般,繼續(xù)查看DRLLexer
創(chuàng)建過程發(fā)現(xiàn)他創(chuàng)建了ANTLRStringStream
,至此找到了最終的答案舔清,drl
文件的解析工作使用了第三方工具ANTLR
去做的丝里,源碼如下
public static DRLLexer buildLexer(String text, LanguageLevelOption languageLevel) {
return getDRLLexer(new ANTLRStringStream(text), languageLevel);
}
此時(shí)查看引入的依賴包可以發(fā)現(xiàn)antlr
的相關(guān)依賴jar包
drl
文件引入的antlr
格式定義文件路徑為src/main/resources/org/drools/compiler/lang/DRL6Lexer.g
,由于文件太長(zhǎng)体谒,此處就不貼出來了杯聚,想看的可以直接在項(xiàng)目中搜索該文件