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<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())) {
                //初始化规则
                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,由于文件太长,此处就不贴出来了,想看的可以直接在项目中搜索该文件

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352