news 2026/10/21 18:56:23

Spring Boot集成Flowable Modeler流程设计器完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot集成Flowable Modeler流程设计器完整指南

最近在做一个内部审批系统升级,核心工作就是把Flowable的Modeler流程设计器界面化,嵌进现有的Spring Boot项目里,让业务人员直接在浏览器画审批流。文章以Spring Boot 2.7.x和Flowable 6.7.2为基准,讲清楚模块拆分、静态资源整合、安全上下文处理这些关键点,以及我在这套集成中踩过的坑。如果你正在做OA、工单流转这类系统,看完应该能少走不少弯路。

1. 项目背景与方案选型

1.1 团队现状与界面化诉求

接手这个需求之前,项目里的流程定义基本都是开发手工写BPMN XML,写到resources/processes目录下,引擎启动时自动部署。看起来挺顺,但实际维护起来非常痛苦:产品经理改一句审批条件,开发要先找到对应XML节点,改完再发一版;流程图稍微复杂一点,sequenceFlow、conditionExpression这些节点在文本里根本看不出逻辑关系;等流程数量超过20个,不要说产品,连开发自己都容易搞混。

所以"界面化"这个需求本质上不是要一个炫酷的画图工具,而是要解决三个具体问题:

  • 业务同学能自己拖拽节点、配置连线条件,不用每改一次流程就找开发提工单。
  • 开发能看到与线上流程定义一模一样的模型,而不是维护一份和代码脱节的文档。
  • 设计器要集成在现有管理系统里,用户点个菜单就能用,而不是再开一个8009端口的独立页面。

1.2 三条技术路线怎么选

当时团队里讨论过三条路。

第一条,单独部署一套Flowable官方UI。优点是安装简单,官方war包丢到Tomcat就能跑,modeler功能完整;缺点也明显:它自带登录、自带用户体系,跟我们业务系统的账号体系和菜单权限完全是两套,体验割裂。就算用反向代理和单点登录硬接,后面每次升级都要操心两边配置同步,心态容易崩。

第二条,不用官方UI,继续写XML或用IDEA插件生成。这条对开发来说其实可行,BPMN插件画完导出XML再放到工程里,也能跑。但它是把问题留给了"开发当翻译",业务人员依然只能看截图,看不了真实模型,更没法自己改。

第三条,Spring Boot工程里直接嵌入modeler模块,前端静态资源平移到项目里,后端复用Flowable官方modeler-rest接口。这条路最贴近业务系统本身:用原有菜单进入,用原有登录态,模型数据还落在同一个数据库里,后续做权限控制、一键部署都方便。

方案定了,细节问题就来了。首当其冲的是:Flowable UI到底有哪些模块,哪些该带走,哪些该扔掉。

2. 核心思路与模块拆解

2.1 Flowable UI的模块构成与取舍

Flowable官方UI在6.x版本里其实是个多模块Spring Boot应用,主要由四块组成:

模块职责本次是否嵌入
modeler在线BPMN流程设计器,负责画图、保存模型嵌入
task任务工作台,处理待办、已办不嵌入,业务系统已有审批页
admin系统管理,管理用户、租户、数据源不嵌入
idm身份管理和登录认证不嵌入,但要参考它的用户上下文实现

如果图省事把整个flowable-ui作为依赖引进来,项目里会多出一整套登录跳转和路由逻辑,跟现有系统打架的概率极高。真正需要的就是modeler这一块,外加它依赖的common基础模块。task和admin,你们如果也是做业务系统,大概率不需要。

2.2 嵌入方案的思路演进

一开始我试过最直接的办法:拿到flowable-ui的war包,把整个工程结构照搬进Spring Boot项目,启动类、自动配置都留着。结果启动后系统里同时出现两套安全配置,一套是我们自己的登录拦截,一套是Flowable自带的登录页,访问哪个接口都可能被跳转,光排查过滤器顺序就花了一整天。

后来换了个思路:既然Flowable UI本身也是Spring Boot应用,它的前端是纯静态资源,后端接口是通过flowable-ui-modeler-rest这个模块暴露的,那我为什么不能只取这两样?

最终方案分成两条线:

  • 前端:从官方war包里抽出modeler.html和对应的scripts/styles目录,放到Spring Boot静态资源目录,用ResourceHandler映射。
  • 后端:引入modeler-rest和common相关依赖,让官方Controller直接注册到当前Spring容器里,数据库仍是引擎那套ACT_表。

这样的好处是"只借器官,不用借身体":页面是我们系统的页面,登录是我们系统的登录,用户是我们系统的用户,但画图、保存模型还是官方原装逻辑,升级时只要替换前端资源和依赖版本即可。

2.3 modeler后端接口和数据结构

在动手配置之前,建议先搞清楚modeler的接口长什么样。以6.7.2为例,前端页面里JavaScript发起的请求主要走这几个前缀:

  • /modeler/service/editor/stencilset:获取元件定义,相当于设计器里的元素素材库。
  • /modeler/service/editor/load:根据模型ID加载BPMN JSON和图片。
  • /modeler/service/editor/save:保存模型,把画布上的节点、连线、条件表达式序列化成JSON,再转为BPMN XML。
  • /modeler/service/rest/models:模型列表,负责首页展示和管理。
  • /app/rest/authenticate:认证入口,如果不想用Flowable自己的登录,这个接口可以绕过。

这些接口操作的核心表是ACT_RE_MODEL,模型数据以JSON和XML两种形态分别存在editor_source_extra和editor_source字段里。换句话说,设计器负责编辑模型,流程引擎负责部署模型,两者不是一回事。很多同学嵌入成功后,在画布里画了图保存了,但业务跑不起来,就是因为漏掉了"部署"这一步,后文我会专门说。

3. 实操落地步骤

3.1 版本选择与依赖引入

版本组合是稳定性的第一道关。如果是老项目升级改造,我建议优先选Spring Boot 2.7.x + Flowable 6.7.2这套组合,网上踩坑记录多,遇到问题容易搜到解决方案。Spring Boot 3.x用户建议直接上Flowable 7.x或更高版本,但modeler前端改版较大,配置方式会有差异,别硬套。

pom里需要加五类东西,引擎starter、modeler-rest、modeler-logic,以及common-rest和common-logic。实际引入时,modeler-rest的传递依赖会帮你把common带进来,但显式写上版本号更稳妥,也能避免Maven依赖仲裁时拉到奇怪版本。

<dependency> <groupId>org.flowable</groupId> <artifactId>flowable-spring-boot-starter</artifactId> <version>6.7.2</version> </dependency> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-ui-modeler-rest</artifactId> <version>6.7.2</version> </dependency> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-ui-modeler-logic</artifactId> <version>6.7.2</version> </dependency> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-ui-common-rest</artifactId> <version>6.7.2</version> </dependency> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-ui-common-logic</artifactId> <version>6.7.2</version> </dependency>

这里有个关键前提:确保flowable-spring-boot-starter和flowable-ui-*的版本完全一致。版本不一致时,设计器生成XML里的命名空间和引擎解析规则可能对不上,最容易出现的bug就是"保存成功但部署时解析报错"。

3.2 前端资源提取与放置

前端资源不宜自己从零写,直接把官方编译好的产物搬过来最省心。去Flowable官方下载对应版本的flowable-ui压缩包,里面有个flowable-ui.war,本质是个zip,直接解压。

解压后找到静态资源目录,在6.7.2版本里一般在WEB-INF/classes/static下。我们关心的文件是modeler.html和它配套的脚本目录,常见的目录名是modeler,里面放着app.js、components等前端代码。

命令行操作大致是这个思路:

unzip flowable-ui-6.7.2.war -d flowable-ui-war cp -r flowable-ui-war/WEB-INF/classes/static/modeler.html src/main/resources/static/modeler.html cp -r flowable-ui-war/WEB-INF/classes/static/modeler src/main/resources/static/modeler/

我实际操作时是保留官方目录结构的,也就是说把modeler.html和modeler目录都放在static根下面。这样做的原因是modeler.html里对脚本的引用大多是相对路径,比如modeler/scripts/app.js,目录结构不变,路径引用的坑就少很多。

3.3 静态资源映射配置

Spring Boot默认会把static目录下的内容直接映射到根路径,理论上访问http://localhost:8080/modeler.html就能打开页面。但实际项目里往往有多套静态资源,还有 context-path、网关转发,所以最好显式声明一段资源映射,保证/modeler/**这类路径不会被其他拦截器误伤。

@Configuration public class ModelerWebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/modeler/**") .addResourceLocations("classpath:/static/modeler/") .setCachePeriod(3600); } }

如果你的modeler.html是放在static根目录而不是modeler子目录,那modeler.html本身由Spring Boot默认静态资源规则处理即可,不需要额外配置。但页面要调的后端接口路径是以/modeler/service/开头的,这一类请求走的是Controller,不走资源映射,所以前端资源映射和后端接口映射是不冲突的。

提示:如果项目配了server.servlet.context-path,所有路径都会带上上下文前缀。此时要确认前端资源引用的路径里是否包含context-path,如果前端写死了根路径引用,就要在Gateway或Nginx层做一下重写,否则会出现"HTML能打开、JS全部404"的经典事故。

3.4 安全过滤链与模拟用户

后端接口和前端资源都就位后,真正让人头疼的安全问题才浮出水面。modeler-rest内部很多操作要拿当前登录用户信息,比如保存模型时要记录"创建人",模型列表里要显示"由谁创建"。它默认从Spring Security上下文里取对象,如果没有认证信息,轻则列表为空,重则保存时直接空指针。

最简单的落地方式是自己写一个过滤器,把当前业务系统的登录用户包装成Flowable认识的FlowableUser,放到SecurityContext里。FlowableUser是flowable-ui-common包里的类,构造时传四个参数:用户ID、显示名、租户ID、权限列表。

@Component public class ModelerUserFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String uri = request.getRequestURI(); if (uri.startsWith("/modeler/") || uri.startsWith("/app/rest/")) { FlowableUser flowableUser = new FlowableUser( "system-user", "系统用户", "default", Collections.emptyList()); UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(flowableUser, null, Collections.emptyList()); SecurityContextHolder.getContext().setAuthentication(authentication); } chain.doFilter(request, response); } }

这段代码里我直接写了个固定的system-user,生产环境替换成真实登录用户的ID和昵称就行。注意一点,过滤器要保证在Spring Security的过滤器链中执行。如果你的项目用的是Spring Security,最干净的方式是在SecurityFilterChain里通过addFilterBefore把ModelerUserFilter加进去,顺序放在认证过滤器之前。如果项目没有Spring Security,只有HandlerInterceptor或Shiro,那就要看modeler-rest是否依赖security相关类,大概率还是要引入spring-boot-starter-security,然后只放行modeler相关路径。

安全策略上,我给/modeler/**和/modeler.html设了匿名访问,其余请求走原有认证。生产环境更稳的做法是再加一层控制,只有登录用户才能访问设计器,这个可以在自己的网关或鉴权层统一处理,而不是交给Flowable内部去管。

@Configuration @EnableWebSecurity public class ModelerSecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth .requestMatchers("/modeler/**", "/modeler.html", "/app/rest/**").permitAll() .anyRequest().authenticated()); return http.build(); } }

3.5 启动验证与部署联动

完成上述步骤后,启动项目,浏览器访问http://localhost:8080/modeler.html,正常情况下能看到模型列表页。点新建模型,进入设计器后,左侧是元件面板,中间是画布,右侧是属性面板,可以拖拽startEvent、userTask、exclusiveGateway这些节点,双击连线可以配置conditionExpression。

画好图点保存,模型会写入ACT_RE_MODEL,但引擎还没有对应的流程定义。业务上线前必须做一步"部署":把模型里的BPMN XML喂给引擎,生成真正的ACT_RE_PROCDEF流程定义。官方界面里按钮路径比较深,而且不一定符合你们的产品习惯,所以最好自己写一个部署接口。

@RestController @RequestMapping("/bpm/model") public class ModelDeployController { private final RepositoryService repositoryService; public ModelDeployController(RepositoryService repositoryService) { this.repositoryService = repositoryService; } @PostMapping("/{modelId}/deploy") public String deploy(@PathVariable String modelId) { org.flowable.engine.repository.Model model = repositoryService.createModelQuery().modelId(modelId).singleResult(); byte[] editorSource = repositoryService.getModelEditorSource(modelId); repositoryService.createDeployment() .name(model.getName()) .addString(model.getKey() + ".bpmn20.xml", new String(editorSource, StandardCharsets.UTF_8)) .deploy(); return "deploy success"; } }

部署成功后再去查ACT_RE_PROCDEF,就能看到新生成的流程定义版本。从此以后,画图、保存、部署、发起审批这条链路就完整了。

4. 常见问题与排查实录

4.1 白屏与静态资源404

页面白屏是所有嵌入方案里出现概率最高的。打开浏览器F12看Network面板,通常能看到一堆JS请求返回404,或者modeler.html加载出来后脚本路径全是根路径引用,被网关拦截。

排查顺序是这样的:先看HTML本身能不能访问,再看HTML里引用的JS路径有没有被资源映射覆盖,最后看有没有其他WebMvcConfigurer覆盖了静态资源配置。在我印象里,最隐蔽的一个case是,项目里前人写了一个@Configuration实现了WebMvcConfigurer,但是只加了拦截器没有调用父类方法,结果默认静态资源处理被覆盖,导致modeler的所有静态文件全部404。这种情况需要在配置里明确加上registry.addResourceHandler,而不是依赖Spring Boot的默认Mapping。

4.2 modeler接口返回401或直接跳登录

嵌入后打开页面发现,前端能加载,但一点"模型列表"就返回401,或者请求被重定向到了登录页。这多半是Spring Security拦截了/modeler/service/**和/app/rest/**。

两种处理方式:一是把这两类路径加入permitAll,二是走前面说的ModelerUserFilter模拟用户。如果业务上要求只有登录用户能画流程,就在自己的网关层校验登录态,到Flowable这一层保持permitAll并塞用户上下文。这样既能复用现有权限体系,又不会触发Flowable自带的那套认证跳转。

4.3 保存模型时空指针

保存模型时后端报NullPointerException,仔细看异常栈基本都是"failed to get current user"这类。原因是modeler在保存时要把当前用户ID写进模型的create_by字段,而SecurityContext里没有用户信息。

这个问题说到底还是"用户上下文"没打通。检查一下ModelerUserFilter的过滤路径是否正确,Spring Security对请求的执行顺序是怎样的。曾经我犯过一个低级错误:过滤器类上用@Component注册了,但项目里又自定义了FilterRegistrationBean,导致实际执行的是旧的过滤器实例,用户信息根本没设置进去。排查时可以在过滤器里临时加一行System.out.println(SecurityContextHolder.getContext().getAuthentication()),启动后请求一下接口,看控制台有没有输出。

4.4 模型能保存但流程跑不起来

流程设计器里画完图保存成功,去发起流程时却提示找不到流程定义,这种情况十有八九是没做"部署"。前面说过了,modeler只负责写模型,引擎只认流程定义,中间差一个deploy动作。

部署还有一个容易踩的坑:用addString添加BPMN XML时,文件名后缀必须是.bpmn20.xml,否则Flowable可能识别不了。文件名前半段建议用model.getKey(),保持和流程key一致,这样后续查询repositoryService.createProcessDefinitionQuery().processDefinitionKey()时不容易混淆。

4.5 多套安全框架冲突

把flowable-ui引入工程后,如果项目里原本用的是Shiro而没有Spring Security,会出现过滤器链特别混乱的情况。modeler-rest和common模块里有很多类依赖Spring Security的API,如果你没有显式引入spring-boot-starter-security,启动时可能直接报NoClassDefFoundError;引入了又可能和Shiro的拦截器打架。

这种场景我建议做一个取舍:统一用Spring Security做安全框架,Shiro相关的代码逐渐迁移;或者干脆把modeler-rest包里的security依赖排除,自己在Controller外层包一层业务接口。前者省事,符合主流趋势;后者工程量不小,但适合那种安全逻辑高度定制的系统。

针对刚说的4类高频问题,整理成速查表:

现象可能原因处理动作
页面白屏静态资源映射丢失检查ResourceHandler和WebMvcConfigurer
JS请求404前端路径与映射不一致保留官方目录结构或增加对应映射
接口401安全框架拦截放行/modeler/**与/app/rest/**
保存时空指针用户上下文缺失配置ModelerUserFilter并确认过滤器链顺序
流程启动报错模型未部署调自定义部署接口写入流程定义
部署解析失败版本不一致或文件名后缀错误统一版本,使用.bpmn20.xml后缀

5. 进一步扩展与个人经验

5.1 与现有权限体系的整合

基础嵌入跑通后,下一步要考虑的是权限。默认情况下,所有能访问modeler页面的人都能看到全部模型,这肯定不是我们想要的。我这里分享两个实用做法。

第一个做法是给模型列表接口加数据权限过滤。可以拦截/modeler/service/rest/models这个接口,拿到当前登录用户ID,然后只返回他创建或者他有权限的模型。实现方式可以用AOP切面,也可以包一层自己的Controller,但注意别破坏modeler前端对返回格式的期望,字段名最好保持一致。

第二个做法是保留Flowable自己的用户表,但只做"影子账户"。也就是说,业务系统的用户登录时,自动在ACT_ID_USER里同步创建一条记录,然后通过ModelerUserFilter把业务用户ID映射到Flowable用户。这样模型的创建人、权限归属都能落到Flowable自己的表里,后续要接官方admin模块也方便。

5.2 后续演进方向

按我这边的经验,嵌入modeler模块只是工作流中台化的第一步。往后还有三件事值得做。

第一,把"发布"流程做成一条完整的上线流水线。画完图保存只是个草稿,点了发布才生成流程定义,发布前可以做校验,比如检查是否有未闭合的网关、是否有孤立节点。校验逻辑可以基于引擎提供的BpmnModel对象,遍历元素做规则检查。

第二,把表单配置纳入modeler。Flowable的modeler本身支持关联表单key,但真正好用的表单设计器一般是业务系统自带的。可以把formKey约定为一个业务表单编码,画图时填上,发起审批时由业务前端根据编码渲染表单。这样流程设计和表单设计就解耦了,各自为政又通过key串起来。

第三,建议把模型的版本管理纳入现有CI/CD流程。模型有修改就生成一个新版本,只有通过测试的版本才允许部署到生产环境。模型本身存的是JSON加XML,可以做单元测试断言关键节点的存在性,和代码一起进流水线。

最后再分享一点个人体会。嵌入官方UI这类工作,最忌讳的是"复制粘贴一时爽,排查问题火葬场"。动手前一定要先看清楚官方模块的依赖关系、版本号、接口前缀,宁可前面多花半天读源码和war包结构,也不要等到启动报错再去翻文档。整个方案里最容易出问题的从来不是画图和保存,而是安全上下文和部署联动,这两个点想清楚,后面就顺了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 18:56:05

Windows 10开启SSH服务实现VMware虚拟机安全连接

1. 为什么在VMware里连不上Win10宿主机的SSH——一个被90%新手忽略的底层逻辑 “VMware虚拟机ssh连接win10宿主机”这个标题看似简单&#xff0c;但背后藏着三层认知断层&#xff1a;第一层&#xff0c;误以为SSH是Windows原生服务&#xff1b;第二层&#xff0c;混淆了“宿主机…

作者头像 李华
网站建设 2026/10/21 18:55:33

3吨悬臂式电动葫芦提升机SolidWorks三维设计全流程解析

说句实在话&#xff0c;很多人一看到"3吨悬臂式电动葫芦提升机SW三维"这个标题&#xff0c;第一反应就是"不就是画个葫芦挂个梁嘛&#xff0c;有什么好说的&#xff1f;"但真上手做一套完整的SolidWorks三维设计&#xff0c;你会发现里面牵扯的东西远比想象…

作者头像 李华
网站建设 2026/10/21 18:55:13

图表设计方法论:从配色布局到可复用设计系统的工程实践

1. 从"diagram-design"这个标题能读出什么第一次看到"diagram-design"这个标题&#xff0c;我脑子里蹦出来的第一个念头是&#xff1a;这大概率不是一个单纯的"画图工具"项目&#xff0c;而是一套关于"图表设计"的方法论或者设计系统。…

作者头像 李华
网站建设 2026/10/21 18:54:49

图表设计方法论:从信息结构到可视化表达的完整指南

1. 从"diagram-design"这个标题能读出什么 第一次看到"diagram-design"这个标题&#xff0c;我脑子里蹦出来的第一个念头是&#xff1a;这大概率不是一个单纯的"画图工具推荐"&#xff0c;而是一套关于 图表设计方法论 的东西。为什么这么判断…

作者头像 李华
网站建设 2026/10/21 18:54:43

性能测试面试高频考点:从指标原理到调优实战

1. 性能测试面试&#xff0c;到底在面什么 先抛一个很多人都会踩的误区&#xff1a;性能测试面试&#xff0c;重点从来不是“你会不会用某个工具”&#xff0c;而是“你懂不懂性能”。工具只是敲门砖&#xff0c;LoadRunner、JMeter 这些&#xff0c;只要肯花两周时间&#xff…

作者头像 李华