infoq发布了一个关于规则引擎的介绍real-world rule engines,原文 http://www.infoq.com/articles/rule-engines
onjava上也有两篇文章:
give your business logic a framework with drools http://www.onjava.com/lpt/a/6093
using drools in your enterprise java application http://www.onjava.com/lpt/a/6160
下面总结一下其中的精华:
大多数web和企业java应用可以分成三个部分:一个和用户交互的前台, 一个和后台系统,例如数据库交互的服务层,以及他们中间的业务逻辑。 现在使用框架构建前台和后台系统已经成为普遍共识(例如, struts, cocoon, spring, hibernate, jdo, 和 entity beans), 但却没有一个标准的方法来构建业务逻辑。一些框架,例如 ejb 和 spring 只在一个高层实现业务逻辑,但对于我们组织逻辑代码没有任何帮助,所以,为什么没有一个框架来替换冗繁,易错的if...then语句呢,这个框架应该和其它前台或后台框架一样,易于配置,具有可读性和重用性。下面我们将介绍drools 规则引擎,这个来解决我们问题的框架。
下面是一个典型的java业务逻辑的代码
if ((user.ismemberof(administratorgroup)
&& user.ismemberof(teleworkergroup))
|| user.issuperuser(){
// more checks for specific cases
if((expenserequest.code().equals("b203")
||(expenserequest.code().equals("a903")
&&(totalexpenses<200)
&&(bosssignoff> totalexpenses))
&&(deptbudget.notexceeded)) {
//issue payments
} else if {
//check lots of other conditions
}
} else {
// even more business logic
}
这是大多数程序员写业务逻辑的方法,但是有以下的问题:
- 如果用户有另一个选项,例如("c987") ,那么需要修改上面的代码,当代码很长的时候,修改代码是难于维护的
- 我们如何保证代码的正确性,这个代码只有程序员能够看到,真正的使用者,业务人员无法看到这个代码
- 很多应用程序有相同的业务逻辑,如果某个业务改变了,如何保证其他业务逻辑的一致性
- 业务逻辑能否不合java语言绑定?
- 业务逻辑能否用其他的脚本语言。
java下的规则引擎标准就是jsr94,它的实现主要有jess jena drools
drools中,一个典型的业务逻辑的配置,如下
<?xml version="1.0"?>
<rule-set name="businessrulessample"
xmlns="http://drools.org/rules"
xmlns:java="http://drools.org/semantics/java"
xmlns:xs
="http://www.w3.org/2001/xmlschema-instance"
xs:schemalocation
="http://drools.org/rules rules.xsd
http://drools.org/semantics/java java.xsd">
<!-- import the java objects that we refer
to in our rules -->
<java:import>
java.lang.object
</java:import>
<java:import>
java.lang.string
</java:import>
<java:import>
net.firstpartners.rp.stockoffer
</java:import>
<!-- a java (utility) function we reference
in our rules-->
<java:functions>
public void printstock(
net.firstpartners.rp.stockoffer stock)
{
system.out.println("name:"
+stock.getstockname()
+" price: "+stock.getstockprice()
+" buy:"
+stock.getrecommendpurchase());
}
</java:functions>
<rule-set>
<!-- ensure stock price is not too high-->
<rule name="stock price low enough">
<!-- params to pass to business rule -->
<parameter identifier="stockoffer">
<class>stockoffer</class>
</parameter>
<!-- conditions or 'left hand side'
(lhs) that must be met for
business rule to fire -->
<!-- note markup -->
<java:condition>
stockoffer.getrecommendpurchase() == null
</java:condition>
<java:condition>
stockoffer.getstockprice() < 100
</java:condition>
<!-- what happens when the business
rule is activated -->
<java:consequence>
stockoffer.setrecommendpurchase(
stockoffer.yes);
printstock(stockoffer);
</java:consequence>
</rule>
</rule-set>
一条规则就是rule-set中的rule,如果有很多规则,就要写很多的rule。
上面规则的意思是判断股票价格是否小于100,如果100这个标准改变了,那么只要修改这个规则文件,而不用去修改源代码了