目前几大Java开源流程引擎:Activiti6、JBoss JBPM 6.5、JFlow 6.0。都说activiti文档最全,资料最丰富,于是就研究了一下,分享给大家。
一、入门——集成spring mvc
1、修改pom.xml
<activti.engine.version>6.0.0</activti.engine.version>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>${activti.engine.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>${activti.engine.version}</version>
</dependency>
2、添加spring-activiti.xml
为隔离其他业务表,activiti使用独立datasource,单独配置transactionManager事务回滚。以及自动部署bpmn文件。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="transactionManager_activiti"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource_activiti"/>
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager_activiti" />
<!-- 配置事务属性 -->
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>repositoryService</value>
<value>runtimeService</value>
<value>taskService</value>
<value>historyService</value>
<value>managementService</value>
<value>identityService</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
<!-- activiti datasource -->
<bean id="dataSource_activiti" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.activiti.driverClass}"/>
<property name="url" value="${jdbc.activiti.jdbcUrl}"/>
<property name="username" value="${jdbc.activiti.user}"/>
<property name="password" value="${jdbc.activiti.password}"/>
<property name="defaultAutoCommit" value="${jdbc.activiti.auto-commit}" />
<property name="testWhileIdle" value="true" />
<property name="validationQuery" value="SELECT 1" />
</bean>
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource_activiti"/>
<property name="transactionManager" ref="transactionManager_activiti"/>
<property name="databaseSchemaUpdate" value="true"/>
<property name="asyncExecutorActivate" value="true"/>
<property name="deploymentResources" value="classpath*:/activiti/*.bpmn"/>
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration"/>
</bean>
<bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
<bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
<bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
<bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
<bean id="managementService" factory-bean="processEngine" factory-method="getManagementService"/>
<bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>
</beans>
3、使用idea2018安装bpmn插件后,绘制流程图
![](https://img.haomeiwen.com/i18760789/edb5a62fe60b3dd7.png)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1578358782707" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="copy02" isClosed="false" isExecutable="true" processType="None">
<startEvent id="_2" name="StartEvent"/>
<userTask activiti:candidateGroups="RoleDeptSuper" activiti:exclusive="true" id="_3" name="DeptSuper"/>
<sequenceFlow id="_4" sourceRef="_2" targetRef="_3"/>
<exclusiveGateway gatewayDirection="Unspecified" id="_5" name="SecretLevel"/>
<sequenceFlow id="_6" sourceRef="_3" targetRef="_5"/>
<userTask activiti:candidateGroups="RoleInstituteLeader" activiti:exclusive="true" id="_7" name="InstituteSuper"/>
<userTask activiti:candidateGroups="RoleCopier" activiti:exclusive="true" id="_8" name="DoCopy"/>
<sequenceFlow id="_9" sourceRef="_5" targetRef="_8">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${secret==2}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="_10" sourceRef="_5" targetRef="_7">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${secret==3}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="_11" sourceRef="_7" targetRef="_8"/>
<endEvent id="_12" name="EndEvent"/>
<sequenceFlow id="_13" sourceRef="_8" targetRef="_12"/>
</process>
<bpmndi:BPMNDiagram documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="copy02">
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
<omgdc:Bounds height="32.0" width="32.0" x="275.0" y="35.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
<omgdc:Bounds height="55.0" width="85.0" x="250.0" y="145.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5" isMarkerVisible="false">
<omgdc:Bounds height="32.0" width="32.0" x="270.0" y="280.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7">
<omgdc:Bounds height="55.0" width="85.0" x="125.0" y="380.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_8" id="Shape-_8">
<omgdc:Bounds height="55.0" width="85.0" x="240.0" y="500.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_12" id="Shape-_12">
<omgdc:Bounds height="32.0" width="32.0" x="280.0" y="625.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_13" id="BPMNEdge__13" sourceElement="_8" targetElement="_12">
<omgdi:waypoint x="296.0" y="555.0"/>
<omgdi:waypoint x="296.0" y="625.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_4" id="BPMNEdge__4" sourceElement="_2" targetElement="_3">
<omgdi:waypoint x="291.0" y="67.0"/>
<omgdi:waypoint x="291.0" y="145.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_6" id="BPMNEdge__6" sourceElement="_3" targetElement="_5">
<omgdi:waypoint x="286.0" y="200.0"/>
<omgdi:waypoint x="286.0" y="280.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_5" targetElement="_8">
<omgdi:waypoint x="286.0" y="312.0"/>
<omgdi:waypoint x="286.0" y="500.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_7" targetElement="_8">
<omgdi:waypoint x="165.0" y="435.0"/>
<omgdi:waypoint x="165.0" y="535.0"/>
<omgdi:waypoint x="240.0" y="535.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_5" targetElement="_7">
<omgdi:waypoint x="270.0" y="296.0"/>
<omgdi:waypoint x="165.0" y="335.0"/>
<omgdi:waypoint x="165.0" y="380.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
4、启动流程
public class ActFlowServiceImpl implements ActFlowService {
public static Logger logger = LoggerFactory.getLogger(ActFlowServiceImpl.class);
@Autowired
ProcessEngineFactoryBean processEngine;
@Autowired
private RepositoryService repositoryService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
@Autowired
private IdentityService identityService;
@Autowired
private ManagementService managementService;
@Override
public int ActFlowCopy(Map<String, Object> variables){
String copyFlow = "copy02";
//流程发起人
String submitter = (String)variables.get("submitterId");
//设置流程发起人
identityService.setAuthenticatedUserId(submitter);
//发起流程
runtimeService.startProcessInstanceByKey(copyFlow, variables);
return 0;
}
}
5、数据库
5.1 部署表
![](https://img.haomeiwen.com/i18760789/856683ff3b4c66bc.png)
5.2 流程定义表
![](https://img.haomeiwen.com/i18760789/9c80e50ee84e69df.png)
5.3 流程实例表
![](https://img.haomeiwen.com/i18760789/6bb192118f125c79.png)
5.4 变量表
![](https://img.haomeiwen.com/i18760789/d6e081373f61d88b.png)
二、放弃——查询太麻烦
1、查询指定发起人的流程
List<HistoricProcessInstance> unFinishedList = historyService.createHistoricProcessInstanceQuery()
.startedBy(submitter).orderByProcessInstanceStartTime().desc()
.list();
分析:可以通过historyService进行查询,但是得到的仅是HistoricProcessInstance。如果流程中需要显示“流程当前步骤数”、“流程总步骤数”、“下一步处理人”。这些信息还需要根据流程实例id进入二次查询。如果要获得流程变量,也需要单独查询。如果想在一条记录中包括这些信息,会比较麻烦。更麻烦的是还要分页查询,无法集成通用分页PageHelper,需要另外维护一套分页信息。
2、activiti有自带的用户关系表。如果是已有用户认证授权系统,需要考虑与activiti自带的表进行适配协调。
结论:
如果是需求比较明确,流程相对固定的情况,建议自行开发。
如果是流程非常复杂,流程中分支特别多,可以考虑使用activiti,但类似“下一步处理人”这种需求要特殊处理。
如果要用activiti最好是抱着完全摸清楚表结构,并适当二次开发,来适应需求。总之,适合自己的才是最好的。
网友评论