pom.xml introduces dependencies:
<dependencies> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.8.0</version> </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-spring-boot-starter-jpa</artifactId> <version>6.0.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <!-- servlet Support --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <!-- jstl Support --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
Create the process folder under the project root path and create the helloworld.bpmn file
<?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:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" 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="m1567831900728" name="" targetNamespace="http://www.activiti.org/testm1567831900728" typeLanguage="http://www.w3.org/2001/XMLSchema"> <process id="myProcess_1" isClosed="false" isExecutable="true" processType="None"> <startEvent id="_2" name="StartEvent"/> <endEvent id="_3" name="EndEvent"/> <userTask activiti:assignee="zhagnsan" activiti:exclusive="true" id="_4" name="apply"/> <userTask activiti:assignee="lisi" activiti:exclusive="true" id="_5" name="manager apply"/> <userTask activiti:assignee="wangwu" activiti:exclusive="true" id="_6" name="boss apply"/> <sequenceFlow id="_7" sourceRef="_2" targetRef="_4"/> <sequenceFlow id="_8" sourceRef="_4" targetRef="_5"/> <sequenceFlow id="_9" sourceRef="_5" targetRef="_6"/> <sequenceFlow id="_10" sourceRef="_6" targetRef="_3"/> </process> <bpmndi:BPMNDiagram documentation="background=#FFFFFF;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="myProcess_1"> <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"> <dc:Bounds height="32.0" width="32.0" x="75.0" y="170.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"> <dc:Bounds height="32.0" width="32.0" x="645.0" y="180.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"> <dc:Bounds height="55.0" width="85.0" x="190.0" y="165.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"> <dc:Bounds height="55.0" width="85.0" x="335.0" y="165.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6"> <dc:Bounds height="55.0" width="85.0" x="490.0" y="170.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_2" targetElement="_4"> <di:waypoint x="107.0" y="186.0"/> <di:waypoint x="190.0" y="192.5"/> <bpmndi:BPMNLabel> <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_4" targetElement="_5"> <di:waypoint x="275.0" y="192.5"/> <di:waypoint x="335.0" y="192.5"/> <bpmndi:BPMNLabel> <dc: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="_6"> <di:waypoint x="420.0" y="192.5"/> <di:waypoint x="490.0" y="197.5"/> <bpmndi:BPMNLabel> <dc: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="_6" targetElement="_3"> <di:waypoint x="575.0" y="197.5"/> <di:waypoint x="645.0" y="196.0"/> <bpmndi:BPMNLabel> <dc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>
application.yml Configuration Data Source
spring: jpa: properties: show-sql: true hibernate: hbm2ddl: auto: update mvc: view: prefix: /WEB-INF/jsp/ suffix: .jsp datasource: url: jdbc:mysql://localhost:3306/activity username: root password: 123 driverClassName: com.mysql.jdbc.Driver minPoolSize: 3 maxPoolSize: 25 activiti: database-schema-update: true # Automated Deployment Verification Settings: true-on (default), false-off check-process-definitions: false
The core class of the process is Process Engine, which is required for process deployment, startup and query.
public class HelloWorld { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();//By default, the configuration information is read from activiti.cfg.xml in the project root directory, and springboot can be injected /**Deployment process definition*/ @Test public void deploymentProcessDefinition(){ Deployment deployment = processEngine.getRepositoryService()//Service related to process definition and deployment objects .createDeployment()//Create a deployment object .name("helloworld Initial procedures")//Add the name of the deployment .addClasspathResource("process/helloworld.bpmn")//Only one file can be loaded at a time from a classpath resource .addClasspathResource("process/helloworld.png")//Only one file can be loaded at a time from a classpath resource .deploy();//Complete deployment System.out.println("deploy ID: "+deployment.getId());//1 System.out.println("Deployment name:"+deployment.getName());//helloworld starter } /**Start process instance*/ @Test public void startProcessInstance(){ //key of process definition String processDefinitionKey = "helloworld"; ProcessInstance pi = processEngine.getRuntimeService()//Service related to executing process instances and executing objects .startProcessInstanceByKey(processDefinitionKey);//Start the process instance with the key defined by the process. The key corresponds to the attribute value of id in the helloworld.bpmn file. Start with the key value. By default, start according to the latest version of the process definition. System.out.println("Process examples ID:"+pi.getId());//Process instance ID 101 System.out.println("Process definition ID:"+pi.getProcessDefinitionId());//Process definition ID helloworld: 1:4 } /**Query the current person's personal tasks*/ @Test public void findMyPersonalTask(){ String assignee = "Wang Wu"; List<Task> list = processEngine.getTaskService()//Service related to ongoing task management .createTaskQuery()//Creating Task Query Objects .taskAssignee(assignee)//Designated Personal Task Query, Designated Translator .list(); if(list!=null && list.size()>0){ for(Task task:list){ System.out.println("task ID:"+task.getId()); System.out.println("Task Name:"+task.getName()); System.out.println("Task creation time:"+task.getCreateTime()); System.out.println("Task Manager:"+task.getAssignee()); System.out.println("Process examples ID: "+task.getProcessInstanceId()); System.out.println("target of execution ID:"+task.getExecutionId()); System.out.println("Process definition ID:"+task.getProcessDefinitionId()); System.out.println("########################################################"); } } } /**Complete my task*/ @Test public void completeMyPersonalTask(){ //Task ID String taskId = "302"; processEngine.getTaskService()//Service related to ongoing task management .complete(taskId); System.out.println("Completing tasks: tasks ID: "+taskId); } }
The role of service:
RepositoryService |
Management process definition |
RuntimeService |
Execution management, including start, push, delete process instances and other operations |
TaskService |
task management |
HistoryService |
History Management (Management of Executed Data) |
IdentityService |
Organizational management |
FormService |
An optional service, task form management |
ManagerService |
|
Deployment
1. Information on multiple files deployed at a time. You can delete and modify unnecessary processes.
2. The corresponding table:
act_re_deployment: Deployment object table
act_re_procdef: Process Definition Table
act_ge_bytearray: resource file table
act_ge_property: Primary key generation policy table
Process Definition process definition
After parsing. bpmn, the information of process definition rules is obtained, and the workflow system is executed according to the rules of process definition.
Execution
Execute a process according to the rules defined in the process.
The corresponding table:
act_ru_execution: information being executed
act_hi_procinst: Executed historical process instance information
act_hi_actinst: Store all completed activities in history
Process Instance Process Example
Specially refers to the largest execution branch of a process from start to end. In an execution process, there is only one process instance.
Be careful
(1) If it is a singleton process, the execution object ID is the process instance ID.
(2) If a process has branching and aggregation, then the execution object ID and process instance ID are different.
(3) In a process, there is only one instance of the process, and there can be multiple execution objects.
Task task
Task information generated when performing a task link.
The corresponding table:
act_ru_task: Task information being executed
act_hi_taskinst: Information on completed historical tasks
public class ProcessDefinitionTest { ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); /**Deployment process definition (from classpath)*/ @Test public void deploymentProcessDefinition_classpath(){ Deployment deployment = processEngine.getRepositoryService()//Service related to process definition and deployment objects .createDeployment()//Create a deployment object .name("Process definition")//Add the name of the deployment .addClasspathResource("process/helloworld.bpmn")//Only one file can be loaded at a time from a classpath resource .addClasspathResource("process/helloworld.png")//Only one file can be loaded at a time from a classpath resource .deploy();//Complete deployment System.out.println("deploy ID: "+deployment.getId());// System.out.println("Deployment name:"+deployment.getName());// } /**Deployment process definition (from zip)*/ @Test public void deploymentProcessDefinition_zip(){ InputStream in = this.getClass().getClassLoader().getResourceAsStream("process/helloworld.zip"); ZipInputStream zipInputStream = new ZipInputStream(in); Deployment deployment = processEngine.getRepositoryService()//Service related to process definition and deployment objects .createDeployment()//Create a deployment object .name("Process definition")//Add the name of the deployment .addZipInputStream(zipInputStream)//Files in zip format are specified for deployment .deploy();//Complete deployment System.out.println("deploy ID: "+deployment.getId());// System.out.println("Deployment name:"+deployment.getName());// } /**Query process definition*/ @Test public void findProcessDefinition(){ List<ProcessDefinition> list = processEngine.getRepositoryService()//Service related to process definition and deployment objects .createProcessDefinitionQuery()//Create a process-defined query /**Specify query criteria, where criteria*/ // . deploymentId(deploymentId)// Query using deployment object ID // Process Definition Id (process Definition Id)// Use Process Definition ID Queries // Process Definition Key // Query using process defined key // Process Definition NameLike // Fuzzy Query with Process Definition NameLike // Name Definition /**sort*/ .orderByProcessDefinitionVersion().asc()//In ascending order of versions // OrderByProcess Definition Name (). desc ()// / in descending order by the name of the process definition /**Return result set*/ .list();//Returns a list of collections that encapsulate process definitions // singleResult();// Returns a unique result set // count();// Number of Result Sets Returned // ListPage (first Result, maxResults);//Paging query if(list!=null && list.size()>0){ for(ProcessDefinition pd:list){ System.out.println("Process definition ID:"+pd.getId());//key+Version+Random Generation Number of Process Definition System.out.println("Name of process definition:"+pd.getName());//The name attribute value in the corresponding helloworld.bpmn file System.out.println("Process-defined key:"+pd.getKey());//The id attribute values in the corresponding helloworld.bpmn file System.out.println("Version of process definition:"+pd.getVersion());//When the key value of the process definition is the same, version upgrade, default 1 System.out.println("Resource Name bpmn file:"+pd.getResourceName()); System.out.println("Resource Name png file:"+pd.getDiagramResourceName()); System.out.println("Deployment objects ID: "+pd.getDeploymentId()); System.out.println("#########################################################"); } } } /**Delete process definition*/ @Test public void deleteProcessDefinition(){ //Complete deletion using deployment ID String deploymentId = "601"; /** * Delete without cascade * Only processes that are not started can be deleted, and if the process is started, an exception will be thrown. */ // processEngine.getRepositoryService()// // .deleteDeployment(deploymentId); /** * cascading deletion * Whether or not the process is started, it can be deleted */ processEngine.getRepositoryService()// .deleteDeployment(deploymentId, true); System.out.println("Delete successfully!"); } /**View flow chart * @throws IOException */ @Test public void viewPic() throws IOException{ /**Put the generated image under the folder*/ String deploymentId = "801"; //Get the name of the image resource List<String> list = processEngine.getRepositoryService()// .getDeploymentResourceNames(deploymentId); //Define the name of the image resource String resourceName = ""; if(list!=null && list.size()>0){ for(String name:list){ if(name.indexOf(".png")>=0){ resourceName = name; } } } //Get the input stream of the picture InputStream in = processEngine.getRepositoryService()// .getResourceAsStream(deploymentId, resourceName); //Generate pictures into the directory of disk D File file = new File("D:/"+resourceName); //Write the picture of the input stream under the D disk FileUtils.copyInputStreamToFile(in, file); } /***Additional function: query the latest version of the process definition*/ @Test public void findLastVersionProcessDefinition(){ List<ProcessDefinition> list = processEngine.getRepositoryService()// .createProcessDefinitionQuery()// .orderByProcessDefinitionVersion().asc()//Use process-defined versions in ascending order .list(); /** * Map<String,ProcessDefinition> map Key of collection: key of process definition map value of collection: object defined by process map Characteristic of a set: When the key value of a map set is the same, the value of the latter will replace the value of the previous one. */ Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>(); if(list!=null && list.size()>0){ for(ProcessDefinition pd:list){ map.put(pd.getKey(), pd); } } List<ProcessDefinition> pdList = new ArrayList<ProcessDefinition>(map.values()); if(pdList!=null && pdList.size()>0){ for(ProcessDefinition pd:pdList){ System.out.println("Process definition ID:"+pd.getId());//key+Version+Random Generation Number of Process Definition System.out.println("Name of process definition:"+pd.getName());//The name attribute value in the corresponding helloworld.bpmn file System.out.println("Process-defined key:"+pd.getKey());//The id attribute values in the corresponding helloworld.bpmn file System.out.println("Version of process definition:"+pd.getVersion());//When the key value of the process definition is the same, version upgrade, default 1 System.out.println("Resource Name bpmn file:"+pd.getResourceName()); System.out.println("Resource Name png file:"+pd.getDiagramResourceName()); System.out.println("Deployment objects ID: "+pd.getDeploymentId()); System.out.println("#########################################################"); } } } /**Additional function: delete process definitions (delete all different versions of process definitions with the same key)*/ @Test public void deleteProcessDefinitionByKey(){ //key of process definition String processDefinitionKey = "helloworld"; //First, use the key defined by the process to query the process definition and find out all the versions. List<ProcessDefinition> list = processEngine.getRepositoryService()// .createProcessDefinitionQuery()// .processDefinitionKey(processDefinitionKey)//key queries using process definition .list(); //Traverse to get the deployment ID for each process definition if(list!=null && list.size()>0){ for(ProcessDefinition pd:list){ //Get the deployment ID String deploymentId = pd.getDeploymentId(); processEngine.getRepositoryService()// .deleteDeployment(deploymentId, true); } } } }