zoukankan      html  css  js  c++  java
  • Drools 规则文件语法概述

    概述(Overview)

    以.drl为扩展名的文件,是Drools中的规则文件,规则文件的编写,遵循Drools规则语法。下面详细介绍一下Drools规则文件语法。具体参考官方文档: https://docs.jboss.org/drools/release/7.0.0.Final/drools-docs/html_single/index.html#_droolslanguagereferencechapter
    DRL文件的整体结构如下:

    package package-name
    

    imports

    globals

    functions

    queries

    rules

    对于上述元素,其顺序在drl文件中的顺序不重要,除了package-name,必须是drl文件的第一个元素。上述所有的元素都是可选的,接下来我们将详细介绍上述元素。

    规则(Rule)组成

    一个简单的规则结构如下所示:

    rule "name"
        attributes
        when
            LHS
        then
            RHS
    end
    

    通常,规则文件中是不需要标点符号的。即使是规则名“name”上的双引号也是可选的。attributes展示规则的执行方式,也是可选的。LHS是规则的条件部分,遵循一个固定的语法规则,在下面的内容会详细介绍。RHS通常是一个可以本地执行的代码块。

    关键字(Key Words)

    从Drools 5开始,提出了“软”关键字和“硬”关键字的概念。硬关键字是保留的,不允许开发人员在编写规则文件时使用。硬关键字有如下几个:

    • true
    • false
    • null

    软关键字是在文件内容中公认的一些字,开发人员可以在任何地方使用这些关键字,但是为了消除混淆,并不推荐开发人员在实际中使用这些关键字。软关键字有如下几个:

    • lock-on-active
    • date-effective
    • date-expires
    • no-loop
    • auto-focus
    • activation-group
    • agenda-group
    • ruleflow-group
    • entry-point
    • duration
    • package
    • import
    • dialect
    • salience
    • enabled
    • attributes
    • rule
    • extend
    • when
    • then
    • template
    • query
    • declare
    • function
    • global
    • eval
    • not
    • in
    • or
    • and
    • exists
    • forall
    • accumulate
    • collect
    • from
    • action
    • reverse
    • result
    • end
    • over
    • init

    注释(Comments)

    注释是规则文件中一段会被规则引擎自动忽略的一段文本。drl文件中的注释采用类Java语法的方式,可以分为两类:单行注释和多行注释。

    单行注释

    单行注释可以简单的使用双斜杠"//"来标识。语法解析器会自动忽视其后的所有内容。样例如下:

    rule "Testing Comments"
    when
        // this is a single line comment
        eval( true ) // this is a comment in the same line of a pattern
    then
        // this is a comment inside a semantic code block
    end
    

    另外需要注意的是,“#”开头的单行注释在drl文件中已经被弃用。

    多行注释

    多行注释主要用于在代码块外对整个文件进行注释,以"/"开头和"/"结尾的之间所有的内容都会被语法解析器解释为注释。样例如下:

    rule "Test Multi-line Comments"
    when
        /* this is a multi-line comment
           in the left hand side of a rule */
        eval( true )
    then
        /* and this is a multi-line comment
           in the right hand side of a rule */
    end
    

    错误信息(Error Messages)

    Drools 5 开始提出了标准的错误信息。标准化的目的是为了使开发者可以更准确更简单定位错误问题所在。接下来将介绍如正确理解和识别错误信息。

    错误信息格式

    标准的错误信息格式如下所示。


    ErrorMessageFormat.png

    错误信息包含以下几个部分:

    • 1st Block: 表明当前错误的错误码。
    • 2st Block: 错误可能发生的行和列。
    • 3st Block: 错误信息描述。
    • 4st Block: 指明错误发生的规则,函数,模板,查询等。
    • 5st Block: 指明错误发生于何种模式。一般不是强制性的。

    错误码描述

    • 101: No viable alternative
      错误码101指明了最常见的错误,语法解析器无法找到替代方案。下面有一些常见的例子:
    1: rule one
    2:   when
    3:     exists Foo()
    4:     exits Bar()  // "exits"
    5:   then
    6: end
    

    上述示例会产生如下错误信息:

    • [ERR 101] Line 4:4 no viable alternative at input 'exits' in rule one

    上述例子中的exits != exists, 解析器找不到exits的替代方案,于是报错。下面我们可以再看一个例子。

    1: package org.drools.examples;
    2: rule
    3:   when
    4:     Object()
    5:   then
    6:     System.out.println("A RHS");
    7: end
    

    现在,上述的代码会产生如下错误信息:

    • [ERR 101] Line 3:2 no viable alternative at input 'WHEN'

    这里when是一个关键字,语法解析器在这里会遇到一个问题:rule没有文件名,而when是一个规则的条件部分。因此报错。下面还有一个相同类型错误的示例:

    1: rule simple_rule
    2:   when
    3:     Student( name == "Andy )
    4:   then
    5: end
    

    这里双引号缺少了另一半,因此会报错。

    • 102: Mismatched input
      该错误表明,语法解析器在当前输入位置中未找到一个特定的符号。下面有一些例子:
    1: rule simple_rule
    2:   when
    3:     foo3 : Bar(
    

    上述示例会产生如下错误:

    • [ERR 102] Line 0:-1 mismatched input '<eof>' expecting ')' in rule simple_rule in pattern Bar

    要解决上述问题,需要完善上述规则语句。接下来的实例会产生多个错误:

    1: package org.drools.examples;
    2:
    3: rule "Avoid NPE on wrong syntax"
    4:   when
    5:     not( Cheese( ( type == "stilton", price == 10 ) || ( type == "brie", price == 15 ) ) from $cheeseList )
    6:   then
    7:     System.out.println("OK");
    8: end
    

    上述代码会产生如下错误:

    • [ERR 102] Line 5:36 mismatched input ',' expecting ')' in rule "Avoid NPE on wrong syntax" in pattern Cheese
    • [ERR 101] Line 5:57 no viable alternative at input 'type' in rule "Avoid NPE on wrong syntax
    
     该错误信息与前一个错误相关,这里只需要将```,``````&&```替换就好了。
    

    103: Failed predicate*
    出现该错误信息的原因是一个验证的语义谓词被验证为false。通常这些语义谓词用于识别软关键字。以下是一个示例:

    1: package nesting;
    2: dialect "mvel"
    3:
    4: import org.drools.compiler.Person
    5: import org.drools.compiler.Address
    6:
    7: fdsfdsfds
    8:
    9: rule "test something"
    10: when
    11: p: Person( name=="Michael" )
    12: then
    13: p.name = "other";
    14: System.out.println(p.name);
    15: end

    我们可以得到如下错误信息:
      * ```[ERR 103] Line 7:0 rule 'rule_key' failed predicate: {(validateIdentifierKey(DroolsSoftKeywords.RULE))}? in rule
    

    fdsfdsfds是个无效的关键字,语法解析器无法将其识别成一个软关键字。

    • 104: Trailing semi-colon not allowed
      该错误信息与eval从句相关,当分号不是出现在其表达式的结尾时可能报此错误。可以看一下如下示例。
    1: rule simple_rule
    2:   when
    3:     eval(abc();)
    4:   then
    5: end
    

    由于在eval中以分号结尾,我们可以得到如下错误信息:

    • [ERR 104] Line 3:4 trailing semi-colon not allowed in rule simple_rule

    该错误很容易修复,只要移除eval中的分号即可。

    • 105: Early Exit
      drl文件中的子规则至少能被匹配选择一次,但是当子规则不能匹配任何东西的时候,就会报这个错。
      以下是一个示例:
    1: template test_error
    2:   aa s  11;
    3: end
    

    该示例会报以下错误信息:

    • [ERR 105] Line 2:2 required (…​)+ loop did not match anything at input 'aa' in template test_error

    • Other Messages
      开发中可能还会遇到一些其他意想不到的问题,这些问题可以向Drools的开发团队求助。

    包(Package)

    package是一系列rule或其他相关构件如imports, globals的容器。这个成员之间相互关联,一个package代表了一个命名空间,其中的每个rule的名字都是唯一的,package名字本身就是命名空间,与实际的文件和文件夹没有任何关系。常见的结构是,一个文件包含多个rule的文件就定义成一个包。以下的线路图表明了一个包中包含的所有组成元素。

    package.png

       需要注意的是,一个包必须有一个命名空间,且其声明必须遵守Java命名规范。package语句必须出现在包的首行,其他组成部分的出现顺序无关紧要。其中package语句结尾的分号;是可选的。

    import

    Drools文件中的import语句功能与Java中的import语句功能类似。使用import时,必须指定对象的全称限定路径和类型名。Drools会自动导入Java相同名字的包中的所有类,也会导入java.lang.*

    global

    global.png

       global用于定义全局变量。用于使应用对象对一系列规则有效。通常,用于向规则提供全局的数据和服务,特别是一些用于规则序列的应用服务,如日志、规则序列中累加的值等。全局的变量是不会插入Woking Memory中的,另外,全局变量不要用于建立规则的条件部分,除非它是一个不会改变的常量。全部变量的改变不会通知到规则引擎,规则引擎不跟踪全局变量的变化,因为他们并没有加入到Woking Memory中。全局变量使用不当,会产生很多不可思议的结果。如果多个包中同时定义了相同标识符的全局变量,那么这些全局变量必须是相同类型,并会引用一个相同的全局值。为了更好地使用全局变量,必须遵循以下规则:

    1. 在规则文件中定义常量,并使用这些常量。
    global java.util.List myGlobalList;
    rule "Using a global"
    when
        eval( true )
    then
        myGlobalList.add( "Hello World" );
    end
    
    1. 在工作内存中,为全局变量设值。在从内存中获取所有的fact之前,最好将所有的全局变量设置。例如:
    List list = new ArrayList();
    KieSession kieSession = kiebase.newKieSession();
    kieSession.setGlobal( "myGlobalList", list );
    

    全局变量并不是用来在规则间共享数据,而且最好不要用于在规则间共享数据。规则总是对工作内存的状态产生推理和反应,因此,如果想在规则之间传递数据,可以将这些数据作为facts传入工作内存。因为规则引擎并不会关心和跟踪这些全局变量的变化。

    函数(Function)

    function.png

       function提供了一种在规则源文件中插入语义代码的方式,与在普通Java类中不同。他们需要帮助类,否则不能做任何事情。(实际上,编译器会针对这些句子自动产生帮助类。)在规则中使用函数的最主要优点就是你可以把所有逻辑放在一个地方,你可以根据需要更改这些函数的逻辑。函数通常用于在规则的then部分调用某些动作,特别是一些经常被用到的而传入参数不一样的动作。
    典型的function格式如下:

    function String hello(String name) {
        return "Hello "+name+"!";
    }
    

    需要注意的是,这里我们使用了function关键字,即使它并不是Java语言的一部分。参数和返回值的定义和传入与Java语言一致。当然,参数和返回值并不是必须的。另外,我们可以使用一个帮助类中的静态方法,如:Foo.hello()
      Drools支持函数的导入,我们所要做的就是:

    import function my.package.Foo.hello
    

    不需要考虑函数的定义和导入方式,我们可以直接在需要的地方直接使用函数名调用这个函数。例如:

    rule "using a static function"
    when
        eval( true )
    then
        System.out.println( hello( "Bob" ) );
    end
    

    类型声明(Type Declaration)

    在规则引擎中,类型声明有两个目的:允许新的类型声明;允许元数据类型的声明。

    • 声明新类型:Drools工作时会将外部的普通Java对象作为事实。但是有时候使用者想要自己定义一些规则引擎可以直接使用的模型,而不用担心用Java之类的底层语言来创建对象。另外有时候,当一个域模型已经建立,但是用户想或者需要用一些主要在推理过程中使用的实体来完善这个模型。
    • 声明元数据:事实往往会有一些与之相关的元数据信息。元信息的样本包含的任何种类的数据都不能代表事实的属性,且在该事实类型的所有实例中都是不变的。这些元信息在规则引擎的运行和推理古城中需要被查询。

    声明新类型

    为了定义新类型,我们需要使用关键字``declare,然后是一系列域,最终以end关键字结尾。一个新的fact必须有一系列域,否则规则引擎会去classpath中寻找一个存在的fact```类,如果没找到,会报错。下面给出定义新类型的几个例子。

    Example . Declaring a new fact type: Address

    declare Address
       number : int
       streetName : String
       city : String
    end
    

    上面的例子中我们定义了一个新类型Address,这个fact有三个属性,每个属性都具有一个Java中有效的数据类型。同样的,我们可以再定义一个数据类型:
    Example . Declaring a new fact type: Person

    declare Person
        name : String
        dateOfBirth : java.util.Date
        address : Address
    end
    

    我们可以看一下上面的例子,dateOfBirth是Java中的java.util.Date类型,address是我们刚才声明的类型。为了不用写全称限定名,我们可以先使用import来导入要使用的类型,例如:
    Avoiding the need to use fully qualified class names by using import

    import java.util.Date
    

    declare Person
    name : String
    dateOfBirth : Date
    address : Address
    end

    当我们声明一个新的fact类型时,Drools会在编译期间生成实现自一个表示该fact类型的Java类的字节码。这个生成的Java类

    Example : generated Java class for the previous Person fact typedeclaration

    public class Person implements Serializable {
        private String name;
        private java.util.Date dateOfBirth;
        private Address address;
    
    <span class="token comment">// empty constructor</span>
    <span class="token keyword">public</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">}</span>
    
    <span class="token comment">// constructor with all fields</span>
    <span class="token keyword">public</span> <span class="token class-name">Person</span><span class="token punctuation">(</span> <span class="token class-name">String</span> name<span class="token punctuation">,</span> <span class="token class-name">Date</span> dateOfBirth<span class="token punctuation">,</span> <span class="token class-name">Address</span> address <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">}</span>
    
    <span class="token comment">// if keys are defined, constructor with keys</span>
    <span class="token keyword">public</span> <span class="token class-name">Person</span><span class="token punctuation">(</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>keys<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">}</span>
    
    <span class="token comment">// getters and setters</span>
    <span class="token comment">// equals/hashCode</span>
    <span class="token comment">// toString</span>
    

    }

    该类型生成的class是一个普通的Java类,可以在规则中直接使用,就向其他 fact一样。见如下例子:
    Using the declared types in rules

    rule "Using a declared Type"
    when
        $p : Person( name == "Bob" )
    then
        // Insert Mark, who is Bob's mate.
        Person mark = new Person();
        mark.setName("Mark");
        insert( mark );
    end
    

    声明枚举类型

    DRL同时支持声明枚举类型。该类型声明需要另外一种关键字enum,然后以都好分割可接收值的列表,最后以分号结束。

    declare enum DaysOfWeek
       SUN("Sunday"),MON("Monday"),TUE("Tuesday"),WED("Wednesday"),THU("Thursday"),FRI("Friday"),SAT("Saturday");
    

    fullName : String
    end

    声明完成之后,该枚举类型可以用于之后的规则中。

    rule "Using a declared Enum"
    when
       $p : Employee( dayOff == DaysOfWeek.MONDAY )
    then
       ...
    end
    

    声明元数据

    在Drools中元数据会被分配给一系列不同对象的构造:fact类型,fact属性和规则。Drools使用@符号来引出元数据,使用使用如下格式:

    @metadata_key( metadata_value )
    

    其中metadata_value是可选的。
       Drools允许声明任何任意元数据属性,但是当其他属性在运行时仅仅对查询有效时,有些属性对于规则引擎来说具有不同的意义。Drools允许为fact类型和fact属性声明元数据。所有的元数据在该属性被分配到fact类型前声明,而在向一个特定属性分配值之前声明。
    Example 115. Declaring metadata attributes for fact types and attributes

    import java.util.Date
    

    declare Person
    @author( Bob )
    @dateOfCreation( 01-Feb-2009 )

    name <span class="token operator">:</span> String <span class="token label symbol">@key</span> <span class="token label symbol">@maxLength</span><span class="token punctuation">(</span> <span class="token number">30</span> <span class="token punctuation">)</span>
    dateOfBirth <span class="token operator">:</span> Date
    address <span class="token operator">:</span> Address
    

    end

    上面的例子中,声明了两个fact类型(@author@dateOfCreation)的元数据元素,另外为name属性声明了两个(@key@maxLength)元数据。其中@key没有必须值,所有括号和值均被省略了。

    规则(Rule)

    rule.png

       一个规则,指定当(when)一系列特定的条件发生时(左手边LHS),然后(then)做出一系列相应的动作(右手边RHS)。一个常见的问题就是:为什么使用when而不是if,因为if通常是执行流程中特定时间点的一部分,是一个需要检查的条件。相反的,when指明的是一个不绑定于任何特定判断序列或时间点的条件判断,它在规则引擎的声明周期内的任何一个条件发生的情况下都可能触发,不管这个条件是否遇到,这些动作都会执行。
       一个规则在一个包中必须具有独一无二的名字。如果在一个DRL文件中重复定义两个相同名字的规则,在加载的时候就会报错。如果向包中添加一个名字已经存在的规则,该规则会覆盖掉之前的同名规则。如果一个规则命中存在空格符,最好使用双引号将规则名包括起来。
       规则的属性不是必须的,且属性最好写成一行。
       规则中的LHS在关键字when的后面,同样的,RHS应该在关键字then的后面,规则最后以关键字end结尾。另外,规则不准嵌套。

    Example . Rule Syntax Overview

    rule "<name>"
        <attribute>*
    when
        <conditional element>*
    then
        <action>*
    end
    

    Example . A simple rule

    rule "Approve if not rejected"
      salience -100
      agenda-group "approval"
        when
            not Rejection()
            p : Policy(approved == false, policyState:status)
            exists Driver(age > 25)
            Process(status == policyState)
        then
            log("APPROVED: due to no objections.");
            p.setApproved(true);
    end
    
    rule attributes.png

    规则属性

    规则属性显式地声明了对规则行为的影响,有些规则属性很简单,有些规则属性是复杂的子系统的一部分,如规则流。为了从Drools中获得更多东西,我们需要确保对每一个规则属性均有正确的认识。
    常用的规则属性有如下:

    • no-loop

      • 默认值:false
      • type: Boolean
        当规则序列更改了一个fact,会导致该规则会被重新触发,以至于产生一个无限循环。当设置为true时,当前规则只会被激活一次。
    • ruleflow-group

      • 默认值:N/A
      • type: String
        ruleflow是Drools的特色之一,可以让你自己控制规则的命中。同一个ruleflow-group中的所有规则只有当该组激活时才能被命中。
    • lock-on-active

      • 默认值:false
      • type: Boolean
        不管何时ruleflow-groupagenda-group被激活,只要其中的所有规则将lock-on-active设置为true,那么这些规则都不会再被激活,不管一开始怎么更新,这些匹配的规则都不会被激活。这是no-loop属性的增强,因为这些变化现在不仅仅是规则自身的变化。
    • salience

      • 默认值:0
      • type: Integer
        任何规则都有一个默认为0的salience属性,该属性可以为0,正数和负数。salience表示规则的优先级,值越大其在激活队列中的优先级越高。Drools支持使用动态的salience,可以使用一个包含动态约束变量的表达式来表示。如下所示
        Dynamic Salience
    rule "Fire in rank order 1,2,.."
            salience( -$rank )
        when
            Element( $rank : rank,... )
        then
            ...
    end
    
    • agenda-group

      • 默认值:MAIN
      • type: String
        agenda-group允许用户将Agenda分割成多个部分以提供更多的运行控制。
    • auto-focus

      • 默认值:false
      • type: Boolean
        当一个规则被激活时auto-focus为true,而且该规则的agenda-group还没有focus,当该agenda-groupfocus时,允许该规则潜在命中。
    • activation-group

      • 默认值:N/A
      • type: String
        属于同一个activation-group的规则会进行唯一命中。也就是说同一个activation-group中的规则,只要有一个命中,其他的规则都会被取消激活状态,这样这些规则就不会被命中。
    • dialect

      • 默认值:as specified by the package
      • type: String
        dialect用于指明规则中使用的代码的语言种类,目前支持两种语言,"java"或"mvel"。
    • date-effective

      • 默认值:N/A
      • type: String (包含日期和时间)
        当前系统时间在date-effective之后,该规则才会被激活。
    • date-effective

      • 默认值:N/A
      • type: String (包含日期和时间)
        当前系统时间在date-effective之后,该规则不会再被激活。
    • duration

      • 默认值:无
      • type: long (包含日期和时间)
        duration用于表示一个规则在一定时间之后才会被命中,如果它还是激活状态的话。

    LHS语法

    LHS是规则的条件部分的统称,由零到多条条件元素组成。如果LHS为空,默认为是条件部分一直为true。当一个新的WorkingMemory session创建的时候,会被激活和触发。
    Example. Rule without a Conditional Element

    rule "no CEs"
    when
        // empty
    then
        ... // actions (executed once)
    end
    

    // The above rule is internally rewritten as:

    rule "eval(true)"
    when
    eval( true )
    then
    ... // actions (executed once)
    end

    LHS中的条件元素基于一个或多个模式,最常用的条件元素是and。当然如果LHS中有多个不互相连接的模式时,默认使用隐式的and
    Implicit and

    rule "2 unconnected patterns"
    when
        Pattern1()
        Pattern2()
    then
        ... // actions
    end
    

    // The above rule is internally rewritten as:

    rule "2 and connected patterns"
    when
    Pattern1()
    and Pattern2()
    then
    ... // actions
    end

    模式
    模式是最终要的条件元素,它可以隐式地匹配所有插入到WorkingMemory中的所有fact。一个模式具有0个或多个约束条件和一个可选的模式组合。模式的结构图如下所示:

    Pattern.png

    下面给出一个最简单的模式的例子

    Person()
    

    这里的类型为Person,该模式意味着将匹配WorkingMemory中的所有Person对象。该类型不需要是一个真实 fact对象的类。模式可以指向超类甚至是接口,这样可以匹配多个不同类的facts。例如:

    Object() // matches all objects in the working memory
    

    模式的括号中条件定义了模式在何种条件下满足。如下所示:

    Person( age == 100 )
    

    为了引用匹配的对象,可以使用一个模式绑定参数如:$p
    Example . Pattern with a binding variable

    rule ...
    when
        $p : Person()
    then
        System.out.println( "Person " + $p );
    end
    

    $符号是非强制性的,只是用于在复杂的规则中方便标识,将其与变量及域区分开来。
    约束

    • 什么是约束?

    约束是一个返回truefalse的表达式,如下例所示:

    Person( 5 < 6 )  // just an example, as constraints like this would be useless in a real pattern
    

    约束本质上是一个与Java表达式稍微有点不同的表达式,例如equals()等价于==。接下来我们深入理解一下。

    • Java Beans属性获取。

    任何一个bean的属性都可以被直接使用,bean属性的获取也可以使用标准的Java bean getter: getMyProperty() or isMyProperty()。例如:

    //use directly
    Person( age == 50 )
    

    // this is the same as:
    Person( getAge() == 50 )

    同时,Drools还支持嵌套的属性获取方式,如:

    //use directly
    Person( address.houseNumber == 50 )
    

    // this is the same as:
    Person( getAddress().getHouseNumber() == 50 )

    当然,约束中的条件表达式是支持Java表达式的,下面几个例子都是正确的:

    Person( age == 50 )
    Person( age > 100 && ( age % 10 == 0 ) )
    Person( Math.round( weight / ( height * height ) ) < 25.0 )
    
    • 逗号分隔符 AND

    逗号分隔约束,具有隐含的AND的含义。

    // Person is at least 50 and weighs at least 80 kg
    Person( age > 50, weight > 80 )
    

    // Person is at least 50, weighs at least 80 kg and is taller than 2 meter.
    Person( age > 50, weight > 80, height > 2 )

    逗号运算符不能出现在复合的约束表达式中,如

    // Do NOT do this: compile error
    Person( ( age > 50, weight > 80 ) || height > 2 ) 
    

    // Use this instead
    Person( ( age > 50 && weight > 80 ) || height > 2 )

    • 绑定变量

    属性值可以绑定到一个变量中:

    // 2 persons of the same age
    Person( $firstAge : age ) // binding
    Person( age == $firstAge ) // constraint expression
    
    • 分组访问嵌套对象属性

    可以先看一个例子:

    Person( name == "mark", address.city == "london", address.country == "uk" )
    

    Person( name == "mark", address.( city == "london", country == "uk") )

    也就是对嵌套对象属性的访问,可以组合在一个括号里面。

    • 内联强制类型转换

    当处理嵌套对象时,往往需要将其转换成子类,可以通过使用#符号来完成。如下例所示:

    Person( name == "mark", address#LongAddress.country == "uk" )
    

    在该例子中将 Address转换成LongAddress。如果类型转换失败,该值会被认为是false。当然,类型转换也支持全称限定名称。如下所示:

    Person( name == "mark", address#org.domain.LongAddress.country == "uk" )
    

    当然,在同一个表达式中使用多级内联转换也是可行的。如下所示:

    Person( name == "mark", address#LongAddress.country#DetailedCountry.population > 10000000 )
    

    另外,Drools同样支持instanceof操作。

    Person( name == "mark", address instanceof LongAddress, address.country == "uk" )
    
    • 特殊文字支持
      除了正常的Java文字,Drools还支持以下特殊的文字:
      • 日期文字。

    查询(Query)

    Domain Specific Languages

    原文地址:https://www.jianshu.com/p/ae9a62588da4
  • 相关阅读:
    pdf.js-----后端返回utf-8数据流,前端处理数据展示pdf
    正则表达式之去除前后空格
    ng之邮箱校验
    ng-校验重复并提示具体重复内容
    input 数值框处理
    逻辑之不重复
    ng -----监听变化($scope.$watch())
    js中document的用法
    php中12个魔术方法
    php 中const和 define的区别
  • 原文地址:https://www.cnblogs.com/jpfss/p/12016578.html
Copyright © 2011-2022 走看看