0%

jbpm和drools

JBPM是开源的工作流引擎,drools是基于RETE算法的开源规则引擎。

JBPM

JBPM核心特性

  • 轻量(基于Java且完全开源)
  • 支持bpmn2
  • 支持持久层和事务
  • UI界面
  • 可以基于eclipse和web
  • 规则引擎

安装插件

在eclipse中安装插件https://downloads.jboss.org/jbpm/release/7.47.0.Final/updatesite/,下载运行时类并配置https://download.jboss.org/jbpm/release/7.47.0.Final/jbpm-7.47.0.Final-bin.zip。此时可以创建一个默认的HelloWorld示例。

示例

HelloWorld示例目录结构如图

ProcessMain代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class ProcessMain {

private static final Logger logger = LoggerFactory.getLogger(ProcessMain.class);
private static final boolean usePersistence = true;

public static final void main(String[] args) throws Exception {
// load up the knowledge base
KieBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = newStatefulKnowledgeSession(kbase);
// start a new process instance
ksession.startProcess("com.sample.bpmn.hello");
logger.info("Process started ...");
}

private static KieBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("com/sample/sample.bpmn2"), ResourceType.BPMN2);
return kbuilder.newKieBase();
}

public static StatefulKnowledgeSession newStatefulKnowledgeSession(KieBase kbase) {
RuntimeEnvironmentBuilder builder = null;
if ( usePersistence ) {
Properties properties = new Properties();
properties.put("driverClassName", "org.h2.Driver");
properties.put("className", "org.h2.jdbcx.JdbcDataSource");
properties.put("user", "sa");
properties.put("password", "");
properties.put("url", "jdbc:h2:tcp://localhost/~/jbpm-db");
properties.put("datasourceName", "jdbc/jbpm-ds");
PersistenceUtil.setupPoolingDataSource(properties);
Map<String, String> map = new HashMap<String, String>();
map.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.jbpm.persistence.jpa");
builder = RuntimeEnvironmentBuilder.Factory.get()
.newDefaultBuilder()
.entityManagerFactory(emf);
} else {
builder = RuntimeEnvironmentBuilder.Factory.get()
.newDefaultInMemoryBuilder();
DeploymentDescriptor descriptor =
new DeploymentDescriptorManager().getDefaultDescriptor().getBuilder().auditMode(AuditMode.NONE).get();
builder.addEnvironmentEntry("KieDeploymentDescriptor", descriptor);
}
builder.knowledgeBase(kbase);
RuntimeManager manager = RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(builder.get());
return (StatefulKnowledgeSession) manager.getRuntimeEngine(EmptyContext.get()).getKieSession();
}
}

bpmn2文件直接用图形化页面编辑。

Drools

基本概念

  • 事实(facts):代表规则的输入数据。
  • 规则(rule):事实和动作之间的连接,有两种表示方式,一种是用Drools规则语言写的.drl文件,一种是用决策表的excel文件。
  • KieSession:拥有触发规则的所有资源

安装Drools插件

eclipse对Drools的支持更加友好,所以用eclipse作为开发工具。

步骤:Help -> Install New Software。然后选择合适的版本
https://download.jboss.org/drools/release/7.47.0.Final/org.drools.updatesite/
如eclipse插件下载失败,根据报错信息去网站下载jar包,放入eclipse的plugins文件夹下。

配置Drools Runtimes

下载drools-distribution-7.47.0.Final.zip,解压缩,eclipse–>preferences–>drools

使用

新建drools项目,HelloWorld示例目录结构如图

DroolsTest类代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class DroolsTest {

public static final void main(String[] args) {
try {
// load up the knowledge base
KieServices ks = KieServices.Factory.get();
KieContainer kContainer = ks.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("ksession-rules");

// go !
Message message = new Message();
message.setMessage("Hello World");
message.setStatus(Message.HELLO);
kSession.insert(message);
kSession.fireAllRules();
} catch (Throwable t) {
t.printStackTrace();
}
}

public static class Message {

public static final int HELLO = 0;
public static final int GOODBYE = 1;

private String message;

private int status;

public String getMessage() {
return this.message;
}

public void setMessage(String message) {
this.message = message;
}

public int getStatus() {
return this.status;
}

public void setStatus(int status) {
this.status = status;
}

}

}

配置文件kmodule.xml如下

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="rules" packages="com.sample.rules">
<ksession name="ksession-rules"/>
</kbase>
<kbase name="dtables" packages="com.sample.dtables">
<ksession name="ksession-dtables"/>
</kbase>
<kbase name="process" packages="com.sample.process">
<ksession name="ksession-process"/>
</kbase>
</kmodule>

规则文件Sample.drl如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.sample.rules

import com.sample.DroolsTest.Message;

rule "Hello World"
when
m : Message( status == Message.HELLO, myMessage : message )
then
System.out.println( myMessage );
m.setMessage( "Goodbye cruel world" );
m.setStatus( Message.GOODBYE );
update( m );
end

rule "GoodBye"
when
Message( status == Message.GOODBYE, myMessage : message )
then
System.out.println( myMessage );
end

决策表

  • 决策表使用简洁的语法定义一系列规则,格式为.xls或者csv。
  • 决策表分两部分RuleSetRuleTable

RuleSet

常用的关键字

  • RuleSet:生成DRL文件的包名,必须在第一行。
  • Import:引入的java类,以逗号分隔。

RuleTable

RuleTable左边的行都会被忽略

DRL语言

定义在.drl文件中业务规则,一个文件可以包含一到多个规则。

规则属性

属性定义位置在条件和动作前,格式如下:

1
2
3
4
5
6
7
8
rule "rule_name"
// Attribute
// Attribute
when
// Conditions
then
// Actions
end

常用规则属性有:

  • no-loop:布尔值,默认为false,意为只要满足条件,就会重复执行