activiti
为满足用户自定义流程,这里采用排他网关将所有流程节点相连接并设置好连线参数,用户可以自行配置每一节点后下一步的参数,达到流程配置的目的
依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>
<properties>
<project.build.sourceencoding>UTF-8</project.build.sourceencoding>
<project.reporting.outputencoding>UTF-8</project.reporting.outputencoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-bpmn-layout</artifactId>
<version>6.0.0.RC1</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
代码
package com.sws.activiti.controller;
import org.activiti.bpmn.BpmnAutoLayout;
import org.activiti.bpmn.model.*;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.Mapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
@RestController
@RequestMapping("/activiti")
public class ActivitiController {
@Autowired
private RuntimeService runtimeService;
@Autowired
private RepositoryService repositoryService;
@RequestMapping("/start_activiti")
public void startActiviti() throws IOException {
BpmnModel model = new BpmnModel();
org.activiti.bpmn.model.Process process = new org.activiti.bpmn.model.Process();
model.addProcess(process);
String bpmId = "my-process";
process.setId(bpmId);
process.addFlowElement(createStartEvent());
// process.addFlowElement(createUserTask("task1", "First task", "fred"));
// process.addFlowElement(createUserTask("task2", "Second task", "john"));
int nodeNum = 7;
for(int i=1;i<nodeNum+1;i++){
process.addFlowElement(createUserTask("task"+i,"task"+i));
process.addFlowElement(createExclusiveGateway("gatway"+i));
process.addFlowElement(createSequenceFlow("task"+i, "gatway"+i));
process.addFlowElement(createSequenceFlow("gatway"+i,"end","${type=-1}"));
}
for(int i=1;i<nodeNum+1;i++){
for(int j=1;j<nodeNum+1;j++){
if(i==j){
continue;
}
process.addFlowElement(createSequenceFlow("gatway"+i, "task"+j,"${type="+j+"}"));
}
}
process.addFlowElement(createEndEvent());
process.addFlowElement(createSequenceFlow("start", "task1"));
// 2. Generate graphical information
new BpmnAutoLayout(model).execute();
// 3. Deploy the process to the engine
// Deployment deployment = activitiRule.getRepositoryService().createDeployment()
// .addBpmnModel("dynamic-model.bpmn", model).name("Dynamic process deployment")
// .deploy();
Deployment deployment = repositoryService.createDeployment()
.addBpmnModel("dynamic-model.bpmn", model).name("Dynamic process deployment")
.deploy();
// // 4. Start a process instance
// ProcessInstance processInstance = activitiRule.getRuntimeService()
// .startProcessInstanceByKey("my-process");
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(bpmId);
// // 5. Check if task is available
// List tasks = activitiRule.getTaskService().createTaskQuery()
// .processInstanceId(processInstance.getId()).list();
// Assert.assertEquals(1, tasks.size());
// Assert.assertEquals("First task", tasks.get(0).getName());
// Assert.assertEquals("fred", tasks.get(0).getAssignee());
// 6. Save process diagram to a file
// InputStream processDiagram = activitiRule.getRepositoryService().getProcessDiagram(processInstance.getProcessDefinitionId());
InputStream processDiagram = repositoryService.getProcessDiagram(processInstance.getProcessDefinitionId());
FileUtils.copyInputStreamToFile(processDiagram, new File("processes/diagram.png"));
// 7. Save resultingBPMN xml to a file
// InputStream processBpmn = activitiRule.getRepositoryService().getResourceAsStream(deployment.getId(), "dynamic-model.bpmn");
InputStream processBpmn = repositoryService.getResourceAsStream(deployment.getId(), "dynamic-model.bpmn");
FileUtils.copyInputStreamToFile(processBpmn, new File("processes/process.bpmn20.xml"));
}
/*任务节点*/
// protected UserTask createUserTask(String id, String name, String assignee) {
protected UserTask createUserTask(String id, String name) {
UserTask userTask = new UserTask();
userTask.setName(name);
userTask.setId(id);
//userTask.setAssignee(assignee);
return userTask;
}
/*连线*/
protected SequenceFlow createSequenceFlow(String from, String to) {
SequenceFlow flow = new SequenceFlow();
flow.setSourceRef(from);
flow.setTargetRef(to);
return flow;
}
protected SequenceFlow createSequenceFlow(String from, String to,String skipExpression) {
SequenceFlow flow = new SequenceFlow();
flow.setSourceRef(from);
flow.setTargetRef(to);
flow.setSkipExpression(skipExpression);
return flow;
}
/*排他网关*/
protected ExclusiveGateway createExclusiveGateway(String id) {
ExclusiveGateway exclusiveGateway = new ExclusiveGateway();
exclusiveGateway.setId(id);
return exclusiveGateway;
}
/*开始节点*/
protected StartEvent createStartEvent() {
StartEvent startEvent = new StartEvent();
startEvent.setId("start");
return startEvent;
}
/*结束节点*/
protected EndEvent createEndEvent() {
EndEvent endEvent = new EndEvent();
endEvent.setId("end");
return endEvent;
}
}
配置
spring.datasource.url=jdbc:mysql://192.168.153.131:3306/activiti?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.activiti.check-process-definitions=false
spring.activiti.process-definition-location-prefix= classpath:/processes/
取人规则
每个节点配置对应的取人规则,需要在对应的节点上绑定Task监听器来获取人员
-
id
-
rule_cd
-
remote_rule_cd
- 远程规则cd
-
rule_type
- every_one
- user_fix
- user_apply
- dept_duty
- dept_apply
- dept_fix
- office_duty
- office_apply
- office_fix
-
company_cd
-
user_cd
-
orgn_cd
人员
-
所有人
- rule_type
- every_one
- rule_type
-
固定人员
- rule_type
- user_fix
- user_cd
- xxx
- rule_type
-
提交人
- rule_type
- user_apply
- rule_type
-
责任部门
- rule_type
- dept_duty
- level
- 3
- rule_type
-
申报部门
- rule_type
- dept_apply
- level
- 3
- rule_type
-
固定部门
- rule_type
- dept_fix
- level
- 3
- orgn_cd
- xxx
- rule_type
-
责任科室
- rule_type
- office_duty
- level
- 4
- rule_type
-
申报科室
- rule_type
- office_apply
- level
- 4
- rule_type
-
固定科室
- rule_type
- office_fix
- level
- 4
- orgn_cd
- xxx
- rule_type
流程选取
用户配置多个流程,可以通过juel以及优先级等方法来匹配需要的流程
- id
- company_cd
- process_cd
- is_default
- 一个公司仅一个
- juel
- 需要解析juel表达式
package com.sws.activiti.controller;
import com.sws.activiti.dto.Factor;
import de.odysseus.el.ExpressionFactoryImpl;
import de.odysseus.el.util.SimpleContext;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
@RestController
@RequestMapping("/juel")
public class JuelController {
@RequestMapping("/test")
public void testJuel(@RequestBody Factor factor) throws NoSuchMethodException {
ExpressionFactory factory = new ExpressionFactoryImpl();
//de.odysseus.el.util provides包提供即时可用的子类ELContext
//创建上下文对象context
SimpleContext context = new SimpleContext();
factory.createValueExpression(context, "#{factor}", Factor.class).setValue(context, factor);
ValueExpression expr2 = factory.createValueExpression(context, "${factor.level>10 || factor.type==\"xxx\"}", Boolean.class);
System.out.println("++++++++++++++++++++++++++++++++++++++++++++++");
System.out.println(expr2.getValue(context).toString());
System.out.println("++++++++++++++++++++++++++++++++++++++++++++++");
}
}
<dependency>
<groupId>de.odysseus.juel</groupId>
<artifactId>juel-spi</artifactId>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>de.odysseus.juel</groupId>
<artifactId>juel-api</artifactId>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>de.odysseus.juel</groupId>
<artifactId>juel-impl</artifactId>
<version>2.2.7</version>
</dependency>