• activiti 一个流程的运转步骤 以请假流程为例


    ---为了加深对activiti的理解记忆,对自己做的一个流程进行自述。加强记忆

    请假实例

    一.设计请假的流程图以及流程文件,完善对应数据项,比如用户信息,请假单信息

    --请假单 

     --流程图

    --流程文件leaveBill.bpmn

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
    <process id="LeaveBill" name="LeaveBillProcess" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <userTask id="usertask1" name="提交申请" activiti:assignee="${inputUser}" activiti:formKey="workflowAction_audit.action"></userTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <userTask id="usertask2" name="经纪人审批" activiti:formKey="workflowAction_audit.action">
    <extensionElements>
    <activiti:taskListener event="create" class="cn.itcast.ssh.utils.MangerTaskHandlerCandidateUsers"></activiti:taskListener>
    </extensionElements>
    </userTask>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
    <userTask id="usertask3" name="老总审批" activiti:assignee="王中军" activiti:formKey="workflowAction_audit.action"></userTask>
    <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
    </process>
    <bpmndi:BPMNDiagram id="BPMNDiagram_LeaveBill">
    <bpmndi:BPMNPlane bpmnElement="LeaveBill" id="BPMNPlane_LeaveBill">
    <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
    <omgdc:Bounds height="35.0" width="35.0" x="290.0" y="60.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
    <omgdc:Bounds height="55.0" width="105.0" x="255.0" y="140.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
    <omgdc:Bounds height="55.0" width="105.0" x="255.0" y="230.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
    <omgdc:Bounds height="55.0" width="105.0" x="255.0" y="310.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
    <omgdc:Bounds height="35.0" width="35.0" x="290.0" y="400.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
    <omgdi:waypoint x="307.0" y="95.0"></omgdi:waypoint>
    <omgdi:waypoint x="307.0" y="140.0"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
    <omgdi:waypoint x="307.0" y="195.0"></omgdi:waypoint>
    <omgdi:waypoint x="307.0" y="230.0"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
    <omgdi:waypoint x="307.0" y="285.0"></omgdi:waypoint>
    <omgdi:waypoint x="307.0" y="310.0"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
    <omgdi:waypoint x="307.0" y="365.0"></omgdi:waypoint>
    <omgdi:waypoint x="307.0" y="400.0"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
    </bpmndi:BPMNDiagram>
    </definitions>

    二.准备请假单的增删改查页面,用来处理请假单的生成业务逻辑

    填写好请假单后,就要开始申请请假了。这里主要是更新请假状态,启动请假流程实例。runtimeService.startProcessInstanceByKey(key,objId,variables);key时请假实体类的类名,其实就是一个标识。这里还可以通过流程id来启动startProcessInstanceById

    /**更新请假状态,启动流程实例,让启动的流程实例关联业务*/
    @Override
    public void saveStartProcess(WorkflowBean workflowBean) {
    //1:获取请假单ID,使用请假单ID,查询请假单的对象LeaveBill
    Long id = workflowBean.getId();
    LeaveBill leaveBill = leaveBillDao.findLeaveBillById(id);
    //2:更新请假单的请假状态从0变成1(初始录入-->审核中)
    leaveBill.setState(1);
    //3:使用当前对象获取到流程定义的key(对象的名称就是流程定义的key)
    String key = leaveBill.getClass().getSimpleName();
    /**
    * 4:从Session中获取当前任务的办理人,使用流程变量设置下一个任务的办理人
    * inputUser是流程变量的名称,
    * 获取的办理人是流程变量的值
    */
    Map<String, Object> variables = new HashMap<String,Object>();
    variables.put("inputUser", SessionContext.get().getName());//表示惟一用户
    /**
    * 5: (1)使用流程变量设置字符串(格式:LeaveBill.id的形式),通过设置,让启动的流程(流程实例)关联业务
    (2)使用正在执行对象表中的一个字段BUSINESS_KEY(Activiti提供的一个字段),让启动的流程(流程实例)关联业务
    */
    //格式:LeaveBill.id的形式(使用流程变量)
    String objId = key+"."+id;
    variables.put("objId", objId);
    //6:使用流程定义的key,启动流程实例,同时设置流程变量,同时向正在执行的执行对象表中的字段BUSINESS_KEY添加业务数据,同时让流程关联业务
    runtimeService.startProcessInstanceByKey(key,objId,variables);

    }

    三.启动以后,流程框架会按照你画好的流程图,走到第一个节点,这里说的是除了start节点。也就是申请请假节点。这里设置的申请请假处理人,是当前登录人。随意,当我们启动请假流程后,我们也就有了一个任务,提交申请的任务。查看我们的任务:

    /**2:使用当前用户名查询正在执行的任务表,获取当前任务的集合List<Task>*/
    @Override
    public List<Task> findTaskListByName(String name) {
    List<Task> list = taskService.createTaskQuery()//
    .taskAssignee(name)//指定个人任务查询
    .orderByTaskCreateTime().asc()//
    .list();
    if(null==list||list.size()<1){//如果指定个人任务为空,则查询多人任务
    list = taskService.createTaskQuery().
    taskCandidateUser(name).
    orderByTaskCreateTime().
    asc().
    list();
    }
    if(null==list||list.size()<1){//如果指定多人任务为空在获取组的任务
    list = taskService.createTaskQuery().taskCandidateGroup(name).
    orderByTaskCreateTime().
    asc().
    list();
    }
    return list;
    }

    ---处理我们的任务,使其想下一个节点进行

    public String audit(){
    //获取任务ID
    String taskId = workflowBean.getTaskId();
    /**一:使用任务ID,查找请假单ID,从而获取请假单信息*/
    LeaveBill leaveBill = workflowService.findLeaveBillByTaskId(taskId);
    ValueContext.putValueStack(leaveBill);
    /**二:已知任务ID,查询ProcessDefinitionEntiy对象,从而获取当前任务完成之后的连线名称,并放置到List<String>集合中*/
    List<String> outcomeList = workflowService.findOutComeListByTaskId(taskId);
    ValueContext.putValueContext("outcomeList", outcomeList);
    /**三:查询所有历史审核人的审核信息,帮助当前人完成审核,返回List<Comment>*/
    List<Comment> commentList = workflowService.findCommentByTaskId(taskId);
    ValueContext.putValueContext("commentList", commentList);
    return "taskForm";
    }

    ------获取后续流程节点的信息

    /**二:已知任务ID,查询ProcessDefinitionEntiy对象,从而获取当前任务完成之后的连线名称,并放置到List<String>集合中*/
    @Override
    public List<String> findOutComeListByTaskId(String taskId) {
    //返回存放连线的名称集合
    List<String> list = new ArrayList<String>();
    //1:使用任务ID,查询任务对象
    Task task = taskService.createTaskQuery()//
    .taskId(taskId)//使用任务ID查询
    .singleResult();
    //2:获取流程定义ID
    String processDefinitionId = task.getProcessDefinitionId();
    //3:查询ProcessDefinitionEntiy对象
    ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
    //使用任务对象Task获取流程实例ID
    String processInstanceId = task.getProcessInstanceId();
    //使用流程实例ID,查询正在执行的执行对象表,返回流程实例对象
    ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
    .processInstanceId(processInstanceId)//使用流程实例ID查询
    .singleResult();
    //获取当前活动的id
    String activityId = pi.getActivityId();
    //4:获取当前的活动
    ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);
    //5:获取当前活动完成之后连线的名称
    List<PvmTransition> pvmList = activityImpl.getOutgoingTransitions();
    if(pvmList!=null && pvmList.size()>0){
    for(PvmTransition pvm:pvmList){
    String name = (String) pvm.getProperty("name");
    if(StringUtils.isNotBlank(name)){
    list.add(name);
    }
    else{
    list.add("默认提交");
    }
    }
    }
    return list;
    }

    -------获取完后通过任务id获取历史批注信息

      

    /**获取批注信息,传递的是当前任务ID,获取历史任务ID对应的批注*/
    @Override
    public List<Comment> findCommentByTaskId(String taskId) {
    List<Comment> list = new ArrayList<Comment>();
    //使用当前的任务ID,查询当前流程对应的历史任务ID
    //使用当前任务ID,获取当前任务对象
    Task task = taskService.createTaskQuery()//
    .taskId(taskId)//使用任务ID查询
    .singleResult();
    //获取流程实例ID
    String processInstanceId = task.getProcessInstanceId();
    //使用流程实例ID,查询历史任务,获取历史任务对应的每个任务ID
    List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()//历史任务表查询
    .processInstanceId(processInstanceId)//使用流程实例ID查询
    .list();
    //遍历集合,获取每个任务ID
    if(htiList!=null && htiList.size()>0){
    for(HistoricTaskInstance hti:htiList){
    //任务ID
    String htaskId = hti.getId();
    //获取批注信息
    List<Comment> taskList = taskService.getTaskComments(htaskId);//对用历史完成后的任务ID
    list.addAll(taskList);
    }
    }
    list = taskService.getProcessInstanceComments(processInstanceId);
    return list;
    }

    ----以上信息用来展现将来任务进行的状态,流程图的查看

    四.提交申请,进入下一环节

    /**指定连线的名称完成任务*/
    @Override
    public void saveSubmitTask(WorkflowBean workflowBean) {
    //获取任务ID
    String taskId = workflowBean.getTaskId();
    //获取连线的名称
    String outcome = workflowBean.getOutcome();
    //批注信息
    String message = workflowBean.getComment();
    //获取请假单ID
    Long id = workflowBean.getId();

    /**
    * 1:在完成之前,添加一个批注信息,向act_hi_comment表中添加数据,用于记录对当前申请人的一些审核信息
    */
    //使用任务ID,查询任务对象,获取流程流程实例ID
    Task task = taskService.createTaskQuery()//
    .taskId(taskId)//使用任务ID查询
    .singleResult();
    //获取流程实例ID
    String processInstanceId = task.getProcessInstanceId();
    /**
    * 注意:添加批注的时候,由于Activiti底层代码是使用:
    * String userId = Authentication.getAuthenticatedUserId();
    CommentEntity comment = new CommentEntity();
    comment.setUserId(userId);
    所有需要从Session中获取当前登录人,作为该任务的办理人(审核人),对应act_hi_comment表中的User_ID的字段,不过不添加审核人,该字段为null
    所以要求,添加配置执行使用Authentication.setAuthenticatedUserId();添加当前任务的审核人
    * */
    Authentication.setAuthenticatedUserId(SessionContext.get().getName());
    taskService.addComment(taskId, processInstanceId, message);
    /**
    * 2:如果连线的名称是“默认提交”,那么就不需要设置,如果不是,就需要设置流程变量
    * 在完成任务之前,设置流程变量,按照连线的名称,去完成任务
    流程变量的名称:outcome
    流程变量的值:连线的名称
    */
    Map<String, Object> variables = new HashMap<String,Object>();
    if(outcome!=null && !outcome.equals("默认提交")){
    variables.put("outcome", outcome);
    }

    //3:使用任务ID,完成当前人的个人任务,同时流程变量
    taskService.complete(taskId, variables);
    //4:当任务完成之后,需要指定下一个任务的办理人(使用类)-----已经开发完成

    /**
    * 5:在完成任务之后,判断流程是否结束
    如果流程结束了,更新请假单表的状态从1变成2(审核中-->审核完成)
    */
    ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
    .processInstanceId(processInstanceId)//使用流程实例ID查询
    .singleResult();
    //流程结束了
    if(pi==null){
    //更新请假单表的状态从1变成2(审核中-->审核完成)
    LeaveBill bill = leaveBillDao.findLeaveBillById(id);
    bill.setState(2);
    }
    }

    五.接下来的老总审批和4是完全相同的重复步骤了。不做解释了

          走到最后节点时,流程实例ProcessInstance会为空,则进行业务逻辑处理。完成请假单的所有流程。到这里就结束了。

          工作流的运作轨迹,都在代码中,注释的很清楚。

  • 相关阅读:
    分享一款颜色神器ColorSchemer Studio
    只要你用atom修改后保存代码文件的时候,你在chrome上的页面就会自动刷新。
    十六进制颜色代码
    WordPress窗体化侧边栏
    QQ输入法中英文标点符号快速切换
    Android ListView的item背景色设置以及item点击无响应等相关问题
    Android内存优化(使用SparseArray和ArrayMap代替HashMap)
    [Fatal Error] :3:13: Open quote is expected for attribute "{1}" associated with an element type "id".
    java模式—装饰者模式
    Java模式—适配器模式
  • 原文地址:https://www.cnblogs.com/ANCAN-RAY/p/6647199.html
Copyright © 2020-2023  润新知