【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.4 约束(Pattern的一部分)

4.4.3 约束(Pattern的一部分)

前面我们已经介绍了条件约束在Pattern中位置了,那么什么是条件约束呢?简单来说就是一个返回true或者false的表达式,比如下面的5小于6,就是一个约束条件。

Person( 5 < 6 )

从本质上来讲,它是JAVA表达式的一种增强版本(比如属性访问),同时它又有一些小的区别,比如equals方法和==的语言区别。下面我们就深入了解一下。

访问JavaBean中的属性

任何一个JavaBean中的属性都可以访问,不过对应的属性要提供getter方法或isProperty方法。比如:

Person( age == 50 )

// 与上面拥有同样的效果
Person( getAge() == 50 )

Drools使用java标准的类检查,因此遵循java标准即可。同时,嵌套属性也是支持的,比如:

Person( address.houseNumber == 50 )

// 与上面写法相同
Person( getAddress().getHouseNumber() == 50 )

在使用有状态session的情况下使用嵌套属性需要注意属性的值可能被其他地方修改。要么认为它们是不可变的,当任何一个父引用被插入到working memory中。或者,如果要修改嵌套属性值,则应将所有外部fact标记更新。在上面的例子中,当houseNumber属性值改变时,任何一个包含Address的Person需要被标记更新。

Java表达式

在pattern的约束条件中,可以任何返回结果为布尔类型的java表达式。当然,java表达式也可以和增强的表达式进行结合使用,比如属性访问。可以通过使用括号来更改计算优先级,如在任一逻辑或数学表达式中。

Person( age > 100 && ( age % 10 == 0 ) )

也可以直接使用java提供的工具方法来进行操作计算:

Person( Math.round( weight / ( height * height ) ) < 25.0 )

在使用的过程中需要注意,在LHS中执行的方法只能是只读的,不能在执行方法过程中改变改变FACT对象的值,否则会影响规则的正确执行。

Person( incrementAndGetAge() == 10 ) //不要像这样在比较的过程中更新Fact对象

另外,FACT对象的相关状态除了被在working memory中进行更新操作,不应该每次调用时状态会发生变化。

Person( System.currentTimeMillis() % 1000 == 0 ) // 不要这样实现

标准Java运算符优先级也适用,请参见下面的运算符优先级列表。所有的操作符都有标准的Java语义,除了==和!=。它们的null安全的,就相当于java中比较两个字符串时把常量字符串放前面调用equals方法的效果一样。

约束条件的比较过程中是会进行强制类型转换的,比如在数据计算中传入字符串“10”,则能成功转换成数字10进行计算。但如果,此时传入的值无法进行转换,比如传了“ten”,那么将会抛出异常。

逗号分隔符

逗号可以对约束条件进行分组,它的作用相当于“AND”。

// Person的年龄要超过50,并且重量 超过80 kg
Person( age > 50, weight > 80 )

虽然“&&”和“,”拥有相同的功能,但是它们有不同的优先级。“&&”优先于“||”,“&&”和“||”又优先于“,”。但建议优先使用“,”分隔符,因为它更利于阅读理解和引擎的优化操作。同时,逗号分隔符不能和其他操作符混合使用,比如:

Person( ( age > 50, weight > 80 ) || height > 2 ) // 会编译错误

// 使用此种方法替代
Person( ( age > 50 && weight > 80 ) || height > 2 )

绑定变量

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

// 2 person的age属性值相同
Person( $firstAge : age ) // 绑定
Person( age == $firstAge ) // 约束表达式

前缀$只是个通用惯例,在复杂规则中可以通过它来区分变量和属性。为了向后兼容,允许(但不推荐)混合使用约束绑定和约束表达式。

// 不建议这样写
Person( $age : age * 2 < 100 )

// 推荐(分离绑定和约束表达式)
Person( age * 2 < 100, $age : age )

使用操作符“==”来绑定变量,Drools会使用散列索引来提高执行性能。

内部类分组访问

通常情况,我们访问一个内部类的多个属性时会有如下的写法:

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

Drools提供的分组访问可以更加方便进行使用:

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

注意前缀’.’是用来区分嵌套对象约束和方法调用所必需的。

内部强制转换

在使用内部类的时候,往往需要将其转换为父类,在规则中可以通过“#”来进行强制转换:

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

上面的例子将Address强制转换为LongAddress.,这样使得getter方法变得可用。如果无法强制转换,表达式计算的结果为false。强制转换也支持全路径的写法:

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

多次内部转换语法:

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

也可以使用instanceof操作符进行判断,判断之后将进一步使用该属性进行比较。

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

日期字符

规则语法中除了支持JAVA标准字符,同时也支持日期字符。Drools默认支持的日期格式为“dd-mmm-yyyy”,可以通过设置系统变量“drools.dateformat”的值来改变默认的日期格式。

Cheese( bestBefore < "27-Oct-2009" )

List和Map的访问

访问List:

// 和childList(0).getAge() == 18效果相同
Person( childList[0].age == 18 )

根据key访问map:

// 和credentialMap.get("jsmith").isValid()相同
Person( credentialMap["jsmith"].valid )

&&和||

约束表达式可以通过&&和||来进行判断比较,此处用法与标准Java相似,当组合使用时,可通过括号来划分优先级。

Person( age > 30 && < 40 )
Person( age ( (> 30 && < 40) ||(> 20 && < 25) ) )
Person( age > 30 && < 40 || location == "london" )

DRL特殊操作符

“< ? > >=”操作符用于属性的比较是按照默认的排序,比如日期属性使用小于号标示可以按照日期排序,当使用在String字符串的比较时,则按照字母顺序进行排序。此操作符仅适用于可比较的属性。

Person( firstName < $otherFirstName )
Person( birthDate < $otherBirthDate )

“!.”提供了一个默认空校验的操作。当使用此操作符时,会先校验当前对象是否为null,如果不为null再调用其方法或获得其属性进行判断。一旦当前操作对象为null,则相当于结果为false。

Person( $streetName : address!.street )

// 上面的写法相当于
Person( address != null, $streetName : address.street )

matches操作符可使用Java的正则表达式进行字符串的匹配,通常情况下是对字符串进行匹配,但也支持变量值为正确的表达式的方式。此操作符仅适用于字符串属性。如果属性值为null,匹配的结果始终为false。

Cheese( type matches "(Buffalo)?\\S*Mozzarella" )

not matches方法与matches相同,唯一不同的是返回的结果与之相反。

Cheese( type not matches "(Buffalo)?\\S*Mozzarella" )

contains操作符判断一个集合属性或元素是否包含指定字符串或变量值。仅适用于集合属性。也可以用于替代String.contains()来检查约束条件。not contains用法与之相同,结果取反。

CheeseCounter( cheeses contains "stilton" ) // 包含字符串
CheeseCounter( cheeses contains $var ) // 包含变量

Cheese( name contains "tilto" )
Person( fullName contains "Jr" )
String( this contains "foo" )

memberOf用来检查属性值是否为集合,此集合的表示必须为变量。not memberOf使用方法相同,结果取反。

CheeseCounter( cheese memberOf $matureCheeses )

soundslike的效果与matches相似,但它用来检查一个字符串的发音是否与指定的字符十分相似(使用英语发音)。

// 匹配 "fubar" 或 "foobar"
Cheese( name soundslike ‘foobar‘ )

str操作用来比较一个字符串是否以指定字符串开头或结尾,有可以用于比较字符串的长度。

Message( routingValue str[startsWith] "R1" )

Message( routingValue str[endsWith] "R2" )

Message( routingValue str[length] 17 )

in和notin用来匹配一组数据中是否含一个或多个匹配的字符串,使用的方法与数据库中in的使用方法相似。待匹配的数据可以是字符串、变量。

Person( $cheese : favouriteCheese )
Cheese( type in ( "stilton", "cheddar", $cheese ) )

运算符优先级

操作类型 操作符 备注
(嵌套/空安全)属性访问 .!. 非标准java语义
List/Map访问 [ ] 非标准java语义
约束绑定 : 非标准java语义
乘除 */%  
加减 +-  
移位 <<>>>>>  
关系 <>?>=instanceof  
==!= 未使用标准java语义,某些语义相当于equals。
非短路AND &  
非短路异或 ^  
非短路包含OR |  
逻辑与 &&  
逻辑或 ||  
三元运算符 ? :  
逗号分隔,相当于and , 非标准java语义








原文地址:https://www.cnblogs.com/shangxiaofei/p/9439611.html

时间: 2024-11-05 19:04:50

【java规则引擎】《Drools7.0.0.Final规则引擎教程》第4章 4.4 约束(Pattern的一部分)的相关文章

阿里巴巴Java开发手册1.4.0

转自官网 前言 <阿里巴巴Java开发手册>是阿里巴巴集团技术团队的集体智慧结晶和经验总结,经历了多次大规模一线实战的检验及不断完善,系统化地整理成册,回馈给广大开发者.现代软件行业的高速发展对开发者的综合素质要求越来越高,因为不仅是编程知识点,其它维度的知识点也会影响到软件的最终交付质量.比如:数据库的表结构和索引设计缺陷可能带来软件上的架构缺陷或性能风险:工程结构混乱导致后续维护艰难:没有鉴权的漏洞代码易被黑客攻击等等.所以本手册以Java开发者为中心视角,划分为编程规约.异常日志.单元测

Java多线程-线程池ThreadPoolExecutor构造方法和规则

为什么用线程池 博客地址 http://blog.csdn.net/qq_25806863 原文地址 http://blog.csdn.net/qq_25806863/article/details/71126867 有时候,系统需要处理非常多的执行时间很短的请求,如果每一个请求都开启一个新线程的话,系统就要不断的进行线程的创建和销毁,有时花在创建和销毁线程上的时间会比线程真正执行的时间还长.而且当线程数量太多时,系统不一定能受得了. 使用线程池主要为了解决一下几个问题: 通过重用线程池中的线程

Java EE 7 / JAX-RS 2.0: Simple REST API Authentication &amp; Authorization with Custom HTTP Header--reference

REST has made a lot of conveniences when it comes to implementing web services with the already available HTTP protocol at its disposal. By just firing GET, POST and other HTTP methods through the designated URL, you’ll sure to get something done thr

阿里巴巴Java开发手册v1.2.0

最近阿里出了java开发手册v1.2.0版,看一下自己平时有哪些做不到的,特此记录一下(不太理解的标为红色) 此手册编写是为了提供代码质量,降低协同成本,提升沟通效率.对无规范的沟通深有感触. 编程规范 变量规范 1.类名在 PO(Persist Object) VO(Value Object) BO(Business Object) DO(Domain Object) DTO(Data Transfer Object) AO(Access Object)使要保持大写 2.抽象类名Abstrac

《Java知识点列表》V1.0

<Java知识点列表>V1.0  1 开发环境Java SDK 下载和安装 2 环境变量的配置(path和classpath) 3 编程基础 标识符命名规范 4 Java数据类型5 运算符6 分支语句(if,switch)7 循环语句(for,while)8 函数的定义方法9 面向对象基础 面向对象与面向过程语言之间的区别10 面向对象基本思想(封装)11 类的定义方法12 对象和类的关系13 对象的创建方法14 通过对象使用成员变量和成员函数的方法15 构造函数的作用16 函数的重载17 s

java在线聊天项目1.0版 异常处理——开启多个客户端,关闭一个客户端后,在其他客户端中再发出信息会出现异常的处理

异常一 只开启一个客户端,输入信息后关闭,客户端出现如下异常 根据异常说明 ChatClientFrame客户端117行 提示原因是Socket关闭 分析原因 客户端代码 while (connected) { String str = dis.readUTF(); 当窗口关闭后,Socket已经关闭,读的操作还在继续 处理这个异常,代码如下 catch (SocketException e) { System.out.println("a client has been closed!&quo

旗正商业规则引擎和开源及其它规则引擎测试对比

规则引擎在基础软件,或者在很多系统中已经不是稀奇的玩意,最近这几年,国内不断兴起很多的规则引擎,至于什么是规则引擎,在这篇文章中,就不做介绍了,我想能看以下内容的,多少对规则引擎也都有所了解了. 国内在2003年的时候,出了第一款商业规则引擎-旗正商业规则引擎(VisualRules),为什么这么说呢,因为再此之前,国内所用的规则引擎,都是国外产品,或者开源产品,纯自主研发旗正是第一款,直至目前为止,纯自主研发的规则引擎少之又少.那么旗正商业规则引擎到底怎样?今天,给大家介绍一下,顺便,我们拿出

在java中使用solr7.2.0 新旧版本创建SolrClient对比

在Java中使用solr 版本7.2.0 solrj已经更新到了7.2.0,新版本solr获取SolrClient的方式也和之前旧版本有所不同 solr6.5开始不推荐直接使用HttpSolrClient的构造方法创建SolrClient(6.5之前版本的创建方式在页末) 从7.0.0开始删除了HttpSolrClient创建客户端的构造方法,使用内部类Builder构建SolrClient 安装solr:https://my.oschina.net/u/2931319/blog/1595303

五年磨一剑:Java 开源博客 Solo 1.0.0 发布了!

从 Solo 第一个版本发布至今,已经过去 5 年了.今天我们非常自豪地宣布,Solo 1.0.0 正式发布,感谢一直以来关注 B3log 开源的朋友! 目前 B3log 开源有三款产品: GitHub 上 Star 数最多的 Java 博客 Solo Golang 黑科技之在线 IDE Wide 基于实时交互技术的社区 Sym 特性 基于标签的文章分类 博客/标签 Atom/RSS.Sitemap 输出 评论回复及邮件提醒 自定义页面.导航 多编辑器:Markdown.TinyMCE.Kind