Flowable 与 bpmn.io@7.0 完整集成示例 Demo
Flowable 与 bpmn.io@7.0 完整集成示例 Demo
下面是一个完整的前后端集成示例,包含前端使用 bpmn.js 7.0 和与 Flowable 后端交互的实现。
1. 后端实现 (Spring Boot + Flowable)
1.1 添加依赖 (pom.xml)
<dependencies><!-- Spring Boot --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Flowable --><dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter</artifactId><version>6.7.0</version></dependency><!-- 其他必要依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
</dependencies>
1.2 应用配置 (application.yml)
server:port: 8080spring:datasource:url: jdbc:h2:mem:flowable;DB_CLOSE_DELAY=-1username: sapassword:driver-class-name: org.h2.Driverh2:console:enabled: truepath: /h2-consoleflowable:async-executor-activate: falsedatabase-schema-update: true
1.3 控制器 (FlowableController.java)
@RestController
@RequestMapping("/api")
public class FlowableController {@Autowiredprivate RepositoryService repositoryService;@Autowiredprivate RuntimeService runtimeService;// 部署流程@PostMapping("/deploy")public ResponseEntity<?> deployProcess(@RequestParam("file") MultipartFile file) {try {Deployment deployment = repositoryService.createDeployment().addBytes(file.getOriginalFilename(), file.getBytes()).deploy();return ResponseEntity.ok(Map.of("deploymentId", deployment.getId(),"deploymentName", deployment.getName(),"deploymentTime", deployment.getDeploymentTime()));} catch (Exception e) {return ResponseEntity.badRequest().body(e.getMessage());}}// 获取流程定义XML@GetMapping("/process-definition/{id}/xml")public ResponseEntity<?> getProcessDefinitionXml(@PathVariable String id) {try {ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());String xml = IOUtils.toString(resourceAsStream, StandardCharsets.UTF_8);return ResponseEntity.ok(xml);} catch (Exception e) {return ResponseEntity.badRequest().body(e.getMessage());}}// 获取流程定义列表@GetMapping("/process-definitions")public ResponseEntity<?> getProcessDefinitions() {List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().latestVersion().list();List<Map<String, Object>> result = processDefinitions.stream().map(pd -> Map.of("id", pd.getId(),"name", pd.getName(),"key", pd.getKey(),"version", pd.getVersion(),"deploymentId", pd.getDeploymentId())).collect(Collectors.toList());return ResponseEntity.ok(result);}
}
1.4 安全配置 (SecurityConfig.java)
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.cors().and().csrf().disable().authorizeRequests().antMatchers("/api/**").authenticated().and().httpBasic();}@BeanCorsConfigurationSource corsConfigurationSource() {CorsConfiguration configuration = new CorsConfiguration();configuration.setAllowedOrigins(Arrays.asList("*"));configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));configuration.setAllowedHeaders(Arrays.asList("*"));UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", configuration);return source;}
}
2. 前端实现 (React + bpmn.js)
2.1 项目初始化
npx create-react-app flowable-bpmn-demo
cd flowable-bpmn-demo
npm install bpmn-js@7.0.0 axios
2.2 BPMN 编辑器组件 (BpmnEditor.js)
import React, { useEffect, useRef, useState } from 'react';
import BpmnModeler from 'bpmn-js/lib/Modeler';
import 'bpmn-js/dist/assets/diagram-js.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
import axios from 'axios';
import './BpmnEditor.css';const BpmnEditor = () => {const containerRef = useRef(null);const modelerRef = useRef(null);const [processDefinitions, setProcessDefinitions] = useState([]);const [selectedDefinition, setSelectedDefinition] = useState(null);const [xml, setXml] = useState('');// 初始化建模器useEffect(() => {if (containerRef.current && !modelerRef.current) {modelerRef.current = new BpmnModeler({container: containerRef.current,keyboard: { bindTo: document }});// 创建新流程图createNewDiagram();}// 加载流程定义列表loadProcessDefinitions();return () => {if (modelerRef.current) {modelerRef.current.destroy();}};}, []);// 创建新流程图const createNewDiagram = async () => {try {const result = await modelerRef.current.createDiagram();console.log('Diagram created');} catch (err) {console.error('Could not create diagram', err);}};// 加载流程定义列表const loadProcessDefinitions = async () => {try {const response = await axios.get('http://localhost:8080/api/process-definitions', {auth: {username: 'admin',password: 'test'}});setProcessDefinitions(response.data);} catch (error) {console.error('Error loading process definitions:', error);}};// 加载特定流程定义const loadProcessDefinition = async (definitionId) => {try {const response = await axios.get(`http://localhost:8080/api/process-definition/${definitionId}/xml`,{auth: {username: 'admin',password: 'test'}});await modelerRef.current.importXML(response.data);setXml(response.data);setSelectedDefinition(definitionId);} catch (error) {console.error('Error loading process definition:', error);}};// 保存当前流程图const saveDiagram = async () => {try {const { xml } = await modelerRef.current.saveXML({ format: true });setXml(xml);const formData = new FormData();const blob = new Blob([xml], { type: 'text/xml' });formData.append('file', blob, 'process.bpmn');const response = await axios.post('http://localhost:8080/api/deploy', formData, {headers: {'Content-Type': 'multipart/form-data'},auth: {username: 'admin',password: 'test'}});alert(`Deployed successfully! Deployment ID: ${response.data.deploymentId}`);loadProcessDefinitions();} catch (error) {console.error('Error saving diagram:', error);}};return (<div className="bpmn-editor-container"><div className="toolbar"><button onClick={createNewDiagram}>New Diagram</button><button onClick={saveDiagram}>Save/Deploy</button><select value={selectedDefinition || ''}onChange={(e) => loadProcessDefinition(e.target.value)}><option value="">Load Process Definition</option>{processDefinitions.map((pd) => (<option key={pd.id} value={pd.id}>{pd.name || pd.key} (v{pd.version})</option>))}</select></div><div className="canvas" ref={containerRef}></div><div className="xml-viewer"><h3>BPMN XML</h3><textarea value={xml} onChange={(e) => setXml(e.target.value)}rows="20"/></div></div>);
};export default BpmnEditor;
2.3 样式文件 (BpmnEditor.css)
.bpmn-editor-container {display: flex;flex-direction: column;height: 100vh;
}.toolbar {padding: 10px;background: #f5f5f5;border-bottom: 1px solid #ddd;
}.toolbar button, .toolbar select {margin-right: 10px;padding: 5px 10px;
}.canvas {flex: 1;height: 60%;border: 1px solid #ccc;
}.xml-viewer {height: 30%;padding: 10px;border-top: 1px solid #ddd;
}.xml-viewer textarea {width: 100%;height: calc(100% - 30px);font-family: monospace;
}
2.4 主应用组件 (App.js)
import React from 'react';
import './App.css';
import BpmnEditor from './BpmnEditor';function App() {return (<div className="App"><header className="App-header"><h1>Flowable + bpmn.js Integration Demo</h1></header><main><BpmnEditor /></main></div>);
}export default App;
3. 运行说明
3.1 启动后端
- 启动 Spring Boot 应用
- Flowable 会自动创建必要的数据库表
- 后端将在
http://localhost:8080
运行
3.2 启动前端
- 运行
npm start
- 前端将在
http://localhost:3000
运行 - 使用默认凭据登录 (admin/test)
4. 功能说明
- 新建流程图:创建空白的 BPMN 流程图
- 保存/部署:将当前流程图保存并部署到 Flowable
- 加载流程:从 Flowable 加载已部署的流程定义
- XML 查看/编辑:查看和编辑 BPMN XML
5. 扩展建议
- 添加 Flowable 特定属性面板
- 集成 Flowable 表单设计器
- 添加流程实例启动和监控功能
- 实现更完善的用户认证和授权
这个完整示例展示了如何将 bpmn.js 7.0 与 Flowable 后端集成,实现流程建模、部署和管理的完整功能。