Flowable BPMN 简单使用

匿名 (未验证) 提交于 2019-12-02 23:30:02

1.Flowable是什么?

Flowable是一个使用Java编写的轻量级业务流程引擎。Flowable流程引擎可用于部署BPMN 2.0流程定义(用于定义流程的行业XML标准), 创建这些流程定义的流程实例,进行查询,访问运行中或历史的流程实例与相关数据,等等。这个章节将用一个可以在你自己的开发环境中使用的例子,逐步介绍各种概念与API。

Flowable可以十分灵活地加入你的应用/服务/构架。可以将JAR形式发布的Flowable库加入应用或服务,来嵌入引擎。 以JAR形式发布使Flowable可以轻易加入任何Java环境:Java SE;Tomcat、Jetty或Spring之类的servlet容器;JBoss或WebSphere之类的Java EE服务器,等等。 另外,也可以使用Flowable REST API进行HTTP调用。也有许多Flowable应用(Flowable Modeler, Flowable Admin, Flowable IDM 与 Flowable Task),提供了直接可用的UI示例,可以使用流程与任务。

所有使用Flowable方法的共同点是核心引擎。核心引擎是一组服务的集合,并提供管理与执行业务流程的API。 下面的教程从设置与使用核心引擎的介绍开始。后续章节都建立在之前章节中获取的知识之上。

2. Flowable与Activiti

Flowable是Activiti(Alfresco持有的注册商标)的fork。在下面的章节中,你会注意到包名,配置文件等等,都使用flowable

3.项目中简单使用

import com.ilotterytech.component.flowable.utils.FlowDefineUtils; import junit.framework.TestCase; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.ExtensionElement; import org.flowable.bpmn.model.StartEvent; import org.flowable.bpmn.model.UserTask; import org.flowable.engine.*; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.impl.cfg.StandaloneProcessEngineConfiguration; import org.flowable.engine.parse.BpmnParseHandler; import org.flowable.engine.repository.Deployment; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.image.impl.DefaultProcessDiagramGenerator; import org.flowable.task.api.Task; import org.flowable.task.api.history.HistoricTaskInstance;  import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.*;  /**  * Created by Zhang on 2018/11/30.  */ public class FlowableTest extends TestCase {     private StandaloneProcessEngineConfiguration cfg;     private ProcessEngine processEngine;      @Override     protected void setUp() throws Exception {         super.setUp();          cfg = new StandaloneProcessEngineConfiguration();         cfg.setJdbcUrl("jdbc:mysql://192.168.110.2:3306/bwlbis?useSSL=false")                 .setJdbcUsername("bwlbis")                 .setJdbcPassword("bwlbis1234")                 .setJdbcDriver("com.mysql.jdbc.Driver")                 .setDatabaseType(ProcessEngineConfiguration.DATABASE_TYPE_MYSQL)                 .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);          List<BpmnParseHandler> handlers = new ArrayList<>();         //handlers.add(new ExtensionUserTaskParseHandler());         //cfg.setCustomDefaultBpmnParseHandlers(handlers);          processEngine = cfg.buildProcessEngine();     }      public void testDeploy(){         RepositoryService repositoryService = processEngine.getRepositoryService();          Deployment deployment = repositoryService.createDeployment()                 .addClasspathResource("bpmn/stationFee.bpmn20.xml")                 .deploy();     }      public void testQueryDeploy() throws IOException{         RepositoryService repositoryService = processEngine.getRepositoryService();          ProcessDefinition define = repositoryService.createProcessDefinitionQuery()                 .processDefinitionKey("holidayRequest")                 .singleResult();          BpmnModel model = repositoryService.getBpmnModel(define.getId());         List<UserTask> list = model.getMainProcess().findFlowElementsOfType(UserTask.class);         UserTask task = list.get(0);         ExtensionElement ee = task.getExtensionElements().get("page").get(0);         System.out.println(ee.getAttributes());         System.out.println(ee.getAttributeValue(null, "name"));          System.out.println("Found process definition : " + define.getDiagramResourceName());          List<StartEvent> events = model.getMainProcess().findFlowElementsOfType(StartEvent.class);         StartEvent se = events.get(0);         ee = se.getExtensionElements().get("page").get(0);         System.out.println(ee.getAttributes());         System.out.println(ee.getAttributeValue(null, "name"));          ee = se.getExtensionElements().get("service").get(0);         List<ExtensionElement> ext = ee.getChildElements().get("invoke");         ext.forEach(e ->{             System.out.println(e.getElementText());         });          String value = FlowDefineUtils.getStartEventExtensionAttributeValue(define, "page", "name", repositoryService);         System.out.println(value);     }      public void testStart(){         RepositoryService repositoryService = processEngine.getRepositoryService();          ProcessDefinition define =repositoryService.createProcessDefinitionQuery()                 .processDefinitionKey("holidayRequest")                 .singleResult();          System.out.println("Found process definition : " + define.getName());          RuntimeService runtimeService = processEngine.getRuntimeService();         Map<String, Object> variables = new HashMap<>();         variables.put("employee", "test");         variables.put("nrOfHolidays", 5);         variables.put("description", "年假");          ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayRequest", variables);          System.out.println("start up flow [" + processInstance.getId() + "]");     }      public void testQueryTask(){         RepositoryService repositoryService = processEngine.getRepositoryService();          TaskService taskService = processEngine.getTaskService();         List<Task> tasks = taskService.createTaskQuery()                 .or()                 .taskAssignee("10")                 .taskCandidateGroup("managers")                 .endOr()                 .list();         System.out.println("你有 " + tasks.size() + " 个待办任务:");         for (int i = 0; i < tasks.size(); i++) {             Task t = tasks.get(i);             System.out.println(t.getClass());             Map<String, Object> processVariables = taskService.getVariables(t.getId());             System.out.println(String.format("%d) %s : %s - %s - %s - %s - %s", i + 1, t.getName(), t.getId(), t.getAssignee(), t.getCategory(), t.getCreateTime(), processVariables.get("employee")));         }     }      public void testSubmitTask(){         TaskService taskService = processEngine.getTaskService();         List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();         System.out.println("你有 " + tasks.size() + " 个待办任务:");         Task task = tasks.get(0);          Map<String, Object> variables = new HashMap<String, Object>();         variables.put("approved", true);         taskService.complete(task.getId(), variables);     }      public void testExportProcessImg() throws IOException{         HistoryService historyService = processEngine.getHistoryService();         RepositoryService repositoryService = processEngine.getRepositoryService();         RuntimeService runtimeService = processEngine.getRuntimeService();          List<HistoricProcessInstance> his = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("holidayRequest").list();         for (HistoricProcessInstance ins : his){             System.out.println(String.format("%s : %s", ins.getId(), ins.getDurationInMillis()));         }          HistoricProcessInstance instance = his.get(0);         BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());         DefaultProcessDiagramGenerator defaultProcessDiagramGenerator = new DefaultProcessDiagramGenerator();          List<String> highLightedActivities = runtimeService.getActiveActivityIds(instance.getId());          List<String> highLightedFlows = Collections.emptyList();          InputStream in = defaultProcessDiagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivities, highLightedFlows, false);          byte[] data = IOUtils.toByteArray(in);          FileUtils.writeByteArrayToFile(new File("img.png"), data);     }      public void testQueryHisProcess() throws IOException{         HistoryService historyService = processEngine.getHistoryService();         RepositoryService repositoryService = processEngine.getRepositoryService();         RuntimeService runtimeService = processEngine.getRuntimeService();          List<HistoricTaskInstance> list = historyService                 .createHistoricTaskInstanceQuery()                 //.processDefinitionKey("holidayRequest")                 .processInstanceId("2501")                 .finished()                 .list();          for (HistoricTaskInstance ins : list){             System.out.println(String.format("%s : %s, %s, %s", ins.getId(), ins.getCreateTime(), ins.getEndTime(), ins.getAssignee()));         }     }       public void testDefineUtils() throws Exception{         RepositoryService service = processEngine.getRepositoryService();          ProcessDefinition define = FlowDefineUtils.getFlowDefine("holidayRequest", service);         System.out.println(FlowDefineUtils.getStartEventVariables(define, service));         System.out.println(FlowDefineUtils.getUserTaskVariables(define, "approveTask", service));          System.out.println(FlowDefineUtils.getStartEventService(define, service));         System.out.println(FlowDefineUtils.getUserTaskService(define, "approveTask", service));          System.out.println(FlowDefineUtils.getStartEventInitService(define, service));         System.out.println(FlowDefineUtils.getUserTaskInitService(define, "approveTask", service));     } }

3.修改****.bpmn20.xml

<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"              xmlns:xsd="http://www.w3.org/2001/XMLSchema"              xmlns:flowable="http://flowable.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:ilot="http://ilotterytech.com/bpmn"              typeLanguage="http://www.w3.org/2001/XMLSchema"              expressionLanguage="http://www.w3.org/1999/XPath"              targetNamespace="http://flowable.org/test">   <!--<collaboration id="Collaboration">-->   <!--<participant id="sid-FCF94A2B-138F-406B-BA6C-2860A5329290" name="银行对账文件流程" processRef="process"></participant>-->   <!--</collaboration>-->   <process id="stationFee" name="网点保险费流程" isExecutable="true">     <extensionElements>       <flowable:eventListener delegateExpression="${flowableMainEventListener}" events="TASK_COMPLETED,PROCESS_COMPLETED" />     </extensionElements>     <laneSet id="laneSet_process">       <lane id="sid-FF8E9FD8-1C1B-4E2D-98BC-A083D4E947D1" name="市场(营销)管理部→技术管理部">         <flowNodeRef>sid-0AA904C1-154A-43E8-B17D-1445DDD5A58B</flowNodeRef>         <flowNodeRef>sid-5342E247-1EF8-413A-A28D-6AA281753F76</flowNodeRef>         <flowNodeRef>sid-EFECD6EF-42DA-4AD5-AF28-36183BD182B1</flowNodeRef>         <flowNodeRef>sid-946F88C4-6C74-494E-B27A-2490CF613F62</flowNodeRef>         <flowNodeRef>sid-3EABB94F-3180-42F0-AAC7-84BDDBC16BC3</flowNodeRef>       </lane>     </laneSet>     <startEvent id="sid-0AA904C1-154A-43E8-B17D-1445DDD5A58B" name="导入网点保险费列表">       <extensionElements>         <ilot:init service="insuranceFeeService.getStartInitEvent" />         <ilot:page name="startBank.html" route="startCheckAccount.financeStartCheck"/>         <ilot:service form="InsurancePremiumForm" invoke="insuranceFeeService.saveInsuranceFee" />       </extensionElements>     </startEvent>     <userTask id="sid-5342E247-1EF8-413A-A28D-6AA281753F76" name="主机系统处理" flowable:candidateGroups="技术管理部">       <extensionElements>         <ilot:init service="insuranceFeeService.getHostProcessing" />         <ilot:page name="start.html" route="operCheckAccount.financeOperCheck"/>         <ilot:service form="InsurancePremiumHostForm" invoke="insuranceFeeService.saveHostProcessingSubmit" />       </extensionElements>     </userTask>     <endEvent id="sid-EFECD6EF-42DA-4AD5-AF28-36183BD182B1"></endEvent>     <sequenceFlow id="sid-946F88C4-6C74-494E-B27A-2490CF613F62" sourceRef="sid-5342E247-1EF8-413A-A28D-6AA281753F76" targetRef="sid-EFECD6EF-42DA-4AD5-AF28-36183BD182B1"></sequenceFlow>     <sequenceFlow id="sid-3EABB94F-3180-42F0-AAC7-84BDDBC16BC3" sourceRef="sid-0AA904C1-154A-43E8-B17D-1445DDD5A58B" targetRef="sid-5342E247-1EF8-413A-A28D-6AA281753F76"></sequenceFlow>   </process>   <bpmndi:BPMNDiagram id="BPMNDiagram_Collaboration">     <bpmndi:BPMNPlane bpmnElement="Collaboration" id="BPMNPlane_Collaboration">       <bpmndi:BPMNShape bpmnElement="sid-6465C1B4-6357-4329-AD60-1FCAF7F68DA4" id="BPMNShape_sid-6465C1B4-6357-4329-AD60-1FCAF7F68DA4">         <omgdc:Bounds height="249.0" width="937.8" x="0.0" y="15.0"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNShape bpmnElement="sid-FF8E9FD8-1C1B-4E2D-98BC-A083D4E947D1" id="BPMNShape_sid-FF8E9FD8-1C1B-4E2D-98BC-A083D4E947D1">         <omgdc:Bounds height="249.0" width="907.8" x="30.0" y="15.0"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNShape bpmnElement="sid-0AA904C1-154A-43E8-B17D-1445DDD5A58B" id="BPMNShape_sid-0AA904C1-154A-43E8-B17D-1445DDD5A58B">         <omgdc:Bounds height="30.0" width="30.0" x="90.0" y="124.5"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNShape bpmnElement="sid-5342E247-1EF8-413A-A28D-6AA281753F76" id="BPMNShape_sid-5342E247-1EF8-413A-A28D-6AA281753F76">         <omgdc:Bounds height="80.0" width="100.0" x="495.0" y="99.5"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNShape bpmnElement="sid-EFECD6EF-42DA-4AD5-AF28-36183BD182B1" id="BPMNShape_sid-EFECD6EF-42DA-4AD5-AF28-36183BD182B1">         <omgdc:Bounds height="28.0" width="28.0" x="706.8" y="125.5"></omgdc:Bounds>       </bpmndi:BPMNShape>       <bpmndi:BPMNEdge bpmnElement="sid-946F88C4-6C74-494E-B27A-2490CF613F62" id="BPMNEdge_sid-946F88C4-6C74-494E-B27A-2490CF613F62">         <omgdi:waypoint x="594.9499999999894" y="139.5"></omgdi:waypoint>         <omgdi:waypoint x="706.8" y="139.5"></omgdi:waypoint>       </bpmndi:BPMNEdge>       <bpmndi:BPMNEdge bpmnElement="sid-3EABB94F-3180-42F0-AAC7-84BDDBC16BC3" id="BPMNEdge_sid-3EABB94F-3180-42F0-AAC7-84BDDBC16BC3">         <omgdi:waypoint x="119.94999990555667" y="139.5"></omgdi:waypoint>         <omgdi:waypoint x="494.999999999622" y="139.5"></omgdi:waypoint>       </bpmndi:BPMNEdge>     </bpmndi:BPMNPlane>   </bpmndi:BPMNDiagram> </definitions>

4.书写相应的entity , form , service,repository

package com.ilotterytech.bwlbis.station.insurance.entity;  import com.ilotterytech.common.core.entity.UseableEntity; import lombok.Getter; import lombok.Setter;  import javax.persistence.*; import java.sql.Timestamp;  /**  * @ Author : zhukaixin  * @ Date : 2019-04-28-16:05  * @ Desc :  */ @Setter @Getter @Entity @Table( name ="w_station_insurance_premium" ) public class InsurancePremium extends UseableEntity {      /**      * id主键      */     @Id     @GeneratedValue     @Column(name = "id" )     private Long id;       /**      *  时间      */     @Column(name = "date" )     private Timestamp date;     /**      *  保险费      */ //    @Column(name = "money" ) //    private int money;     /**      * 备注      */     @Column(name = "remark" )     private String remark;      /**      * station_code      */ //    @Column(name = "station_code" ) //    private String stationCode;      /**      * dept      */     @Column(name = "dept" )     private Long dept;     /**      * proc_instance_id      */     @Column(name = "proc_instance_id" )     private String procInstanceId;  }
package com.ilotterytech.bwlbis.station.insurance.form;  import com.ilotterytech.bwlbis.flowable.entity.FlowStartForm; import com.ilotterytech.component.flowable.form.FlowableVariableFormBase; import lombok.Data;  /**  * @ Author : zhukaixin  * @ Date : 2019-04-28-16:47  * @ Desc :  */ @Data public class InsurancePremiumForm extends FlowableVariableFormBase implements FlowStartForm {      private Long file;      /**      *  备注      */     private String remark;      @Override     public String getTargetSiteName() {         return null;     }      @Override     public String getTargetSiteCode() {         return null;     }      @Override     public String getTargetAddress() {         return null;     }      @Override     public String getCategory() {         return "网点保险费";     } }
package com.ilotterytech.bwlbis.station.insurance.form;  import com.ilotterytech.component.flowable.form.FlowableVariableFormBase; import lombok.Data;  /**  * @ Author : zhukaixin  * @ Date : 2019-04-28-19:17  * @ Desc :  */ @Data public class InsurancePremiumHostForm extends FlowableVariableFormBase {     /**      *  备注      */     private String remark;      private Long insurancePremiumId;      /**      * 确认主机操作      */     private Boolean sureFlag; }

package com.ilotterytech.bwlbis.station.insurance.repository;  import com.ilotterytech.bwlbis.station.insurance.entity.InsurancePremium; import com.ilotterytech.framework.rest.repository.RestRepository; import org.springframework.stereotype.Repository;  /**  * @ Author : zhukaixin  * @ Date : 2019-04-28-16:07  * @ Desc :  */ @Repository public  interface InsurancePremiumRepository extends RestRepository<InsurancePremium, Long> {      InsurancePremium getByProcInstanceId(String procInstanceId);   }
package com.ilotterytech.bwlbis.station.insurance.service;  import com.ilotterytech.bwlbis.base.attach.entity.Attach; import com.ilotterytech.bwlbis.base.attach.service.AttachService; import com.ilotterytech.bwlbis.base.hostsure.entity.HostSure; import com.ilotterytech.bwlbis.base.hostsure.service.HostSureService; import com.ilotterytech.bwlbis.station.insurance.entity.InsurancePremium; import com.ilotterytech.bwlbis.station.insurance.form.InsurancePremiumForm; import com.ilotterytech.bwlbis.station.insurance.form.InsurancePremiumHostForm; import com.ilotterytech.bwlbis.station.insurance.repository.InsurancePremiumRepository; import com.ilotterytech.component.flowable.entity.FlowableEntity; import com.ilotterytech.component.flowable.service.FlowableTaskService; import com.ilotterytech.component.flowable.service.ServiceInvokeContext; import com.ilotterytech.framework.rest.service.DefaultRestService; import org.apache.commons.collections.map.HashedMap; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;  import javax.annotation.Resource; import java.util.HashMap; import java.util.List; import java.util.Map;  /**  * @ Author : zhukaixin  * @ Date : 2019-04-28-15:55  * @ Desc :  */ @Service @Transactional public class InsuranceFeeService extends DefaultRestService<InsurancePremium, Long, InsurancePremiumRepository> implements FlowableTaskService {      @Resource     private AttachService attachService;     @Resource     private HostSureService hostSureService;     /**      * 初始化页面      */     public Map<String,Object> getStartInitEvent(ServiceInvokeContext context){          Map<String,Object> map= new HashedMap();        map.put("person",context.getUserId());        map.put("dept",context.getUserDeptId());          return map;      }      /**      * 提交修改      * @param entity      * @param context      */     public void saveInsuranceFee(FlowableEntity entity, ServiceInvokeContext context){           InsurancePremiumForm insurancePremiumForm = (InsurancePremiumForm)context.getPageForm();         InsurancePremium insurancePremium = new InsurancePremium();          Attach attach = attachService.findOne(insurancePremiumForm.getFile());         BeanUtils.copyProperties(insurancePremiumForm,insurancePremium);         insurancePremium.setProcInstanceId(context.getProcessInstanceId());         insurancePremium.setDept(context.getUserDeptId());         insurancePremium.setRemark(insurancePremiumForm.getRemark());         repository.save(insurancePremium);         attach.setFId(insurancePremium.getId());         attach.setFType(InsurancePremium.class.getSimpleName());         attachService.save(attach);      }      /**      * 技术部主机处理      */     public Map<String,Object> getHostProcessing(FlowableEntity entity, ServiceInvokeContext context){         InsurancePremium insurancePremium = repository.getByProcInstanceId(entity.getProcInstanceId());         List<Attach>  attach = attachService.getAttachByFidAndFType(insurancePremium.getId(),InsurancePremium.class);         Map<String,Object> map = new HashMap<>();         map.put("insurancePremium",insurancePremium);         map.put("attach",attach);          return map;      }      /**      *      * 技术部主机处理提交修改      * @param entity      * @param context      */     public void saveHostProcessingSubmit(FlowableEntity entity, ServiceInvokeContext context){          InsurancePremiumHostForm insurancePremiumsForm = (InsurancePremiumHostForm)context.getPageForm();          InsurancePremium insurancePremium = repository.findOne(insurancePremiumsForm.getInsurancePremiumId());         HostSure hostSure = new HostSure();         BeanUtils.copyProperties(insurancePremiumsForm,hostSure);         hostSure.setProcInstanceId(context.getProcessInstanceId());          hostSure.setSid(insurancePremium.getId());         hostSure.setStype(InsurancePremium.class.getSimpleName());         hostSureService.saveHostSure(hostSure);      }  }

5.根据service中的方法写相应的流程顺序

6.修改****.bpmn20.xml 每次修改都要重新修改数据库中的对应表数据

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!