Drools入门(三)——规则文件语法

引用

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.confMETA-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,首选语言是javadrl文件会被分为两部分,一部分是LHS一部分是RHSLHS将被解析成一段一段的代码片段,RHS会被解析成java代码并编译成class类作为符合条件时的执行结果

从上面我们大概了解了规则是如何被加载存放,以及是使用什么编译工具去编译drlRHS部分的,那么这里我们在深入一点,整一份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包

antlr依赖

drl文件引入的antlr格式定义文件路径为src/main/resources/org/drools/compiler/lang/DRL6Lexer.g,由于文件太长,此处就不贴出来了,想看的可以直接在项目中搜索该文件

你可能感兴趣的:(Drools入门(三)——规则文件语法)