使用规则引擎drools驱动工作流
本文通过一个简单的例子演示了如何将规则引擎作为工作流的驱动引擎。
财务报销流程如下:
设计思路:
1,单据的流转,是通过单据的状态变化来反映的
2,用户的动作(审批、驳回)是单据状态变更的来源
3,将动作与状态的映射关系,抽象为一系列规则,由规则引擎计算单据的结果状态。
规则描述:
//rule.txt
package TEST.WORKFLOW;
import TEST.WORKFLOW.*;
rule "驳回"
when
bill : Bill(action == "驳回")
then
bill.setStatus("驳回");
end
rule "1, 送审"
when
bill: Bill(status == "待审批", action == "送审")
then
bill.setStatus("部门经理审批");
end
rule "2, 部门经理同意"
when
bill: Bill(status == "部门经理审批", action == "同意")
then
bill.setStatus("额度判断");
update(bill);
end
rule "3.1, 大于等于2万"
when
bill: Bill(status == "额度判断", amount >= 20000)
then
bill.setStatus("总经理审批");
end
rule "3.2, 小于2万"
when
bill: Bill(status == "额度判断", amount < 20000)
then
bill.setStatus("财务审核");
end
rule "4, 总经理同意"
when
bill: Bill(status == "总经理审批", action == "同意")
then
bill.setStatus("财务审核");
end
rule "5, 财务审核"
when
bill : Bill(status == "财务审核", action == "审核")
then
bill.setStatus("审批生效");
end
java代码:
//Bill.java, 报销单
package TEST.WORKFLOW;
/**
* Created by IntelliJ IDEA.
* User: ioly
* Date: 2008-10-28
* Time: 11:31:28
* 报销单
*/
//报销单
public class Bill {
//状态
private String _status;
public String getStatus(){
return _status;
}
public void setStatus(String value){
_status = value;
}
//动作
private String _action;
public String getAction(){
return _action;
}
public void setAction(String value){
_action = value;
}
//金额
private Double _amount;
public Double getAmount(){
return _amount;
}
public void setAmount(Double value){
_amount = value;
}
}
测试代码:
//Test.java,测试代码
package TEST.WORKFLOW;
import org.drools.compiler.PackageBuilder;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.StatefulSession;
import java.io.Reader;
import java.io.InputStreamReader;
import java.util.Date;
import TEST.WorkDate;
import TEST.Shift;
import TEST.Worker;
/**
* Created by IntelliJ IDEA.
* User: ioly
* Date: 2008-10-28
* Time: 11:32:13
* To change this template use File | Settings | File Templates.
*/
//测试代码
public class Test {
public static void main(String[] args) throws Exception{
//read in the source
Reader source = new InputStreamReader(Test.class.getResourceAsStream("rule.txt"), "GBK");
PackageBuilder builder = new PackageBuilder();
//this wil parse and compile in one step
builder.addPackageFromDrl(source);
// Check the builder for errors
if (builder.hasErrors()) {
System.out.println(builder.getErrors().toString());
throw new RuntimeException("Unable to compile.");
}
//get the compiled package (which is serializable)
org.drools.rule.Package pkg = builder.getPackage();
//add the package to a rulebase (deploy the rule package).
RuleBase ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage(pkg);
//测试
StatefulSession session;
Bill bill = new Bill();
//1,送审
bill.setStatus("待审批");
bill.setAction("送审");
session = ruleBase.newStatefulSession();
session.insert(bill);
session.fireAllRules();
assert "部门经理审批".equalsIgnoreCase(bill.getStatus());
//2, 部门经理同意
bill.setStatus("部门经理审批");
bill.setAction("同意");
bill.setAmount(10000d);
session = ruleBase.newStatefulSession();
session.insert(bill);
session.fireAllRules();
assert "财务审核".equalsIgnoreCase(bill.getStatus());
bill.setStatus("部门经理审批");
bill.setAction("同意");
bill.setAmount(20000d);
session = ruleBase.newStatefulSession();
session.insert(bill);
session.fireAllRules();
assert "总经理审批".equalsIgnoreCase(bill.getStatus());
//4, 总经理审批
bill.setStatus("总经理审批");
bill.setAction("同意");
session = ruleBase.newStatefulSession();
session.insert(bill);
session.fireAllRules();
assert "财务审核".equalsIgnoreCase(bill.getStatus());
//5, 财务审核
bill.setStatus("财务审核");
bill.setAction("审核");
session = ruleBase.newStatefulSession();
session.insert(bill);
session.fireAllRules();
assert "审批生效".equalsIgnoreCase(bill.getStatus());
//驳回
bill.setStatus("部门经理审批");
bill.setAction("驳回");
session = ruleBase.newStatefulSession();
session.insert(bill);
session.fireAllRules();
assert "驳回".equalsIgnoreCase(bill.getStatus());
bill.setStatus("总经理审批");
bill.setAction("驳回");
session = ruleBase.newStatefulSession();
session.insert(bill);
session.fireAllRules();
assert "驳回".equalsIgnoreCase(bill.getStatus());
}
}