• jbpm工作流


    一、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

        

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

      

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

      活动环节:

        任务(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

        

    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)

      

      

    @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、个人任务

     

    @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

        事件

      

    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);

  • 相关阅读:
    Java Lambda 表达式 对 Map 对象排序
    比较两个list对象是否相同
    ubuntu redis 自启动配置文件(关机有密码)
    spring中订阅redis键值过期消息通知
    网站架构之性能优化(转)
    Json转Java Bean
    spring mvc 4 校验
    java @ResponseBody返回值中去掉NULL字段
    合并两个java bean对象非空属性(泛型)
    spring mvc 删除返回字符串中值为null的字段
  • 原文地址:https://www.cnblogs.com/jinb/p/6789427.html
Copyright © 2020-2023  润新知