Springboot 整合Activiti流程设计器 完成一个简单的请假流程
1.前言
完成这个功能之前,我负责公司的流程管理模板,在众多的解决方案当中,我选择了Activiti 原因有:
- 开源、免费
- 整合Springboot较容易
Springboot已经成为开发后端不可缺少的一部分,它是如此完美,如此优秀!
2.准备
1.官方文档:https://www.activiti.org/userguide/
2.下载一份官方准备的demo:https://www.activiti.org/get-started 选择5.X download
这里选择旧版本的原因是:新的版本会如果突然出现一些不知名的错误,或者是版本问题,会让你头皮发麻不知道怎么解决,网上新版本这一类的错误博客也很少,很浪费时间!
3.下载解压
打开wars文件夹,复制war文件包到tomcat,利用tomcat对war包进行一个解压,我们也可以不着急,可以登录官方的demo进行尝试一把
放置到tomcat启动后产生的文件夹
地址:htpp://localhost:你的端口号/activiti-explorer
用户名:kermit 密码:kermit
4.开始整合 mysql + activiti + thymeleaf

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>5.22.0</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

按照官网文档的指示,我们引入springboot-starter 依赖 就是这么方便
2.配置文件

spring.datasource.url=jdbc:mysql://localhost:3306/demo?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ##每次应用启动不检查Activiti数据表是否存在及版本号是否匹配 第一次设置为true 会自动创建表结构,之后即可设置为false 提高运行速度
spring.activiti.database-schema-update=true

3.复制文件
复制我们刚才放到tomcat解压后的文件,选择以下文件夹和文件复制到springboot static文件夹下
- diagram-viewer 文件夹
- editor-app 文件夹
- modeler.html
4.加入控制器
复制这三个文件到任意包下,并且为这三个文件加入注解:@RequestMapping("/service")
5.修改配置文件
修改editor-app/app-cfg.js文件,修改其请求路径 和刚才修改的请求路径保持一致
6.剔除启动类里面的安全校验
@SpringBootApplication(exclude = {
org.activiti.spring.boot.SecurityAutoConfiguration.class, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class
})
7.项目启动完毕,查看数据库
25张表结构创建完毕,我简单引用一下别人的博客内容如下:
u ACT_GE_* : “GE”代表“General”(通用),用在各种情况下;
u ACT_HI_* : “HI”代表“History”(历史),这些表中保存的都是历史数据,比如执行过的流程实例、变量、任务,等等。Activit默认提供了4种历史级别:
Ø none: 不保存任何历史记录,可以提高系统性能;
Ø activity:保存所有的流程实例、任务、活动信息;
Ø audit:也是Activiti的默认级别,保存所有的流程实例、任务、活动、表单属性;
Ø full:最完整的历史记录,除了包含audit级别的信息之外还能保存详细,例如:流程变量。
这位大神的链接地址:https://www.cnblogs.com/telwanggs/p/7491564.html 查看更详细的表结构介绍
8.访问静态资源被拦截问题--》加入资源处理器

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

开始流程代码以及逻辑
1.首先是创建模型
创建模型呢可谓是流程管理的第一项,创建一个模型,我们呢需要在这个模型上进行流程图的设计与修改,首先把模型创建好
这里只展示部分代码,展示主要的功能,其他的具体内容,在文章尾部clone项目后进行查看
@RequestMapping("createModel")
public String createModel(HttpServletRequest request, HttpServletResponse response){
String name = "请假流程";
String description = "这是一个请假流程";
String id = null;
try {
Model model = repositoryService.newModel();
String key = name;
//版本号
String revision = "1";
ObjectNode modelNode = objectMapper.createObjectNode();
modelNode.put(ModelDataJsonConstants.MODEL_NAME, name);
modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);
model.setName(name);
model.setKey(key);
//模型分类 结合自己的业务逻辑
//model.setCategory(category);
model.setMetaInfo(modelNode.toString());
repositoryService.saveModel(model);
id = model.getId();
//完善ModelEditorSource
ObjectNode editorNode = objectMapper.createObjectNode();
editorNode.put("id", "canvas");
editorNode.put("resourceId", "canvas");
ObjectNode stencilSetNode = objectMapper.createObjectNode();
stencilSetNode.put("namespace",
"http://b3mn.org/stencilset/bpmn2.0#");
editorNode.put("stencilset", stencilSetNode);
repositoryService.addModelEditorSource(id, editorNode.toString().getBytes("utf-8"));
response.sendRedirect(request.getContextPath() + "/static/modeler.html?modelId=" + id);
} catch (Exception e) {
e.printStackTrace();
}
return "index";
}
PS 模型建好了肯定要进行画模型 我对流程设计器进行了汉化,这样操作起来方便多了 我简单画一个
一个最简单的请假流程 开始---》人事部审批----》总经理审批------》结束
这张图表示在这个流程开始时候需要填写的一些表单属性 这些都是可以动态加载的!
任务派遣:就表示的意思是:这个任务到底是指派给谁去执行? 我这里指派给张三去执行 当有人提交这个流程的时候 提交的内容填写完 就会有一个信息到张三这儿!
2.模型创建完毕,需要把模型发布为可用的流程定义(Process definition) 需要进行部署
@RequestMapping("deploymentModel")
@ResponseBody
public JSONObject deploymentModel(String id) throws Exception {
//获取模型
Model modelData = repositoryService.getModel(id);
byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
if (bytes == null) {
return JsonUtil.getFailJson("模型数据为空,请先设计流程并成功保存,再进行发布。");
}
JsonNode modelNode = modelNode = new ObjectMapper().readTree(bytes);
BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
if (model.getProcesses().size() == 0) {
return JsonUtil.getFailJson("数据模型不符要求,请至少设计一条主线流程。");
}
byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
//发布流程
String processName = modelData.getName() + ".bpmn20.xml";
Deployment deployment = repositoryService.createDeployment()
.name(modelData.getName())
.addString(processName, new String(bpmnBytes, "UTF-8"))
.deploy();
modelData.setDeploymentId(deployment.getId());
repositoryService.saveModel(modelData);
return JsonUtil.getSuccessJson("流程发布成功");
}

1 @RequestMapping("deploymentModel")
2 @ResponseBody
3 public JSONObject deploymentModel(String id) throws Exception {
4
5 //获取模型
6 Model modelData = repositoryService.getModel(id);
7 byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
8
9 if (bytes == null) {
10 return JsonUtil.getFailJson("模型数据为空,请先设计流程并成功保存,再进行发布。");
11 }
12 JsonNode modelNode = modelNode = new ObjectMapper().readTree(bytes);
13
14 BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
15 if (model.getProcesses().size() == 0) {
16 return JsonUtil.getFailJson("数据模型不符要求,请至少设计一条主线流程。");
17 }
18 byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);
19
20 //发布流程
21 String processName = modelData.getName() + ".bpmn20.xml";
22 Deployment deployment = repositoryService.createDeployment()
23 .name(modelData.getName())
24 .addString(processName, new String(bpmnBytes, "UTF-8"))
25 .deploy();
26 modelData.setDeploymentId(deployment.getId());
27 repositoryService.saveModel(modelData);
28 return JsonUtil.getSuccessJson("流程发布成功");
29 }

部署后的流程定义会显示部署ID 这个时候 模板就变成了流程定义
记住这个单词 后面用到的地方特别多!!!!
这里给解释一下这两个词的意思
- 流程定义:可以理解为画好的流程,已经发布过的,可以拿来用的一个模板
- 流程实例:流程实例是流程定义由某个用户启动后,它存在于系统当中,它是一个实例;
3.发布后的模型称之为流程定义,开启流程操作
开启流程的时候 我们需要一个页面展示这个流程需要填写的字段等 然后提交进行流程的下一步操作
启动一个流程,这里加载的是我们在画流程图时候输入的表单,这里的提交人就是当前登录的用户(我这里没有整合安全框架 随便写了一个做测试!)
审核人界面进行审批/驳回(暂时未有这个功能)
这里是派遣给张三的任务,刚才提交的任务现在到张三的下面 进行一个审核,然后把这个任务提交到下一级(总经理审核)
这里需要张三进行流程的审批。我们填写表单后,进行提交,现在打开总经理(李四)的任务列表,发现有一个需要待处理的任务!
这里我们既可以看到人事部审核的意见,也可以看到流程开始时候用户提交的内容。流程图也做了相应的更新。
写在最后
作为一个刚接触流程的小白,第一次打开这个流程啥都不懂,也慢慢摸索一些,从网上关于流程Activiti的资料很少。
总的来说就是:
- 杂乱,没有一个较好的学习资料可以参考
- 这一方面的博客/文章较少
推荐学习:http://www.agilebpm.cn/
这是博主最近才接触到的一个国内的流程开源版本,总体来说比国外这款Activiti好用,简洁 Api较多,简易
也不能说Activiti人家不好,就是说白了有点复杂,小白一下子上手不了,推荐从这款开源版本开始学习
参考:
https://www.cnblogs.com/zhouyun-yx/p/10410274.html
https://www.jianshu.com/p/701056e672a4
https://www.cnblogs.com/telwanggs/p/7491564.html
错误解决:
class path resource [processes/] cannot be resolved to URL because it does not exist
解决方案:创建这个processes文件夹到resources下 随便丢个文件进去
java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
解决方案:剔除启动校验问题,向上看第六点
Could not write PNG file because no WriteAdapter is availble
解决方案:
依赖文件引入缺少问题 引入一下即可
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-codec</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-css</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-svg-dom</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-svggen</artifactId>
<version>1.7</version>
</dependency>
代码实例开源:
码云:https://gitee.com/mrc1999/activiti
原文链接:https://www.cnblogs.com/ChromeT/p/11261101.html
Springboot 整合Activiti流程设计器 完成一个简单的请假流程的更多相关文章
- 流程设计器jQuery + svg/vml(Demo3 - 添加流程结点)
经过前面的准备工作,终于把设计器的主要UI界面搭建好了,接下来到添加流程结点,效果如下图 代码:GoFlow_03.zip 演示地址:Demo 微信演示公众号: 另:Silverlight版 Silv ...
- 2-1. Creating a Simple Model 使用图形界面设计器创建一个简单的模型
一.创建新项目 二.添加模型文件 三.添加完后,在设计面板空白处右击,创建一个实体 实体集(B) 这里的名称会是对应的数据库表名称!!! ,开始不知道这是什么,生成后才知道表名是这个,以后注意点就行. ...
- activiti工作流的web流程设计器整合视频教程 SSM和独立部署
本视频为activiti工作流的web流程设计器整合视频教程 整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器) 本视频共讲了两种整合方式 1. 流 ...
- activiti工作流的web流程设计器整合视频教程 SSM 和 独立部署
本视频为activiti工作流的web流程设计器整合视频教程 整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器) 本视频共讲了两种整合方式 1. 流 ...
- activiti工作流的web流程设计器整合视频教程
本视频为activiti工作流的web流程设计器整合视频教程 整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器) 本视频共讲了两种整合方式 1. 流 ...
- activiti web流程设计器 工作流的 整合视频教程 SSM和独立部署
本视频为activiti工作流的web流程设计器整合视频教程 整合Acitiviti在线流程设计器(Activiti-Modeler 5.21.0 官方流程设计器) 本视频共讲了两种整合方式 1. 流 ...
- 可视化流程设计——流程设计器演示(基于Silverlight)
上一篇文章<通用流程设计>对鄙人写的通用流程做了一定的介绍,并奉上了相关源码.但一个好的流程设计必少不了流程设计器的支持,本文将针对<通用流程设计>中的流程的设计器做一个简单的 ...
- Eclipse安装Activiti插件(流程设计器)
Eclipse安装Activiti插件(流程设计器) 一.安装步骤: 1,打开Eclipse的 Help -> Install New Software,填上插件地址: Name:Activit ...
- 01--安装Activiti流程设计器eclipse插件
Activiti1 安装流程设计器eclipse插件 Name:Activiti BPMN 2.0 designer(随便起个名字) Location: http://activiti.org/des ...
随机推荐
- 使用 udev 进行动态内核设备管理(转自suse文档)
第 12 章使用 udev 进行动态内核设备管理¶ 目录 12.1. /dev 目录 12.2. 内核 uevents 和 udev 12.3. 驱动程序.内核模块和设备 12.4. 引导和启动设备设 ...
- Android Studio 之 Navigation【1.页面之间的切换】
1.创建 2个 Fragment ,下面两个include 不要勾 2.创建好 Fragment 后,打开layout中的 fragment.xml 文件,将里面默认的 textView 控件删除掉 ...
- Java正则表达式入门基础篇
正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它 用以描述在查找文字主体时待匹配的一个或多个字符串.正则表达式作为 ...
- BurpSuite pro v2.0 使用入门教程
BurpSuite简介 BurpSuite是进行Web应用安全测试集成平台.它将各种安全工具无缝地融合在一起,以支持整个测试过程中,从最初的映射和应用程序的攻击面分析,到发现和利用安全漏洞.Burps ...
- Tarjan 算法求 LCA / Tarjan 算法求强连通分量
[时光蒸汽喵带你做专题]最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili tarjan LCA - YouTube Tarj ...
- ASP.NET 网站迁移 HTTP 错误 500.22 - Internal Server Error 检测到在集成的托管管道模式下不适用
前提:今天要做网站迁移,把A服务器上的网站迁移到B服务器上,A服务器当时的环境是.NET 4.0 ,而B服务器是.NET2.0,A服务器IIS为6.0,B服务器IIS版本为7.0 第一步,先在B服务 ...
- python 基础 ---- 文件读写
文件是一种存储在存储存储媒介上的信息或数据 常用的文件类型 文件 的打开关闭 close() 关闭文件 文件的打开路径 绝对路径 : 文件在操作系统中标准的存放路径 相对路径: 与目前引用文件的相对位 ...
- NP完全问题的证明
目录 NP完全问题的证明 一.限制法 最小覆盖问题(VC) 子图同构问题 0-1背包(Knapsack) 三元集合的恰当覆盖(X3C) 集中集 有界度的生成树 多处理机调度 二.局部替换法 3SAT问 ...
- Python基础笔记(五)
1. 类(class) 下面的代码建立了一个Employee类: #!/usr/bin/env python3 # -*- coding: utf-8 -*- class Employee(objec ...
- Java学习: 面向对象的使用与注意事项
面向对象的使用与注意事项 面向过程:当需要实现一个功能的时候,每一个具体的步骤都需要亲力,详细处理每一个细节面向对象:当需要实现一个功能的时候,不关心具体的步骤,而是找一个已经具有该功能的人,来帮我做 ...