Activiti 5.1.4最佳实践

本文详细介绍Activiti工作流引擎的使用方法,包括流程定义、Spring集成配置、流程部署、权限设计等内容。并通过示例代码展示了如何进行流程审批、动态创建流程等高级应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、简单介绍

Activiti是一个开源的工作流引擎,它实现了BPMN 2.0规范,可以发布设计好的流程定义,并通过api进行流程调度。 

Activiti 作为一个遵从 Apache 许可的工作流和业务流程管理开源平台,其核心是基于 Java 的超快速、超稳定的 BPMN 2.0 流程引擎,强调流程服务的可嵌入性和可扩展性,同时更加强调面向业务人员。 

Activiti 流程引擎重点关注在系统开发的易用性和轻量性上。每一项 BPM 业务功能 Activiti 流程引擎都以服务的形式提供给开发人员。通过使用这些服务,开发人员能够构建出功能丰富、轻便且高效的 BPM 应用程序。

2、Activiti  的持久化方式

Activiti 使用 Mybatis3 做持久化工作,可以在配置中设置流程引擎启动时创建表。
Activiti 使用到的表都是 ACT_开头的。
ACT_RE_*:流程定义存储。
ACT_RU_*:流程执行记录,记录流程启动到结束的所有动作,流程结束后会清除相关记录。
ACT_ID_*:用户记录,流程中使用到的用户和组。
ACT_HI_*:流程执行的历史记录。
ACT_GE_*:通用数据及设置。

使用到的表:
ACT_GE_BYTEARRAY:流程部署的数据。
ACT_GE_PROPERTY:通用设置。
ACT_HI_ACTINST:流程活动的实例。
ACT_HI_ATTACHMENT:
ACT_HI_COMMENT:
ACT_HI_DETAIL:
ACT_HI_PROCINST:流程实例。
ACT_HI_TASKINST:任务实例。
ACT_ID_GROUP:用户组。
ACT_ID_INFO:
ACT_ID_MEMBERSHIP:
ACT_ID_USER:用户。
ACT_RE_DEPLOYMENT:部署记录。
ACT_RE_PROCDEF:流程定义。
ACT_RU_EXECUTION:流程执行记录。
ACT_RU_IDENTITYLINK:
ACT_RU_JOB:
ACT_RU_TASK:执行的任务记录。
ACT_RU_VARIABLE:执行中的变量记录。

3、名词解释

关键对象

Deployment:流程部署对象,部署一个流程是创建。

ProcessDefinitions:流程定义,部署成功后自动创建。

ProcessInstances:流程实例,启动流程是创建。

Task:任务,在 Activiti 中的 Task 仅指有角色参与的任务,即定义中的 UserTask。

Execution:执行计划,流程实例和流程执行中的所有节点都是 Execution,如 UserTask、ServiceTask 等。

服务接口

ProcessEngine:流程引擎接口,提供流程管理和运作的所有接口。

RuntimeService:运行时服务接口,提供流程启动服务,运行中流程查询,运行变量设置和获取。

TaskService:用户任务接口(UserTask) ,提供运行时任务查询、领取、完成、删除及变量设置用户管理等服务。

IdentityService:用户和组管理接口。

ManagementService:流程引擎管理接口。

HistoryService:流程处理查询接口,包括执行中流程查询和历史流程查询。

4、Activiti的使用

4.1.  流程定义

 

 

<?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: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="expenseAccount" name="expenseAccount" isExecutable="true">
    <startEvent id="startevent1" name="开始"></startEvent>
    <userTask id="usertask1" name="部门经理">
      <extensionElements>
        <activiti:taskListener event="create" expression="${todoListService.createToDoList(task,execution)}"></activiti:taskListener>
      </extensionElements>
    </userTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway"></exclusiveGateway>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="exclusivegateway1"></sequenceFlow>
    <userTask id="usertask2" name="公司副总审批">
      <extensionElements>
        <activiti:taskListener event="create" expression="${todoListService.createToDoList(task,execution)}"></activiti:taskListener>
      </extensionElements>
    </userTask>
    <exclusiveGateway id="exclusivegateway2" name="Exclusive Gateway"></exclusiveGateway>
    <sequenceFlow id="flow4" sourceRef="usertask2" targetRef="exclusivegateway2"></sequenceFlow>
    <userTask id="usertask3" name="财务审批">
      <extensionElements>
        <activiti:taskListener event="create" expression="${todoListService.createToDoList(task,execution)}"></activiti:taskListener>
      </extensionElements>
    </userTask>
    <sequenceFlow id="flow5" name="同意" sourceRef="exclusivegateway2" targetRef="usertask3">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${AssistantCEOPass}]]></conditionExpression>
    </sequenceFlow>
    <exclusiveGateway id="exclusivegateway3" name="Exclusive Gateway"></exclusiveGateway>
    <sequenceFlow id="flow6" name="同意" sourceRef="exclusivegateway1" targetRef="exclusivegateway3">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${managerPass}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow7" name="价格大于10000" sourceRef="exclusivegateway3" targetRef="usertask2">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${money > 10000}]]></conditionExpression>
    </sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow8" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
    <sequenceFlow id="flow9" name="拒绝" sourceRef="exclusivegateway1" targetRef="endevent1">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${!managePass}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow10" name="价格小于10001" sourceRef="exclusivegateway3" targetRef="usertask3">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${money <= 10000}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="flow11" name="拒绝" sourceRef="exclusivegateway2" targetRef="endevent1">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${!AssistantCEOPass}]]></conditionExpression>
    </sequenceFlow>
  </process>
</definitions>
View Code

4.2.  结合spring(3.X)配置

配置文件:application-activiti-service.xml

<!-- activiti start -->
    
    <!-- 定义 Activiti 配置 -->
    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager" />
        <property name="databaseSchemaUpdate" value="true" />
        
        <property name="jobExecutorActivate" value="false" />
        <property name="activityFontName" value="宋体" />
        <property name="labelFontName" value="宋体"/>
        <property name="idGenerator"><bean class="org.activiti.engine.impl.persistence.StrongUuidGenerator" /></property>
    </bean>

    <!-- 定义流程引擎 -->
    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration" />
    </bean>

    <!-- 定义流程中使用的对象 -->
    <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
    <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
    <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
    <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
    <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />
    
    <!-- activiti end -->
View Code

4.3.  流程部署

可以调用原生接口部署流程

RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment().addClasspathResource("FinancialReportProcess.bpmn20.xml").deploy();
//还可以通过字符串,zip 包,inputStream 等方式部署流程

也可以通过调用下面已抽取好的接口来部署

//@Test
    public void deployProcess(){
        String sourceStr = "C:/WorkSouce/DemoSouce/wef_activiti_demo/src/resource/bpmn/expenseAccount.zip";
        workflowService.deploySingleResource(sourceStr, "expenseAccount");
        System.out.println("================= deploy  success = OK");
    }

自动部署

在配置文件application-activiti-service.xml中加入以下配置即可:

<!-- 自动部署开关 -->
<property name="deploymentResources" value="classpath*:/autodeployment/*.zip" />

4.4.  权限设计

因为activiti本身也有一套权限模块,而我们的业务系统同样也有一套权限,为了不同时去维护两套权限,我们在activiti使用之处加入三张权限关联表,让activiti使用我们业务系统的权限。如下:

1 act_re_gillion_link ,任务节点表,可以动态添加节点

2 act_re_gillion_link_role,节点权限表

3 act_ru_gillion_todo,节点代办事项表

4.5.  最佳实践

Activiti本身提供了几乎所有操作工作流的方法接口,但是为了统一调用以及后期版本升级,我们将activiti自带的方法接口重新抽取成一个服务类WorkflowService供业务系统直接调用。代码如下:

public interface WorkflowService extends BaseService {
    //临时20140504
    public String findNextTaskEntity(String CurrTask);
    /**
     * 通过当前流程实例ID获取下一个运行的UserTask
     * @param procInstID
     * @return
     */
    public String getNextTaskDefinition(String businessId, Map<String,Object> variables);
    
    public SysTodoService getSysTodoService();
    
    public InputStream getCurrResource(String taskId);
    /*
     * 自动部署(non-Javadoc)
     * 
     * @see com.cks.workflow.service.WorkflowService#autoDeployResources()
     */
    public void autoDeployResources();
    /*
     * 部署单个文件(non-Javadoc)
     * 
     * @see
     * com.cks.workflow.service.WorkflowService#deploySingleResource(java.lang
     * .String, java.lang.String)
     */
    public void deploySingleResource(String source, String deployName);
    /**
     *     V1.0 20140417    Bylinrh 通过流程定义ID获取流程定义(non-Javadoc)
     *
     * @author linrh
     * @version v1.0
     * @see
     * com.cks.workflow.service.WorkflowService#findProcessDefinitionById(java
     * .lang.String)
     */
    public ProcessDefinition findProcDefinitionById(
            String processDefinitionId);
    /**
     *     V1.0 20140417    Bylinrh 通过流程定义Key获取最新的流程定义;Key会查询到所有版本(non-Javadoc)
     *
     * @author linrh
     * @version v1.0
     * @see
     * com.cks.workflow.service.WorkflowService#findProcessDefinitionByKeyToLatest(java
     * .lang.String)
     */
    public ProcessDefinition findProcDefinitionByKeyToLatest(
            String processDefinitionKey);
    /**
     *     V1.0 20140417    Bylinrh 通过流程定义Key及变更,启动流程定义实例(non-Javadoc)
     *
     * @parm processDefitioKey:@leave businessKey :业务主键(non-Javadoc)
     * @author linrh
     * @version v1.0
     * @see
     * com.cks.workflow.service.WorkflowService#startProcess(java
     * .lang.String,java.util.Map<String,Object>)
     */
    public ProcessInstance startProcess(String processDefitionKey,
            Map<String, Object> variables);

    /*
     * 进行下一步 用户节点
     * 
     * @parm usertask taskId:任务列表的id (non-Javadoc)
     * 
     * @see
     * com.cks.workflow.service.WorkflowService#signalProcess(java.lang.String,
     * java.util.Map)
     */
    public void signalProcess(String taskId, Map<String, Object> variables);

    /**
     *     V1.0 20140417    Bylinrh 通过流程实例ID获取流程实例信息(non-Javadoc)
     *
     * @author linrh
     * @version v1.0
     * @see
     * com.cks.workflow.service.WorkflowService#findProcessInstanceById(java
     * .lang.String)
     */
    public ProcessInstance findProcInstById(String processInstanceId);
    /**
     *     V1.0 20140417    Bylinrh 通过节点ID获取流程实例信息(non-Javadoc)
     *
     * @author linrh
     * @version v1.0
     * @see
     * com.cks.workflow.service.WorkflowService#findProcessInstanceById(java
     * .lang.String)
     */
    public ProcessInstance findProcInstByTaskId(String taskId);
    /**
     *     V1.0 20140417    Bylinrh 通过业务ID获取流程实例信息(non-Javadoc)
     *
     * @author linrh
     * @version v1.0
     * @see
     * com.cks.workflow.service.WorkflowService#findProcessInstanceByBusinessId(java
     * .lang.String)
     */
    public ProcessInstance findProcInstByBusinessId(String businessId);
    /**
     *     V1.0 20140417    Bylinrh 通过当前任务ID获取流程实例实体(non-Javadoc)
     *
     * @author linrh
     * @version v1.0
     * @see
     * com.cks.workflow.service.WorkflowService#findProcDefinitionEntityByTaskId(java
     * .lang.String)
     */
    public ProcessDefinitionEntity findProcDefinitionEntityByTaskId(String currTaskId);
    /**
     *     V1.0 20140417    Bylinrh 通过流程实例ID获取流程实例实体(non-Javadoc)
     *
     * @author linrh
     * @version v1.0
     * @see
     * com.cks.workflow.service.WorkflowService#findProcDefinitionEntityByProcDefId(java
     * .lang.String)
     */
    public ProcessDefinitionEntity findProcDefinitionEntityByProcDefId(String procDefId);
    /*
     * 获取任务实体(non-Javadoc)
     * 
     * @see
     * com.cks.workflow.service.WorkflowService#findTaskEntityById(java.lang.String)
     */
    public TaskEntity findTaskEntityById(String taskId);
    /*
     * 获取活动的流程 不经常使用(non-Javadoc)
     * 
     * @instanceId 流程ID
     * 
     * @see
     * com.cks.workflow.service.WorkflowService#traceProcess(java.lang.String)
     */
    public InputStream getProcessDiagram(String instanceId);

    /*
     * 部署单个文件(non-Javadoc)
     * 
     * @see
     * com.cks.workflow.service.WorkflowService#deploySingleResource(java.lang
     * .String, java.lang.String)
     */
    public ActivityImpl traceProcess(String instanceId);
    
    /**
     *     V1.0 20140417    Bylinrh 通过当前节点ID获取当前的流程图(non-Javadoc)
     *
     * @author linrh
     * @version v1.0
     * @see
     * com.cks.workflow.service.WorkflowService#getCurrTaskImageStream(java
     * .lang.String)
     */
    public InputStream getCurrTaskImageStream(String taskId);
    

    public InputStream getResourceAsStream(String deploymentId,
            String resourceName);

    public ExecutionEntity findExecutionEntityByTaskId(String taskId);

    /*
     * 通过目录是部署文件(non-Javadoc)
     * 
     * @see
     * com.cks.workflow.service.WorkflowService#deploymentInstance(java.lang
     * .String)
     */
    public Deployment deploymentInstance(String processFilePath);
    
    /**
     * 查询所有流程定义(版本为最新的)
     * @return List<ProcessDefinition>
     */
    public List<ProcessDefinition> findAllLatestVersionProcessDefinitions();
    
    /**
     *     V1.0    20140417    ByLinrh    根据流程定义Key获取所有的用户节点
     * @param processDefinitionKey
     * @return
     * @author linrh
     * @version    V1.0    
     */
    public List<ActivityImpl> findUserTaskActivityImplByProcessDefinitionKey(String processDefinitionKey);
    /**
     *     V1.1    20140417    ByLinrh    根据流程定义ID获取所有的用户节点    修改方法名称
     *     V1.0    20140101    Bybaodk 根据流程定义获取所有节点
     * @param processDefinition
     * @return
     * @author baodk
     * @version    V1.1    
     */
    //@Override
    public List<ActivityImpl> findUserTaskActivityImplByProcessDefinitionId(String processDefinitionId);
    
    /**
     * V1.0        20140417    ByLinrh    根据流程定义Key获取所有节点
     * @param processDefinitionKey
     * @return
     * @author linrh
     * @version V1.0
     */
    public List<ActivityImpl> findActivityImplByProcessDefinitionKey(String processDefinitionKey);
            
    /**
     * V1.0        20140417    ByLinrh    根据流程定义获取所有节点
     * @param processDefinition
     * @return
     * @author linrh
     * @version V1.0
     */
    public List<ActivityImpl> findActivityImplByProcessDefinitionId(String processDefinitionId);
    /*
     * 查询流程实例通过id
     */
    public String findCurrentActivitiImplId(String instanceId);
    
    
    /*
     * 查询业务id获取流程实例id
     */
    public String findCurrentActivitiImplIdByBusinessId(String businessId);
}
View Code

4.5.  单元测试

单元测试包括部署流程、启动流程、流程审批,如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/spring/*.xml"})
public class DynamicAddProcTest {

    @Autowired
    private WorkflowService workflowService;
    @Autowired
    private SysTodoService sysTodoService; 
    @Autowired
    private DynamicActProcService dynamicActProcService;
    
    /**
     * 部署流程
     */
    public void deployProcess(){
        String sourceStr = "C:/WorkSouce/DemoSouce/wef_activiti_demo/src/resource/bpmn/expenseAccount.zip";
        workflowService.deploySingleResource(sourceStr, "expenseAccount");
        System.out.println("================= deploy  success = OK");
    }
    
    /**
     * 启动流程
     */
    //@Test
    public void startProcess(){
        String startProcessName = "processAuto第一个";
        String strBusinessID = UUID.randomUUID().toString();
        String strAssignee = "linrh";
        
        Map<String,Object> variables = new HashMap<String,Object>();
        variables.put(WorkflowConstants.BUSINESS_ID, strBusinessID);
        variables.put(WorkflowConstants.ASSIGNEE_USER,strAssignee);
        ProcessInstance processInstance =  workflowService.startProcess(startProcessName,variables);
        assertNotNull(processInstance);
        
        System.out.println("startProcessTaskID == " + processInstance.getId() + " **** BusinessID=" + strBusinessID );
    }
    
    /**
     * 流程审批
     */
    //@Test
    public void signalProcess(){
        //startProcessTaskID == e57806ff-c3a7-11e3-9b1a-e89a8f8209ae **** BusinessID=79dea4e4-0e27-48fb-9bdb-0c633d85d680
        String taskID = "";
        String strBusinessID = "46903b3b-517b-4e1a-a287-571e5f02e71e";        
        taskID = workflowService.findCurrentActivitiImplIdByBusinessId(strBusinessID);    
        String taskUuid = "";
        
        ActGillionTodo sysTodo = sysTodoService.findSysTodo(strBusinessID, null);
        taskUuid = sysTodo.getTaskInstId();
        
        String strAssignee = "linrh"; 
        
        if(taskUuid != ""){
            
            Map<String,Object> variables = new HashMap<String,Object>();            
            variables.put(WorkflowConstants.ASSIGNEE_USER,strAssignee);            
            workflowService.signalProcess(taskUuid,variables);
        }
        
    }
}
View Code

4.7. 兼容低版本的spring(2.5.6)

Activiti 5.1.4默认支持spring3.0以上版本,如果实际项目的spring版本不是3.0以上,则需要做兼容。这里需要重构processEngineConfiguration,具体实现如下:

1 在配置文件application-activiti-service.xml 的processEngineConfiguration节点下添加以下属性

<!-- Spring2.5表达式支持 -->  
        <property name="expressionManager">  
            <bean class="com.gillion.workflow.util.SpringExpressionManagerFactoryBean">  
                <property name="processEngineConfiguration" ref="processEngineConfiguration"></property>  
            </bean>  
        </property>

2 重构processEngineConfiguration

public class SpringExpressionManagerFactoryBean implements FactoryBean {  
      
      ProcessEngineConfiguration processEngineConfiguration;  
        
      public Object getObject() throws Exception {  
          
          return new SpringExpressionManager(ActSpringManager.getApplicationContext(), ((ProcessEngineConfigurationImpl)processEngineConfiguration).getBeans());  
      }  
    
      public Class getObjectType() {  
          return SpringExpressionManager.class;  
      }  
      
      public boolean isSingleton() {  
          return true;  
      }       
    
      public void setProcessEngineConfiguration(  
              ProcessEngineConfiguration processEngineConfiguration) {  
          this.processEngineConfiguration = processEngineConfiguration;  
      }  
}

4.8. 动态创建并部署流程

在4.1流程定义里面我们可以通过Eclipse的activiti插件来拖拽节点进行流程定义,另外一种方式是根据业务需要,直接采用代码生成的方式进行动态创建流程。

1.  配置

首先,我们在activiti配置文件application-activiti-service.xml中配置spring上下文,以便注入到需要动态创建的类当中,如下:

<!-- Spring上下文,主要用于Dynamic Create UserTask Listener -->
    <bean id="actSpringManager" class="com.gillion.workflow.util.ActSpringManager" scope="singleton"/>

2.  定义接口及实现

 先定义动态流程实体,作为动态创建方法的参数

public class DynamicProcEntity {

    private String procName;
    
    private List<DynamicProcTask> procTasks;

    /**
     * 流程名称
     * @return
     */
    public String getProcName() {
        return procName;
    }

    /**
     * 流程名称
     * @param procName
     */
    public void setProcName(String procName) {
        this.procName = procName;
    }

    /**
     * 流程节点信息列表
     * @return
     */
    public List<DynamicProcTask> getProcTasks() {
        return procTasks;
    }

    /**
     * 流程节点信息列表
     * @param procTasks
     */
    public void setProcTasks(List<DynamicProcTask> procTasks) {
        this.procTasks = procTasks;
    }
    
}
View Code

定义接口

public interface DynamicActProcService extends BaseService {

    public void dynamicCreateProcess(DynamicProcEntity procEntity);
}
View Code

接口实现

public class DynamicActProcServiceImpl extends BaseServiceImpl implements
        DynamicActProcService {

    protected Log logger = LogFactory.getLog(getClass());
        
    @Rule
    public ActivitiRule activitiRule;    

    private ActGillionLinkService actGillionLinkService;
    private ActGillionLinkRoleService actGillionLinkRoleService;    

    private String procPath = "";    

    public void dynamicCreateProcess(DynamicProcEntity procEntity){
        if(procEntity == null || procEntity.getProcName().equals("") ){
            throw new ActivitiException(
                    "请传入正确的值");
        }
        
        BpmnModel model = new BpmnModel();
        Process process = new Process();
        model.addProcess(process);
        
        //create process
        process.setId(procEntity.getProcName());
        process.setName(procEntity.getProcName());
        
        
        
        //create process node
        //startevent1
        process.addFlowElement(createStartEvent());
        //添加用户节点
        for(DynamicProcTask task : procEntity.getProcTasks()){
            process.addFlowElement(CreateUserTask(task));
        }
        //endevent1
        process.addFlowElement(createEndEvent());
        
       //create process SequenceFlow       
        
        List<SequenceFlow> addSeqFlows = this.initSequenceFlow(procEntity.getProcTasks());
        for(SequenceFlow seqflow : addSeqFlows){
            process.addFlowElement(seqflow);
        }
        
        // Generate graphical information
        new BpmnAutoLayout(model).execute();
        
        
        /*try {*/
            
            // 3. Deploy the process to the engine
            String bpmnName = procEntity.getProcName() + ".bpmn";
            Deployment deployment = activitiRule.getRepositoryService().createDeployment()
                .addBpmnModel(bpmnName, model).deploy();
            
            // 4. Start a process instance
            //ProcessInstance processInstance = activitiRule.getRuntimeService()
            //        .startProcessInstanceByKey(procEntity.getProcName());
            
            ProcessDefinition procDef = activitiRule.getRepositoryService().createProcessDefinitionQuery()
                    .deploymentId(deployment.getId()).singleResult();
                    //.processDefinitionId(procEntity.getProcName()).latestVersion().singleResult();
            
            String procID = procDef.getId();
                        
            ActGillionLink addActGillionLink = null;
            String linkID = "";
            for(DynamicProcTask task : procEntity.getProcTasks()){
                addActGillionLink = new ActGillionLink();
                addActGillionLink.setActiveId(task.getTaskID());
                addActGillionLink.setActiveName(task.getTaskName());
                addActGillionLink.setProcessKey(procID);
                addActGillionLink.setRowStatus(BaseObject.ROWSTATUS_ADDED);
                
                linkID = actGillionLinkService.saveOrUpdateLink(addActGillionLink).getLinkId();
                String[] roles = task.getAssignee().split(";");
                if(roles.length > 0){
                    ActGillionLinkRole actGillionLinkRole = null;
                    for(String strRoleID : roles){
                        actGillionLinkRole = new ActGillionLinkRole();
                        actGillionLinkRole.setLinkId(linkID);
                        actGillionLinkRole.setRoleId(strRoleID);
                        actGillionLinkRole.setRowStatus(BaseObject.ROWSTATUS_ADDED);
                        
                        actGillionLinkRoleService.saveOrUpdateLinkrole(actGillionLinkRole);                        
                    }
                }
                
            }
}
/**
     * 创建用户节点
     * @param procTask
     * @return
     */
    protected UserTask CreateUserTask(DynamicProcTask procTask) {
        //添加用户节点 Listener
        ActivitiListener listener = new ActivitiListener();
        listener.setEvent("create");    
        //Spring配置以变量形式调用无法写入,只能通过继承TaskListener方法,
        //By linrh 20140515 
        listener.setImplementationType("class");
        listener.setImplementation("com.workflow.service.impl.TaskExceptionOnCreate");
        
        List<ActivitiListener> actListeners = new ArrayList<ActivitiListener>();
        actListeners.add(listener);

        UserTask userTask = new UserTask();
        userTask.setName(procTask.getTaskName());
        userTask.setId(procTask.getTaskID());
        // userTask.setAssignee(assignee);
        userTask.setTaskListeners(actListeners);
        //userTask.setExtensionElements(createElement());
        return userTask;
    }    

    /**
     * 创建二个节点之间的关键节点
     * @param from
     * @param to
     * @return
     */
    protected SequenceFlow createSequenceFlow(String from, String to) {
        SequenceFlow flow = new SequenceFlow();
        flow.setSourceRef(from);
        flow.setTargetRef(to);
        return flow;
    }

    /**
     * 创建开始结点
     * @return
     */
    protected StartEvent createStartEvent() {
        StartEvent startEvent = new StartEvent();
        startEvent.setId("startevent1");
        startEvent.setName("开始");
        return startEvent;
    }

    /**
     * 创建结束节点
     * @return
     */
    protected EndEvent createEndEvent() {
        EndEvent endEvent = new EndEvent();
        endEvent.setId("endevent1");
        endEvent.setName("结束");
        return endEvent;
    }
    
    /**
     * 通过用户节点列表添加所有连接节点
     * @param tasks
     * @return
     */
    protected List<SequenceFlow> initSequenceFlow(List<DynamicProcTask> tasks){
        List<SequenceFlow> workedSeqFlow = new ArrayList<SequenceFlow>();
        
        int i= 0;
        int lstSize = tasks.size();
        String prexTaskid = "";
        
        for(DynamicProcTask task:tasks){
            if(i == 0){
                workedSeqFlow.add(createSequenceFlow("startevent1", task.getTaskID()));
            }else if(i == (lstSize - 1)){
                workedSeqFlow.add(createSequenceFlow(prexTaskid,task.getTaskID()));
                workedSeqFlow.add(createSequenceFlow(task.getTaskID(),"endevent1"));
            }else{
                workedSeqFlow.add(createSequenceFlow(prexTaskid,task.getTaskID()));
            }
            prexTaskid = task.getTaskID();
            i = i + 1;
        }
                
        return workedSeqFlow;
    }
    
    /**
     * 拆分权限组
     * @param linkRoleValue
     * @return
     */
    private List<String> splitRole(String linkRoleValue){
        if(linkRoleValue == ""){
            return null;
        }
        
        String[] roles = linkRoleValue.split(";");
        List<String> roleLst = new ArrayList<String>();
        for(String str : roles){
            roleLst.add(str);
        }
        
        return roleLst;
    }
}
View Code

3.  单元测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/spring/*.xml"})
public class DynamicProceTest {

    @Autowired
    private WorkflowService workflowService;
    
    @Autowired
    private DynamicActProcService dynamicActProcService;
    
    /**
     * 创建流程
     */
    @Test
    public void createProcess(){
        DynamicProcEntity entity = new DynamicProcEntity();
        //entity.se
        List<DynamicProcTask> taskList = new ArrayList<DynamicProcTask>();
        taskList.add(new DynamicProcTask("",1,"task1","我是第一",""));
        taskList.add(new DynamicProcTask("",2,"task2","我是第二",""));
        taskList.add(new DynamicProcTask("",3,"task3","我是第三",""));
        
        entity.setProcName("processAuto第一个");
        entity.setProcTasks(taskList);
        
        dynamicActProcService.dynamicCreateProcess(entity);
        
        
    }
}
View Code

 

转载于:https://www.cnblogs.com/jager/p/4372769.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值