Activiti 5.1.4最佳实践

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

 

posted @ 2015-03-27 20:22  Jager  阅读(1293)  评论(0编辑  收藏  举报