快捷搜索:  汽车  科技

springboot集成工作流引擎(Springboot整合Flowable实现工作流在线编辑)

springboot集成工作流引擎(Springboot整合Flowable实现工作流在线编辑)flowable-engine-flowable-6.4.0\modules\flowable-ui-modeler\flowable-ui-modeler-rest\src\main\java\org\flowable\ui\modeler\rest\app\StencilSetResource.java复制下面文件到Springboot项目中的自定义的conf目录,这个文件是Modeler汉化的组件,由于该类的实例会注入到Spring的容器中去,所以为了避免和原来的文件产生的bean冲突,需要重新命名,这里命名为FlowableStencilSetResource.java。复制下面两个文件到Springboot项目中的自定义的conf目录,这两个文件是启动中必要的配置文件,需要做修改,具体的修改在下面会有描述。flowable-engine-flowable-6.4.0\module

springboot集成工作流引擎(Springboot整合Flowable实现工作流在线编辑)(1)

1 项目准备1.1 新建一个Springboot项目

Springboot采用的版本是2.1.5.RELEASE;

Flowable采用的版本是6.4.0。

1.2 项目的pom文件

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.dream21th</groupId> <artifactId>flowable-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>flowable-demo</name> <description>Demo project for Spring Boot</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <mysql.version>5.1.38</mysql.version> <flowable.version>6.4.0</flowable.version> </properties> ​ <dependencies> <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-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-spring-boot-starter</artifactId> <version>${flowable.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.54</version> <scope>compile</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.flowable/flowable-ui-modeler-logic --> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-ui-modeler-logic</artifactId> <version>6.4.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.flowable/flowable-ui-modeler-conf --> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-ui-modeler-conf</artifactId> <version>6.4.0</version> </dependency> ​ </dependencies> ​ <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> ​ </project> ​1.3 Flowable Modeler UI下载

登录网址github,找到6.4.0版本,https://github.com/flowable/flowable-engine/tree/flowable-6.4.0,下载文件。

文件下载完成后,进入到flowable-engine-flowable-6.4.0\modules\flowable-ui-modeler\flowable-ui-modeler-app\src\main\resources\目录,将static文件夹下面的内容复制到Springboot项目resources资源下面的static目录下面。

2 后端代码2.1 复制代码

复制下面两个文件到Springboot项目中的自定义的conf目录,这两个文件是启动中必要的配置文件,需要做修改,具体的修改在下面会有描述。

flowable-engine-flowable-6.4.0\modules\flowable-ui-modeler\flowable-ui-modeler-conf\src\main\java\org\flowable\ui\modeler\conf\ApplicationConfiguration.java

flowable-engine-flowable-6.4.0\modules\flowable-ui-modeler\flowable-ui-modeler-conf\src\main\java\org\flowable\ui\modeler\servlet\AppDispatcherServletConfiguration.java

复制下面文件到Springboot项目中的自定义的conf目录,这个文件是Modeler汉化的组件,由于该类的实例会注入到Spring的容器中去,所以为了避免和原来的文件产生的bean冲突,需要重新命名,这里命名为FlowableStencilSetResource.java

flowable-engine-flowable-6.4.0\modules\flowable-ui-modeler\flowable-ui-modeler-rest\src\main\java\org\flowable\ui\modeler\rest\app\StencilSetResource.java

同时有两个配置文件需要复制到Springboot项目的resources路径下面,在resources下面新建目录stencilset。

这两个配置文件是stencilset_bpmn.json,stencilset_cmmn.json。

复制flowable-engine-flowable-6.4.0\modules\flowable-ui-common\src\main\java\org\flowable\ui\common\security\SecurityUtils.java到Springboot项目下面的org.flowable.ui.common.security包下面,注意这个文件必须放到和源文件相同的包目录下,所以在Springboot项目下会建一个org.flowable.ui.common.security包。

2.2 代码修改

ApplicationConfiguration修改为:

/* Licensed under the Apache License Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing software * distributed under the License is distributed on an "AS IS" BASIS * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.dream21th.flowable.demo.conf; ​ import org.flowable.ui.common.service.idm.RemoteIdmService; import org.flowable.ui.modeler.properties.FlowableModelerAppProperties; import org.flowable.ui.modeler.servlet.ApiDispatcherServletConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; ​ @Configuration @EnableConfigurationProperties(FlowableModelerAppProperties.class) @ComponentScan(basePackages = { // "org.flowable.ui.modeler.conf" "org.flowable.ui.modeler.repository" "org.flowable.ui.modeler.service" // "org.flowable.ui.modeler.security" //授权方面的都不需要 // "org.flowable.ui.common.conf" // flowable 开发环境内置的数据库连接 // "org.flowable.ui.common.filter" // IDM 方面的过滤器 "org.flowable.ui.common.service" "org.flowable.ui.common.repository" // // "org.flowable.ui.common.security" //授权方面的都不需要 "org.flowable.ui.common.tenant" } excludeFilters = { // 移除 RemoteIdmService @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE value = RemoteIdmService.class) } ) public class ApplicationConfiguration { ​ @Bean public ServletRegistrationBean modelerApiServlet(ApplicationContext applicationContext) { AnnotationConfigWebApplicationContext dispatcherServletConfiguration = new AnnotationConfigWebApplicationContext(); dispatcherServletConfiguration.setParent(applicationContext); dispatcherServletConfiguration.register(ApiDispatcherServletConfiguration.class); DispatcherServlet servlet = new DispatcherServlet(dispatcherServletConfiguration); ServletRegistrationBean registrationBean = new ServletRegistrationBean(servlet "/api/*"); registrationBean.setName("Flowable Modeler App API Servlet"); registrationBean.setLoadOnStartup(1); registrationBean.setAsyncSupported(true); return registrationBean; } } ​

AppDispatcherServletConfiguration修改为:

/* Licensed under the Apache License Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing software * distributed under the License is distributed on an "AS IS" BASIS * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.dream21th.flowable.demo.conf; ​ import org.flowable.ui.modeler.rest.app.EditorGroupsResource; import org.flowable.ui.modeler.rest.app.EditorUsersResource; import org.flowable.ui.modeler.rest.app.StencilSetResource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; import org.springframework.web.servlet.i18n.SessionLocaleResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; ​ @Configuration @ComponentScan(value = { "org.flowable.ui.modeler.rest.app" // 不加载 rest,因为 getAccount 接口需要我们自己实现 // "org.flowable.ui.common.rest" } excludeFilters = { // 移除 EditorUsersResource 与 EditorGroupsResource,因为不使用 IDM 部分 @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE value = EditorUsersResource.class) @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE value = EditorGroupsResource.class) // 配置文件用自己的 @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE value = StencilSetResource.class) } ) @EnableAsync public class AppDispatcherServletConfiguration implements WebMvcRegistrations { ​ private static final Logger LOGGER = LoggerFactory.getLogger(AppDispatcherServletConfiguration.class); ​ @Bean public SessionLocaleResolver localeResolver() { return new SessionLocaleResolver(); } ​ @Bean public LocaleChangeInterceptor localeChangeInterceptor() { LOGGER.debug("Configuring localeChangeInterceptor"); LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); localeChangeInterceptor.setParamName("language"); return localeChangeInterceptor; } ​ @Override public RequestMappingHandlerMapping getRequestMappingHandlerMapping() { LOGGER.debug("Creating requestMappingHandlerMapping"); RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping(); requestMappingHandlerMapping.setUseSuffixPatternMatch(false); requestMappingHandlerMapping.setRemoveSemicolonContent(false); Object[] interceptors = { localeChangeInterceptor() }; requestMappingHandlerMapping.setInterceptors(interceptors); return requestMappingHandlerMapping; } } ​

SecurityUtils修改为,目前是通过getCurrentUserObject方法获得一个固定用户。

/* Licensed under the Apache License Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing software * distributed under the License is distributed on an "AS IS" BASIS * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.flowable.ui.common.security; ​ import org.flowable.idm.api.User; import org.flowable.ui.common.model.RemoteUser; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; ​ import java.util.ArrayList; import java.util.List; ​ /** * Utility class for Spring Security. */ public class SecurityUtils { ​ private static User assumeUser; ​ private SecurityUtils() { } ​ /** * Get the login of the current user. */ public static String getCurrentUserId() { User user = getCurrentUserObject(); if (user != null) { return user.getId(); } return null; } ​ /** * @return the {@link User} object associated with the current logged in user. */ public static User getCurrentUserObject() { if (assumeUser != null) { return assumeUser; } ​ RemoteUser user = new RemoteUser(); user.setId("admin"); user.setDisplayName("Administrator"); user.setFirstName("Administrator"); user.setLastName("Administrator"); user.setEmail("admin@flowable.com"); user.setPassword("123456"); List<String> pris = new ArrayList<>(); pris.add(DefaultPrivileges.ACCESS_MODELER); pris.add(DefaultPrivileges.ACCESS_IDM); pris.add(DefaultPrivileges.ACCESS_ADMIN); pris.add(DefaultPrivileges.ACCESS_TASK); pris.add(DefaultPrivileges.ACCESS_REST_API); user.setPrivileges(pris); return user; } ​ public static FlowableAppUser getCurrentFlowableAppUser() { FlowableAppUser user = null; SecurityContext securityContext = SecurityContextHolder.getContext(); if (securityContext != null && securityContext.getAuthentication() != null) { Object principal = securityContext.getAuthentication().getPrincipal(); if (principal instanceof FlowableAppUser) { user = (FlowableAppUser) principal; } } return user; } ​ public static boolean currentUserHasCapability(String capability) { FlowableAppUser user = getCurrentFlowableAppUser(); for (GrantedAuthority grantedAuthority : user.getAuthorities()) { if (capability.equals(grantedAuthority.getAuthority())) { return true; } } return false; } ​ public static void assumeUser(User user) { assumeUser = user; } ​ public static void clearAssumeUser() { assumeUser = null; } ​ }2.3 新增代码

新增一个FlowableController 里面有一个接口/login/rest/account 目的是在加载页面时候会调用这个接口获取用户信息,由于我们绕过了登陆,因此给个默认的用户 admin。

package com.dream21th.flowable.demo.controller; ​ import org.flowable.ui.common.model.UserRepresentation; import org.flowable.ui.common.security.DefaultPrivileges; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; ​ ​ @RestController @RequestMapping("/login") public class FlowableController { ​ /** * 获取默认的管理员信息 * @return */ @RequestMapping(value = "/rest/account" method = RequestMethod.GET produces = "application/json") public UserRepresentation getAccount() { UserRepresentation userRepresentation = new UserRepresentation(); userRepresentation.setId("admin"); userRepresentation.setEmail("admin@flowable.org"); userRepresentation.setFullName("Administrator"); // userRepresentation.setLastName("Administrator"); userRepresentation.setFirstName("Administrator"); List<String> privileges = new ArrayList<>(); privileges.add(DefaultPrivileges.ACCESS_MODELER); privileges.add(DefaultPrivileges.ACCESS_IDM); privileges.add(DefaultPrivileges.ACCESS_ADMIN); privileges.add(DefaultPrivileges.ACCESS_TASK); privileges.add(DefaultPrivileges.ACCESS_REST_API); userRepresentation.setPrivileges(privileges); return userRepresentation; } } ​

修改resource\static\scripts\configuration\url-conf.js中的getAccountUrl中的地址修改为:

getAccountUrl: function () { return FLOWABLE.CONFIG.contextRoot '/login/rest/account'; }

修改Springboot启动类为:

package com.dream21th.flowable.demo; ​ import com.dream21th.flowable.demo.conf.AppDispatcherServletConfiguration; import com.dream21th.flowable.demo.conf.ApplicationConfiguration; import org.flowable.ui.modeler.conf.DatabaseConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration; import org.springframework.context.annotation.Import; ​ //启用全局异常拦截器 @Import(value={ // 引入修改的配置 ApplicationConfiguration.class AppDispatcherServletConfiguration.class // 引入 DatabaseConfiguration 表更新转换 DatabaseConfiguration.class}) // 移除 Security 自动配置 // Spring Cloud 为 Finchley 版本 // @SpringBootApplication(exclude={SecurityAutoConfiguration.class}) // Spring Cloud 为 Greenwich 版本 @SpringBootApplication(exclude={SecurityAutoConfiguration.class ManagementWebSecurityAutoConfiguration.class SecurityFilterAutoConfiguration.class}) public class FlowableDemoApplication{ ​ public static void main(String[] args) { SpringApplication.run(FlowableDemoApplication.class args); } ​ } ​

application.yml配置文件为:

server: port: 8989 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/test02?allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&nullCatalogMeansCurrent=true username: root password: root driver-class-name: com.mysql.jdbc.Driver ​ ​ flowable: async-executor-activate: false database-schema-update: false ​3 启动项目

springboot集成工作流引擎(Springboot整合Flowable实现工作流在线编辑)(2)

看到的流程图是导入进去的,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: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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test"> <collaboration id="Collaboration"> <participant id="pool1" name="披萨网络订单流程" processRef="pizza-online"></participant> </collaboration> <process id="PIZZA" name="披萨订单流程" isExecutable="true"> <startEvent id="startevent1" name="Start"></startEvent> </process> <process id="pizza-online" name="披萨电话订单流程" isExecutable="true"> <laneSet id="laneSet_pizza-online"> <lane id="lane1" name="接受订单"> <flowNodeRef>startevent1</flowNodeRef> <flowNodeRef>phone-resever</flowNodeRef> <flowNodeRef>assign-order</flowNodeRef> </lane> <lane id="lane2" name="制作披萨"> <flowNodeRef>prepare-pizza</flowNodeRef> <flowNodeRef>cook-pizza</flowNodeRef> <flowNodeRef>package-pizza</flowNodeRef> </lane> <lane id="lane3" name="快递收款"> <flowNodeRef>deliver-pizza</flowNodeRef> <flowNodeRef>recive-pay</flowNodeRef> <flowNodeRef>endevent1</flowNodeRef> </lane> </laneSet> <startEvent id="startevent1" name="Start"></startEvent> <userTask id="phone-resever" name="电话预定"></userTask> <userTask id="assign-order" name="分配订单"></userTask> <userTask id="prepare-pizza" name="准备披萨"></userTask> <userTask id="cook-pizza" name="烹饪披萨"></userTask> <userTask id="package-pizza" name="打包披萨"></userTask> <userTask id="deliver-pizza" name="快递披萨"></userTask> <serviceTask id="recive-pay" name="收到付款" activiti:class="com.study.demo.demo28.ServiceTaskClass"></serviceTask> <endEvent id="endevent1" name="End"></endEvent> <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="phone-resever"></sequenceFlow> <sequenceFlow id="flow2" sourceRef="phone-resever" targetRef="assign-order"></sequenceFlow> <sequenceFlow id="flow3" sourceRef="assign-order" targetRef="prepare-pizza"></sequenceFlow> <sequenceFlow id="flow4" sourceRef="prepare-pizza" targetRef="cook-pizza"></sequenceFlow> <sequenceFlow id="flow5" sourceRef="cook-pizza" targetRef="package-pizza"></sequenceFlow> <sequenceFlow id="flow6" sourceRef="package-pizza" targetRef="deliver-pizza"></sequenceFlow> <sequenceFlow id="flow7" sourceRef="deliver-pizza" targetRef="recive-pay"></sequenceFlow> <sequenceFlow id="flow8" sourceRef="recive-pay" targetRef="endevent1"></sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_Collaboration"> <bpmndi:BPMNPlane bpmnElement="Collaboration" id="BPMNPlane_Collaboration"> <bpmndi:BPMNShape bpmnElement="pool1" id="BPMNShape_pool1"> <omgdc:Bounds height="470.0" width="680.0" x="30.0" y="100.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="lane1" id="BPMNShape_lane1"> <omgdc:Bounds height="156.0" width="660.0" x="50.0" y="100.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="lane2" id="BPMNShape_lane2"> <omgdc:Bounds height="156.0" width="660.0" x="50.0" y="256.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="lane3" id="BPMNShape_lane3"> <omgdc:Bounds height="156.0" width="660.0" x="50.0" y="412.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1"> <omgdc:Bounds height="35.0" width="35.0" x="70.0" y="140.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="phone-resever" id="BPMNShape_phone-resever"> <omgdc:Bounds height="55.0" width="105.0" x="140.0" y="130.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="assign-order" id="BPMNShape_assign-order"> <omgdc:Bounds height="55.0" width="105.0" x="290.0" y="130.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="prepare-pizza" id="BPMNShape_prepare-pizza"> <omgdc:Bounds height="55.0" width="105.0" x="290.0" y="306.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="cook-pizza" id="BPMNShape_cook-pizza"> <omgdc:Bounds height="55.0" width="105.0" x="420.0" y="306.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="package-pizza" id="BPMNShape_package-pizza"> <omgdc:Bounds height="55.0" width="105.0" x="560.0" y="306.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="deliver-pizza" id="BPMNShape_deliver-pizza"> <omgdc:Bounds height="55.0" width="105.0" x="560.0" y="462.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="recive-pay" id="BPMNShape_recive-pay"> <omgdc:Bounds height="55.0" width="105.0" x="430.0" y="462.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"> <omgdc:Bounds height="35.0" width="35.0" x="140.0" y="472.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"> <omgdi:waypoint x="105.0" y="157.0"></omgdi:waypoint> <omgdi:waypoint x="140.0" y="157.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"> <omgdi:waypoint x="245.0" y="157.0"></omgdi:waypoint> <omgdi:waypoint x="290.0" y="157.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3"> <omgdi:waypoint x="342.0" y="185.0"></omgdi:waypoint> <omgdi:waypoint x="342.0" y="306.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4"> <omgdi:waypoint x="395.0" y="333.0"></omgdi:waypoint> <omgdi:waypoint x="420.0" y="333.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5"> <omgdi:waypoint x="525.0" y="333.0"></omgdi:waypoint> <omgdi:waypoint x="560.0" y="333.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6"> <omgdi:waypoint x="612.0" y="361.0"></omgdi:waypoint> <omgdi:waypoint x="612.0" y="462.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7"> <omgdi:waypoint x="560.0" y="489.0"></omgdi:waypoint> <omgdi:waypoint x="535.0" y="489.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8"> <omgdi:waypoint x="430.0" y="489.0"></omgdi:waypoint> <omgdi:waypoint x="175.0" y="489.0"></omgdi:waypoint> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>

项目结构:

springboot集成工作流引擎(Springboot整合Flowable实现工作流在线编辑)(3)

项目结构

码云地址:https://gitee.com/dream21th/flowbale-demo

猜您喜欢: