jbpm工作流

jbpm工作流一、JBPM(javabusinessprocessmanager)1、工作流管理流程O>定义工作流(使用流程设计器生成,png和xml文件,分别面向用户和系统)>执行工作流

大家好,又见面了,我是你们的朋友全栈君。

 

一、JBPM(java business process manager)

  1、工作流管理流程

  O—>定义工作流(使用流程设计器生成,png和xml文件,分别面向用户和系统)

    —>执行工作流(核心对象:流程引擎ProcessEngine)

    —>连接数据库(jbpm18张表,jbpm4_deploymen,jbpm4_deployprop,jbpm4_execution,jbpm4_hist_task,jbpm_hist_var,jbpm4_lob,jbpm4_task,jbpm_variable)

  <—O

  <span role="heading" aria-level="2">jbpm工作流  <span role="heading" aria-level="2">jbpm工作流

  2、jbmp中的几个基本概念

  流程引擎,ProcessEnginee

  *RepositoryService

  *ExcutionService

  *TaskService

  部署对象(deployment):一次部署一个或者多个文件到数据库中(png,xml,zip)

  流程定义(processDefinition):获得并解析xml,解析xml文件中的内容,内容即流程定义的规则,工作流jbpm就是按照流程定义的规则往下执行的。与流程定义相关的表,

    jbpm部署流程定义的表:select * from jbpm4_deployment;

    jbpm流程定义的表:select * from jbpm4_deployprop;

    存放资源文件的表:select * from jbpm4_lob;

  执行对象(Execution):按照指定的流程定义执行一次的过程,就叫做执行对象;

    相关的数据库表:

    存放jbpm正在执行的流程实例信息表:select * from jbpm4_execution;

    存放jbpm执行信息流失表:select * from jbpm4_hist_procinst;

  流程实例(ProcessInstance):从业务的开始到结束之间最大的执行对象就是流程实例,当业务流程中只有一个分支(路线)的时候,此时的执行对象就是流程实例。

  <span role="heading" aria-level="2">jbpm工作流

 

  流程变量:使用流程变量存储数据,在流程执行或者任务执行的过程中,用于设置和获取变量,使用流程变量在流程传递的过程中传递业务参数。

 

  活动环节:

    任务(Task)

      当前活动节点是任务的时候,那么此时执行的就是任务

      相关的数据库表:

        存放正在执行的任务信息表:select * from jbpm4_task;

        存放任务信息历史表:select * from jbpm4_hist_task;

    状态(state)

      当前活动节点是状态的时候,那么此时就是状态节点,是当前流程在状态节点中先停    留一下。

  流程连线

    1、一个活动中可以指定一个或多个Transition(Start中只能有一个,End中没有)

    2、结束活动中没有Transition

    3、开始活动中只有一个Transition

    4、其他活动中有1条或多条Trasition

    5、如果只有一个,则可以不指定名称(名称是null);如果有多个,则要分别指定唯一的名称。

  2、jbpm的实现步骤和细节

  四个步骤: 

    1、部署流程定义(xml和png)

    2、启动流程实例

    3、查看我的个人任务

    4、办理任务

  流程引擎的创建:

    

第一种:使用默认的配置文件(jbpm.cfg.xml)生成Configuration并构建ProcessEngine:
ProcessEngine processEngine = new Configuration().buildProcessEngine();
第二种:使用指定的配置文件(要放到classPath下):
ProcessEngine processEngine = new Configuration()
      .setResource("my-own-configuration-file.xml")
      .buildProcessEngine();
第三种:使用如下代码获取使用默认配置文件的、单例的ProcessEngine对象:
ProcessEngine processEngine = Configuration.getProcessEngine();

 

  流程定义:

    1、部署流程定义

  流程定义通过流程设计器设计出两个对应的png图片格式和xml配置文件的格式。

// 部署
@Test
public void testDeploy() throws Exception {
String deploymentId = processEngine.getRepositoryService()//
.createDeployment()//
.addResourceFromClasspath("helloworld/helloworld.jpdl.xml")//
.addResourceFromClasspath("helloworld/helloworld.png")//
.deploy();
System.out.println("deploymentId=" + deploymentId);
}
// 部署
@Test
public void testDeploy_zip() throws Exception {
InputStream in = getClass().getClassLoader().getResourceAsStream(
"helloworld/helloworld.zip");
ZipInputStream zipInputStream = new ZipInputStream(in);
String deploymentId = processEngine.getRepositoryService()//
.createDeployment()//
.addResourcesFromZipInputStream(zipInputStream)//
.deploy();
System.out.println("deploymentId=" + deploymentId);

 

    2、流程定义的查询

@Test
public void testFindAll() throws Exception {
// 查询
List<ProcessDefinition> list = processEngine.getRepositoryService()//
.createProcessDefinitionQuery()//
// 过滤条件
// .processDefinitionId("helloworld-1")//
.processDefinitionKey("helloworld")//
// 排序
// .orderAsc(ProcessDefinitionQuery.PROPERTY_ID)//
// .orderDesc(ProcessDefinitionQuery.PROPERTY_VERSION)//
// 执行查询
// .uniqueResult();
// .count();
// .page(firstResult, maxResults)//
.list();

// 显示
for (ProcessDefinition pd : list) {
System.out.println("id=" + pd.getId()// 格式:{key}-{version}
+ ", name=" + pd.getName()// .jpdl.xml根元素的name属性的值
+ ", key=" + pd.getKey()// .jpdl.xml根元素的key属性的值,如果不写,默认为name属性的值
+ ", version=" + pd.getVersion()// 默认自动维护,第1个是1,以后相同key的都会自动加1
+ ", deploymentId=" + pd.getDeploymentId()); // 所属的某个Deployment的对象
}
}

 

    3、删除流程定义

// 删除(使用流程定义ID)
@Test
public void testDeleteById() throws Exception {
String deploymentId = "90001";
// 删除某部署对象(也可以称之为删除流程流程定义),如果有关联的执行信息,就报错
// processEngine.getRepositoryService().deleteDeployment(deploymentId);
// 删除某部署对象(也可以称之为删除流程流程定义),如果有关联的执行信息,就级联删除
processEngine.getRepositoryService().deleteDeploymentCascade(
deploymentId);
}

 

    4、查看流程图

// 查看流程图(xxx.png)
@Test
public void testShowProcessImage() throws Exception {
// 获取文件内容
String deploymentId = "1";
String resourceName = "helloworld/helloworld.png";
InputStream in = processEngine.getRepositoryService()//
.getResourceAsStream(deploymentId, resourceName);

// 保存到c:/
FileOutputStream out = new FileOutputStream("c:/process.png");
for (int b = -1; (b = in.read()) != -1;) {
out.write(b);
}
in.close();
out.close();
}

 

    5、查询最新版本的流程定义

@Test
public void testFindAllLatestVersions() throws Exception {
// 查询,把最大的版本都排到后面
List<ProcessDefinition> list = processEngine.getRepositoryService()//
.createProcessDefinitionQuery()//
.orderAsc(ProcessDefinitionQuery.PROPERTY_VERSION)//
.list();
// 过滤出最新的版本
Map<String, ProcessDefinition> map = new LinkedHashMap<String, ProcessDefinition>();
for (ProcessDefinition pd : list) {
map.put(pd.getKey(), pd);
}

// 显示
for (ProcessDefinition pd : map.values()) {
System.out.println("id=" + pd.getId()// 格式:{key}-{version}
+ ", name=" + pd.getName()// .jpdl.xml根元素的name属性的值
+ ", key=" + pd.getKey()// .jpdl.xml根元素的key属性的值,如果不写,默认为name属性的值
+ ", version=" + pd.getVersion()// 默认自动维护,第1个是1,以后相同key的都会自动加1
+ ", deploymentId" + pd.getDeploymentId()); // 所属的某个Deployment的对象
}
}

 

    6、按照key删除所有版本的流程定义

// 删除(使用流程定义的key)
@Test
public void testDeleteByKey() throws Exception {
// 1,查询指定key的所有版本的流程定义
List<ProcessDefinition> list = processEngine.getRepositoryService()//
.createProcessDefinitionQuery()//
.processDefinitionKey("helloworld")//
.list();
// 2,循环删除
for (ProcessDefinition pd : list) {
processEngine.getRepositoryService()//
.deleteDeploymentCascade(pd.getDeploymentId());
}
}

 

  流程实例和任务

    1、部署流程定义(xml和png)

    2、启动流程实例

// 启动流程实例
@Test
public void testStartProcessInstance() throws Exception {
ProcessInstance pi = processEngine.getExecutionService().startProcessInstanceByKey("test");
System.out.println("流程实例启动成功,processInstanceId=" + pi.getId());
}

 

    3、查看我的任务列表

@Test
public void testFindMyTaskList() throws Exception {
// 查询
String userId = "部门经理";
// List<Task> list = processEngine.getTaskService().findPersonalTasks(userId);
List<Task> list = processEngine.getTaskService()//
.createTaskQuery()//
.assignee(userId)// 要是指定的办理人
// .count()
// .page(firstResult, maxResults)
.list();
// 显示
for (Task task : list) {
System.out.println("id=" + task.getId()//
+ ", name=" + task.getName()// 任务的名称
+ ", assignee=" + task.getAssignee()// 任务的办理人
+ ", createTime=" + task.getCreateTime()// 任务的创建时间
+ ", executionId=" + task.getExecutionId()); // 所属的执行对象的id
}
}

 

    4、完成任务

// 办理任务
@Test
public void testCompleteTask() throws Exception {
String taskId = "20002";
processEngine.getTaskService().completeTask(taskId);
}

 

    5、向后执行一步

// 让流程向后执行一步
@Test
public void testSignalExecution() throws Exception {
//String executionId = "helloworld.20001";
//String signalName = "to 审批 [总经理]";
String executionId = "helloworld.20001";
processEngine.getExecutionService().signalExecutionById(executionId,"to 审批 [总经理]");
}

  

  流程变量

    1、在流程传递的过程中,可以为执行的对象或者任务来指定变量值,在流程执行、或者是任务执行的过程中,可以获取并设置对应的流程变量的值、

    2、select * from jbmp4_variable

  设置流程变量

// 设置流程变量
@Test
public void testSetVariable() throws Exception {
String executionId = "test.80001";
 String name = "请假天数";
 Object value = new Integer(5);
 processEngine.getExecutionService().setVariable(executionId, name, value);

//Form form = new Form(1L, "张三请假11天");
//processEngine.getExecutionService().setVariable(executionId, "form", form);
}

  获取流程变量

// 获取流程变量
@Test
public void testGetVariable() throws Exception {
String executionId = "test.80001";
 String name = "请假天数";
 Object value = processEngine.getExecutionService().getVariable(executionId, name);
 System.out.println(name + " = " + value);

//Form form = (Form) processEngine.getExecutionService().getVariable(executionId, "form");
//System.out.println("id=" + form.getId() + ", title=" + form.getTitle());
}
{
// ExecutionService executionService = processEngine.getExecutionService();
// TaskService taskService = processEngine.getTaskService();
// // ========================================
// // 设置变量的方法
// // 通过Execution设置一个变量
// executionService.setVariable(executionId, name, value);
// // 通过Execution设置多个变量
// executionService.setVariables(executionId, variablesMap);
// // 通过Task设置多个变量
// taskService.setVariables(taskId, variablesMap);
// // 在启动流程实例时,同时也设置一些流程变量
// executionService.startProcessInstanceByKey(processDefinitionKey, variablesMap);
// // 在完成任务时,同时也设置一些流程变量
// taskService.completeTask(taskId, variablesMap);
// // ========================================
// // 获取变量的方法
// // 通过Execution获取一个变量
// executionService.getVariable(executionId, variableName);
// // 通过Execution获取所有变量的名称集合
// executionService.getVariableNames(executionId);
// // 通过Execution获取所有变量的信息
// executionService.getVariables(executionId, variableNames);
}

  流程连线和活动

    1、判断decision

    <span role="heading" aria-level="2">jbpm工作流

URL url = this.getClass().getResource("test.jpdl.xml");
String deploymentID = processEngine.getRepositoryService()//
.createDeployment()//
.addResourceFromUrl(url)//
.deploy();
System.out.println("部署流程定义成功!deploymentID"+deploymentID);

//Integer value = 300;
Integer value = 3000;
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("报销金额", value);
ProcessInstance pi = 
processEngine.getExecutionService().startProcessInstanceByKey("test",variables);
System.out.println("启动流程实例成功!id="+pi.getId());
Task task = processEngine.getTaskService()//
.createTaskQuery()//
.processInstanceId(pi.getId())//
.uniqueResult();
System.out.println("当前任务的ID="+task.getId());
System.out.println("当前任务的名称="+task.getName());

processEngine.getTaskService().completeTask(task.getId());
System.out.println("任务完成!");

判断当前操作属于哪一个分支

@SuppressWarnings("serial")
public class DecisionHandlerImpl implements DecisionHandler {
//用来判断当前操作执行哪个分支
@Override
public String decide(OpenExecution execution) {
int money = (Integer) execution.getVariable("报销金额");
//让总经理审批一下
if(money>1000){
    return "to 总经理审批";
}
//让流程结束
return "to end1";
}
}

     2、活动的(fork/join)

  <span role="heading" aria-level="2">jbpm工作流

  

@Test
public void test(){
URL url = this.getClass().getResource("test.jpdl.xml");
String deploymentID = processEngine.getRepositoryService()//
.createDeployment()//
.addResourceFromUrl(url)//
.deploy();
System.out.println("部署流程定义成功!deploymentID"+deploymentID);

ProcessInstance pi = 
processEngine.getExecutionService().startProcessInstanceByKey("test");
System.out.println("启动流程实例成功!id="+pi.getId());
}

 

   3、个人任务

 <span role="heading" aria-level="2">jbpm工作流

 

@Test
public void testCompleteTask(){
// 4,执行完第1个任务,并使用指定的Transition离开
String taskId = "200001";
String transitionName1 = "to end1";
String transitionName2 = "to 审批 [总经理]";

// 办理完任务,使用指定名称的Transition离开
// processEngine.getTaskService().completeTask(task.getId(), transitionName2);
//processEngine.getTaskService().completeTask(taskId, transitionName2);
processEngine.getTaskService().completeTask(taskId);
System.out.println("任务执行完毕!");
}

     4.组任务

  

组任务及三种分配方式:
    1:在.jpdl.xml中直接写 candidate-users=“小A,小B,小C,小D"
    2:在.jpdl.xml中写 candidate-users =“#{userIds}”,变量的值要是String的。
         使用流程变量指定办理人
              Map<String, Object> variables = new HashMap<String, Object>();
              variables.put("userIDs", "大大,小小,中中");
    3,使用AssignmentHandler接口,使用类实现该接口,在类中定义:
            //添加组任务的用户
assignable.addCandidateUser("张无忌");
assignable.addCandidateUser(“张三丰”);   
组任务分配给个人任务:
     processEngine.getTaskService().takeTask(taskId, userId);
个人任务分配给组任务:
     processEngine.getTaskService().assignTask(taskId, null);
向组任务添加人员:
     processEngine.getTaskService().addTaskParticipatingUser(taskId, userId, Participation.CANDIDATE);
组任务对应的表:
       jbpm4_participation

    事件

  <span role="heading" aria-level="2">jbpm工作流

1:在根元素中,或在节点元素中,使用<on event=“”>元素指定事件,其中event属性代表事件的类型(start和end表示开始和结束)。
2:在<on>中用子元素<event-listener class="EventListenerImpl" />,指定处理的类,要求指定的类要实现EventListener接口
3:事件类型:
(1):<on>元素放在根元素(<process>)中,可以指定event为start或end,表示流程的开始与结束。
(2):<on>元素放在节点元素中,可以指定event为start或end,表示节点的进入与离开
(3):在Start节点中只有end事件,在End节点中只有start事件。
(4):在<transition>元素中直接写<event-listener class=“”>,就是配置事件。(因为在这里只有一个事件,所以不用写on与类型)
(5):在<task>元素中还可以配置assign事件,是在分配任务时触发的。
<process name="test" xmlns="http://jbpm.org/4.4/jpdl">
   <!-- 在整个流程实例启动的时候进行事件监听 -->
   <on event="start">
   <event-listener class="cn.itcast.jbpm.k_event.EventListenerImpl" />
   </on>
   <!-- 在整个流程实例停止的时候进行事件监听 -->
   <on event="end">
   <event-listener class="cn.itcast.jbpm.k_event.EventListenerImpl" />
   </on>
   <start name="start1" g="113,78,48,48">
       <!-- 在启动活动的时候进行事件监听 -->
       <on event="end">
          <event-listener class="cn.itcast.jbpm.k_event.EventListenerImpl" />
       </on>
       <transition name="to task1" to="发送短信" g="-53,-17"/>
   </start>
   <end name="end1" g="119,301,48,48">
       <!-- 在结束活动的时候进行事件监听 -->
       <on event="start">
          <event-listener class="cn.itcast.jbpm.k_event.EventListenerImpl" />
       </on>
   </end>
   <task name="发送短信" g="97,189,92,52" assignee="张三">
       <!-- 在任务启动的时候进行事件监听 -->
       <on event="start">
          <event-listener class="cn.itcast.jbpm.k_event.EventListenerImpl" />
       </on>
       <!-- 在任务退出的时候进行事件监听 -->
       <on event="end">
          <event-listener class="cn.itcast.jbpm.k_event.EventListenerImpl" />
@SuppressWarnings("serial")
public class EventListenerImpl implements EventListener {

@Override
public void notify(EventListenerExecution execution) throws Exception {
    System.out.println(“触发了事件监听,当前活动为:"+execution.getActivity());
}

}

 

   3.jbpm的具体过程实现

  //获取工作流文件

  URL url = this.getClass().getResource(“test.jpd1.xml”);

  //部署流程定义

  Stirng deploymentID = processEngine.getRepositoryService()

              .createDeployment()

              .addRosourceFromUrl(url)

              .deploy();

  System.out.println(“部署ID:”+deploymentID);

  //启动流程实例

  ProcessInstance pi = processEngine.getExecutionService()

                .startProcessInstanceByKey(“test”);

  System.out.prinln(“流程实例id”+pi.getId());

  //查询我的任务列表

  Task  task = processEngine.getTaskService()

          .createTaskQuery()

          .processInstanceId(pi.getId())

          .uniqueResult();//按照流程实例查询只有一个任务的结果对象

  System.out.println(“任务Id”+task.getId());

  System.out.println(“任务名称”+task.getName());

  System.out.println(“任务的办理人”+task.getAssignee());

  System.out.println(“任务办理时间”+task.getCreateTime());

  //指定连线完成任务

  String outcome = “流程执行的下一步(to end1)”;

  //完成任务

  processEngine.getTaskService()

        .completeTask(task.getId(),outcome);

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/155258.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 关于惠普笔记本电源已接通但不能把电充满

    关于惠普笔记本电源已接通但不能把电充满首先遇到这种情况大家不要慌,不要老想着自己笔记本的什么零件或者什么硬件坏了,如果电量维持在95~100%之间都是正常,因为电池会有一个自我保护的功能,它有一个充电阈值,会使它充的电不超过这个值,还有人专门设置把电量设置在50%左右,朋友的联想电脑好像是可以下载一个联想电脑管家,可以用来调充电阈值,但是貌似惠普的这个充电阈值是不可调的(惠普的这个设定让人无力吐槽)。就像这样插上电源还是这样,…

    2022年8月12日
    5
  • django drf_django 消息队列

    django drf_django 消息队列前言我们上篇文章使用到了Serializer类,可能有小伙伴说太过复杂,那么本篇就为大家带来更加简便的序列化类ModelSerializerModelSerializer先来看下ModelSer

    2022年7月31日
    8
  • 深度学习之pix2pix原理解析「建议收藏」

    今天我来给大家介绍一下基于CGAN的pix2pix模型,给大家简单讲解一下pix2pix的原理。这里我简单给大家CGAN,我用这张图给大家介绍CGAN的原理:CGAN和传统的GAN不同,传统GAN的生成器Generator只是单纯地传入一个随机噪声从而生成一张图片,那么CGAN和传统的GAN有所不同。CGAN的生成器不再只是一个随机噪声,而是传入一张图片z和一个控制条件y去生成一张假的图片…

    2022年4月10日
    47
  • 推荐15个月 Node.js 开发工具

    推荐15个月 Node.js 开发工具

    2022年1月17日
    45
  • STM32的NVIC和中断的总结「建议收藏」

    STM32的NVIC和中断的总结「建议收藏」前言:1.要想学习STM32中断,要先掌握STM32对优先级的定义;2.有51单片机开发经验会比较容易理解中断优先级;3.本篇博文基于STM32F103ZET6芯片和3.5.0标准库编写;4.本篇博文从寄存器入手,最终实现编程的步骤;如有不足之处,还请前辈多多指教;一基础知识1.cortex-m3支持256个中断,其中包含了16个内核中断,240个外部中断。(本博文只介绍

    2022年5月28日
    30
  • redis和zk实现分布式锁有什么区别_redis分布式锁和zk分布式锁区别

    redis和zk实现分布式锁有什么区别_redis分布式锁和zk分布式锁区别前言本文介绍下分布式锁的一个使用场景分享本文的缘由是因为今天在写代码时需要处理一个原子性问题,场景是:业务功能需要先查询数据,再根据数据判断是否要更新数据,在这个查询+更新的过程必然会存在高并发下的原子性问题那么如何解决这个问题呢,那么就要说到我们的主角:分布式锁了分布式锁介绍分布式锁:即在多集群多节点环境下确保只有一个线程可以拿到锁,防止并发出现的问题,类似于synchronized,只不过synchronized不能处理多节点的问题解决上述问题的一种解决方式就是使用分布式锁,虽然性能会比较低

    2022年9月7日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号