Activiti初尝试(一)
一.
背景介绍
1. Activiti 其核心是 BPMN 2.0 的流程引擎。BPMN 是目前被各 BPM 厂商广泛接受的 BPM 标准,全称为 Business Process Model and Notation,由 OMG 组织进行维护,2011 年 1 月份发布了其 2.0 的正式版。BPMN 2.0 对比于第一个版本,其最重要的变化在于其定义了流程的元模型和执行语义,即它自己解决了存储、交换和执行的问题。这代表着 BPMN 2.0 流程定义模型不仅仅可以在任何兼容 BPMN 2.0 的引擎中执行,而且也可以在图形编辑器间交换。作为一个标准,BPMN 2.0 统一了工作流社区。
2. Activiti 是由 jBPM 的创建者 Tom Baeyens 离开 JBoss 之后建立的项目,构建在开发 jBPM 版本 1 到 4 时积累的多年经验的基础之上,旨在创建下一代的 BPM 解决方案。同时 Activiti 选择了 Apache 许可,一方面是希望 Activiti 能有更长久的生命力,因为它不受任何个人或是公司的控制而是属于整个社区,另一方面更是希望这个宽松的许可能够让 Activiti BPM 引擎和 BPMN2.0 被更广泛的采纳、使用和商业化。
3. 对于 Java 开发者来说,Activiti 的首席架构师 Tom Baeyens 曾提到,Activiti 的首个目标就是要获得开发者的青睐。首先它在使用时极为方便,只是个 jar 文件,使用时仅需要将其放在类路径中,当然,Activiti 也可以作为独立服务器的方式使用;同时 Activiti 提供了很多 BPM 高级工具,其中还包括开发了协作工具,使得开发人员、业务人员和运维人员能够更好的协同工作。
本文将会介绍 Activiti 的基本概念,同时通过示例来介绍如何通过搭建 Activiti 开发环境和 Activiti API 使用,同时也会接触到 Activiti 的一些工具,希望通过阅读这篇文章,Activiti 能成为您在开发 BPM 系统时的一个选择。
2. Activiti 是由 jBPM 的创建者 Tom Baeyens 离开 JBoss 之后建立的项目,构建在开发 jBPM 版本 1 到 4 时积累的多年经验的基础之上,旨在创建下一代的 BPM 解决方案。同时 Activiti 选择了 Apache 许可,一方面是希望 Activiti 能有更长久的生命力,因为它不受任何个人或是公司的控制而是属于整个社区,另一方面更是希望这个宽松的许可能够让 Activiti BPM 引擎和 BPMN2.0 被更广泛的采纳、使用和商业化。
3. 对于 Java 开发者来说,Activiti 的首席架构师 Tom Baeyens 曾提到,Activiti 的首个目标就是要获得开发者的青睐。首先它在使用时极为方便,只是个 jar 文件,使用时仅需要将其放在类路径中,当然,Activiti 也可以作为独立服务器的方式使用;同时 Activiti 提供了很多 BPM 高级工具,其中还包括开发了协作工具,使得开发人员、业务人员和运维人员能够更好的协同工作。
本文将会介绍 Activiti 的基本概念,同时通过示例来介绍如何通过搭建 Activiti 开发环境和 Activiti API 使用,同时也会接触到 Activiti 的一些工具,希望通过阅读这篇文章,Activiti 能成为您在开发 BPM 系统时的一个选择。
-----上面内容都是复制的-----
二.简单使用
直接看代码吧:
/** 部署流程定义 **/
@Test
public void deploymentProcessDefinition(){
Deployment deployment = processEngine.getRepositoryService() //与流程定义和部署相关的service
.createDeployment() //创建一个部署对象
.name("activiti入门") //添加部署对象的名字
.addClasspathResource("diagrams/helloworld.bpmn") //从classpath资源中加载,一次只能加载一个文件
.addClasspathResource("diagrams/helloworld.png") //从classpath资源中加载,一次只能加载一个文件
.deploy();
System.out.println(deployment.getId());
System.out.println(deployment.getName());
}
/** 启动流程实例 **/
@Test
public void startProcessInstance(){
String processDefinitionKey = "helloworld";
ProcessInstance pi = processEngine.getRuntimeService() //与正在执行的流程实例和执行对象相关的service
.startProcessInstanceByKey(processDefinitionKey); //使用流程定义的key启动流程实例,key对应的helloworld.bpmn--id的属性值,使用key值启动,默认按照最新版本流程启动
System.out.println("流程实例id:"+pi.getId()); //流程实例id
System.out.println("流程定义id:"+pi.getProcessDefinitionId()); //流程定义id
}
/** 查询当前人的个人任务 **/
@Test
public void findMyPersionTask(){
System.out.println("**************************开始查询************************");
String assignee = "张三";
List<Task> list = processEngine.getTaskService()
.createTaskQuery() //创建任务查询对象
.taskAssignee(assignee) //指定个人任务查询,指定办理人
.list();
if(list!=null&&list.size()>0){
for (Task task : list) {
System.out.println("任务id:"+task.getId());
System.out.println("任务名称:"+task.getName());
System.out.println("任务创建时间:"+task.getCreateTime());
System.out.println("任务办理人:"+task.getAssignee());
System.out.println("流程实例id:"+task.getProcessInstanceId());
System.out.println("执行对象id:"+task.getExecutionId());
System.out.println("流程定义id:"+task.getProcessDefinitionId());
}
}
System.out.println("**************************查询结束************************");
}
/** 完成我的任务 **/
@Test
public void completeMyPersionTask(){
String taskId = "902";
processEngine.getTaskService().complete(taskId); //与正在执行的任务管理相关的service
System.out.println("完成任务:任务id:"+taskId);
}
/**
* 查询历史任务
*/
@Test
public void queryHistoryTask(){
//历史任务办理人
String taskAssignee = "张三";
List<HistoricTaskInstance> list = processEngine.getHistoryService().createHistoricTaskInstanceQuery().taskAssignee(taskAssignee).list();
if(list!=null&&list.size()>0){
for (HistoricTaskInstance hts : list) {
System.out.println("任务ID:"+hts.getId());
System.out.println("流程实例ID:"+hts.getProcessInstanceId());
System.out.println("任务的办理人:"+hts.getAssignee());
System.out.println("执行对象ID:"+hts.getExecutionId());
System.out.println(hts.getStartTime()+" "+hts.getEndTime()+" "+hts.getDurationInMillis());
}
}
}
/**
* 查询流程定义
*/
@Test
public void findProcessDefinition(){
List<ProcessDefinition> list = processEngine.getRepositoryService()
.createProcessDefinitionQuery()
//指定查询条件
// .deploymentId(deploymentId) //使用部署对象id查找
// .processDefinitionId(processDefinitionId) //使用流程定义id查找
// .processDefinitionKey(processDefinitionKey) //使用流程定义的key查找
//排序
// .orderByProcessDefinitionVersion().asc(); // 按照版本的升序排列
// .orderByProcessDefinitionName().desc(); //按照流程定义的名称降序排列
//返回结果集
.list(); //返回一个集合列表,分装流程定义
// .singleResult(); //返回唯一结果集
// .count(); //返回结果集数量
// .listPage(firstResult, maxResults); //分页查询
if(list!=null&&list.size()>0){
for (ProcessDefinition pd : list) {
System.out.println("流程定义id:"+pd.getId());
System.out.println("流程定义名称:"+pd.getName());
System.out.println("流程定义的key:"+pd.getKey());
System.out.println("流程定义版本:"+pd.getVersion());
System.out.println("资源名称bpmn文件:"+pd.getResourceName());
System.out.println("资源名称bpmn文件:"+pd.getDiagramResourceName());
System.out.println("部署对象ID::"+pd.getDeploymentId());
System.out.println("**********************************************");
}
}
}
/**
* 删除流程定义
*/
@Test
public void deleteProcessDefinitionByDeploymentId(){
String deploymentId = "1";
processEngine.getRepositoryService()
//不带级联的删除 只能删除没有启动的流程,如果流程启动就会抛出异常
// .deleteDeployment(deploymentId);
//级联删除 不管流程是否启动 都可以删除
.deleteDeployment(deploymentId, true);
System.out.println("删除成功!");
}
/**
* 查看流程图
*/
@Test
public void viewPic(){
//将生成的图片放置到文件夹下
String deploymentId = "501";
String resourceName = null;
//获取图片资源名称
List<String> resourcelist = processEngine.getRepositoryService().getDeploymentResourceNames(deploymentId);
if(resourcelist!=null&&resourcelist.size()>0){
for (String namestr : resourcelist) {
if(namestr.indexOf(".png")>=0){
resourceName = namestr;
}
}
}
//获取图片输入流
InputStream in = processEngine.getRepositoryService()
.getResourceAsStream(deploymentId, resourceName);
//定义生成图片资源路径
File file = new File("D:/"+resourceName);
try {
FileUtils.copyInputStreamToFile(in, file);
} catch (IOException e) {
e.printStackTrace();
}
}
/** 附加功能 查询最新版本的流程定义 **/
@Test
public void findLastVersionProcessDefinition(){
List<ProcessDefinition> list = processEngine.getRepositoryService()
.createProcessDefinitionQuery()
.orderByProcessDefinitionVersion().asc().list(); //使用流程定义版本升序排列
Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>();
if(list!=null&&list.size()>0){
for (ProcessDefinition pd : list) {
map.put(pd.getKey(), pd);
}
}
List<ProcessDefinition> pdlist = new ArrayList<ProcessDefinition>(map.values());
if(pdlist!=null&&pdlist.size()>0){
for (ProcessDefinition pd : list) {
System.out.println("流程定义id:"+pd.getId());
System.out.println("流程定义名称:"+pd.getName());
System.out.println("流程定义的key:"+pd.getKey());
System.out.println("流程定义版本:"+pd.getVersion());
System.out.println("资源名称bpmn文件:"+pd.getResourceName());
System.out.println("资源名称bpmn文件:"+pd.getDiagramResourceName());
System.out.println("部署对象ID::"+pd.getDeploymentId());
System.out.println("**********************************************");
}
}
}
这些都没啥可说的,部署注意一下,从方法上来看有5中部署方式:
processEngine.getRepositoryService()
.addBpmnModel(resourceName, bpmnModel)
.addInputStream(resourceName, inputStream)
.addString(resourceName, text)
.addZipInputStream(zipInputStream)
.addClasspathResource(resource)
主要使用的是两种:
1. ZIP方式,在项目整合时,最初用的就是这种,用eclipse插件将流程图画好后,上传至服务器,自动解析进行部署,
/**
* 部署流程定义
*/
@Override
public boolean saveNewDeploy(String filepath,String filename) {
boolean returnflag = true;
ZipInputStream zipInputStream;
try {
System.out.println(filepath);
zipInputStream = new ZipInputStream(new FileInputStream(new File(filepath)));
repositoryService.createDeployment()
.name(filename)
.addZipInputStream(zipInputStream)
.deploy();
System.out.println("部署完成!");
return returnflag;
} catch (FileNotFoundException e) {
returnflag = false;
e.printStackTrace();
}
return returnflag;
}
传入上传文件的路径以及名字就可以进行部署了。
2. addString(resourceName, text)方式,这种方式是整合Activiti Modeler设计器后,比较常见的部署方式,
然后就是可能会遇到的一些问题了:
1. eclipse 安装activiti插件后为什么 画好了流程图保存后 只生成了 bpmn文件,而没有生成对应的png图片呢:
perference -> Activiti -> Save Actions 勾选 Create Process definition image when saving the diagram即可
2. 还有一处要注意:
初尝试 就写这么多吧,下一期说说怎么和项目整合与业务结合,然后再说说怎样集成设计器等
提供一下 demo源码,这里写的比较全些:http://download.csdn.net/detail/qq_27063119/9911518