Drools入門(mén)(三)——規(guī)則文件語(yǔ)法

引用

http://www.itdecent.cn/p/ae9a62588da4

擴(kuò)充

多規(guī)則文件執(zhí)行

多個(gè)drl文件只要package相同則表示它們用的是同一個(gè)KieBaseModel,此時(shí)獲取該KieBaseModel下的KieSession調(diào)用執(zhí)行規(guī)則引擎時(shí)會(huì)批量!!執(zhí)行該KieBaseModel下的所有規(guī)則

注意:對(duì)于規(guī)則引擎來(lái)說(shuō)不管是同一份文件里面寫(xiě)多個(gè)規(guī)則還是分開(kāi)多個(gè)文件寫(xiě)多個(gè)規(guī)則,最終都是以package作為批量執(zhí)行單位

規(guī)則腳本解析過(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é)果存放起來(lái)
                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.confMETA-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,首選語(yǔ)言是javadrl文件會(huì)被分為兩部分,一部分是LHS一部分是RHSLHS將被解析成一段一段的代碼片段,RHS會(huì)被解析成java代碼并編譯成class類(lèi)作為符合條件時(shí)的執(zhí)行結(jié)果

從上面我們大概了解了規(guī)則是如何被加載存放,以及是使用什么編譯工具去編譯drlRHS部分的,那么這里我們?cè)谏钊胍稽c(diǎn),整一份drl文本文件是如何去解析并拆分的呢?接下來(lái)將對(duì)這部分進(jìn)行解答,也算是一種拓展吧

回到最初規(guī)則引擎加載的過(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)建過(guò)程發(fā)現(xiàn)他創(chuàng)建了ANTLRStringStream,至此找到了最終的答案,drl文件的解析工作使用了第三方工具ANTLR去做的,源碼如下

public static DRLLexer buildLexer(String text, LanguageLevelOption languageLevel) {
    return getDRLLexer(new ANTLRStringStream(text), languageLevel);
}

此時(shí)查看引入的依賴(lài)包可以發(fā)現(xiàn)antlr的相關(guān)依賴(lài)jar包

antlr依賴(lài)

drl文件引入的antlr格式定義文件路徑為src/main/resources/org/drools/compiler/lang/DRL6Lexer.g,由于文件太長(zhǎng),此處就不貼出來(lái)了,想看的可以直接在項(xiàng)目中搜索該文件

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

友情鏈接更多精彩內(nèi)容