Activity工作流詳解和封裝(流程定義部署之ZIP方式)


首先兩張圖說明Activity的23張表的含義,可去官網獲取:(以下代碼一些返回格式和數據庫查詢就不具體說明了

流程定義部署之ZIP方式可以百度下

pom.xml

<!-- activiti -->
<dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-engine</artifactId>
      <version>5.14</version>
</dependency>

<dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-json-converter</artifactId>
      <version>5.14</version>
</dependency>

<dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring</artifactId>
      <version>5.14</version>
</dependency>

activtiy.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
    <!-- Activiti配置 -->
    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <property name="dataSource" ref="localDataSource"/>
        <property name="transactionManager" ref="localTransactionManager"/>
        <property name="databaseSchemaUpdate" value="true"/>
        <property name="jobExecutorActivate" value="false"/>
        <property name="activityFontName" value="微軟雅黑"/>
        <property name="labelFontName" value="微軟雅黑"/>
    </bean>

    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean" destroy-method="destroy">
        <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"/>
    <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>
</beans>

注意:要在Srping管理文件application.xml用以下方式引入:

<!-- activiti配置引入 -->
<import resource="activiti.xml"></import>

IActivitiService.java

/**
 * Author:47Gamer
 */import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;

import com.sckj.base.entity.admin.Person;
import com.sckj.base.service.IBaseService;
import com.sckj.base.vo.ComboVo;
import com.sckj.macb.query.ListVo;

import net.sf.json.JSONObject;

/**
 * Activity相關服務接口
 * @author 47Gamer
 */
public interface IActivitiService extends IBaseService {

    /** 自定義模塊的business Key **/
    public static final String DEFINITION_KEY = "definitionKey";


    /**
     * 部署一個流程定義,傳入該流程定義的名稱,名稱必須唯一
     * 只有被部署過的流程定義才能通過其啟動新的流程實例
     *@author 47Gamer
     *@date 2019-3-6
     *@param definitionName
     *@return void
     */
    public void deployProcessDefinition(String definitionName);

    /**
     * 獲取待部署的流程定義
     *@author 47Gamer
     *@date 2019-3-10
     *@return
     *@return List<ComboVo>
     */
    public List<ComboVo> getWaitDefinition();

    /**
     * 獲取已發布的流程定義
     *@author 47Gamer
     *@date 2019-3-10
     *@return
     *@return List<Object>
     */
    public List<Object> getProcessDefinitionList();


    /**
     * 通過自定義流程表id獲取對應的流程的流程定義的部署id
     *@author 47Gamer
     *@date 2019-3-14
     *@param processInfoId
     *@return
     *@return String
     */
    public String getDeployIdByProcessInfoId(String processInfoId);

    /**
     * 通過一個已發布的部署id來刪除流程定義
     * 如果當前存在相關聯的並且未結束的流程實例,則該方法不起作用
     *@author 47Gamer
     *@date 2019-3-6
     *@param id
     *@return void
     */
    public void deleteDeployment(String deploymentIds);

    /**
     * 通過一個已發布的部署id來級聯刪除流程定義
     * 級聯刪除:如果存在與id指向的流程定義的流程實例(包括歷史流程與未結束的流程以及相關的job),則一並刪除
     * 如果不存在則相當於deleteDeployment()這個方法
     * 該方法請慎用
     *@author 47Gamer
     *@date 2019-3-6
     *@param id
     *@return void
     */
    public void deleteDeploymentCascade(String deploymentIds);

    /**
     * 通過一個已發布的流程定義key來啟動一個流程,輸入業務鍵
     * params 為啟動參數,可以為空
     *@author 47Gamer
     *@date 2019-3-6
     *@param key
     *@return void
     */
    public Integer startProcessInstanceByKey(String key, String businessKey, Map<String, Object> params, Person person);

    /**
     * 通過一個已發布的流程定義id來啟動一個流程
     * params 為啟動參數,可以為空
     *@author 47Gamer
     *@date 2019-3-6
     *@param id
     *@return void
     */
    public Integer startProcessInstanceById(String id, Map<String, Object> params, Person person);

    /**
     * 通過流程實例id返回一個歷史流程實例,如果不存在則返回null
     *@author 47Gamer
     *@date 2019-3-6
     *@param id
     *@return ProcessInstance
     */
    public HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId);

    /**
     * 通過流程實例id返回一個正在進行的流程實例,如果流程不存在或者指定的流程已線結束則返回null
     *@author 47Gamer
     *@date 2019-3-6
     *@param id
     *@return ProcessInstance
     */
    public ProcessInstance getProcessInstanceById(String processInstanceId);

    /**
     * 通過流程實例id來刪除一個正在運流中的流程實例,同時刪除T_PROCESSINFO表的數據
     *@author 47Gamer
     *@date 2019-3-6
     *@param processInstanceId
     *@return void
     */
    public void deleteProcessInstance(String processInstanceId, String processInstanceInfoId, String deleteReason);

    /**
     * 通過參數分頁查詢流程實例,包括歷史流程
     *@author 47Gamer
     *@date 2019-3-6
     *@param params
     *@return ListVo<Object>
     */
    public ListVo<Object> getProcessInstanceList(Map<String, Object> params);

    /**
     * 向執中中發送一個觸發器信號,使流程繼續向下走
     * 使用該方法的前提是,流程圖中有至少有一個state活動節點,當流程流向該節點時會使流程陷入等待
     * 通過調用該方法使流程得以繼續
     *@author 47Gamer
     *@date 2019-3-6
     *@param executionId
     *@return void
     */
    public void signal(String executionId, @SuppressWarnings("unchecked") Map<String, Object>... pamras);

    /**
     * 通過變量名獲取一個執行上下文中的變量值
     *@author 47Gamer
     *@date 2019-3-6
     *@param executionId
     *@param variableName
     *@return Object
     */
    public Object getExecutionVariable(String executionId, String variableName);

    /**
     * 獲取執行上下文的所有變量
     *@author 47Gamer
     *@date 2019-3-6
     *@param executionId
     *@return Map<String, Object>
     */
    public Map<String, Object> getExecutionVariables(String executionId);

    /**
     * 向一個執行上下文中存入一個變量值
     * 如果對應的variableName已存在於執行上下文中,則新賦予的值會覆蓋以前的值
     *@author 47Gamer
     *@date 2019-3-6
     *@param executionId
     *@param variableName
     *@param value
     *@return void
     */
    public void setExecutionVariable(String executionId, String variableName, String value);

    /**
     * 向一個執行上下文中批量存入變量值
     * 如果對應的variableName已存在於執行上下文中,則新賦予的值會覆蓋以前的值
     *@author 47Gamer
     *@date 2019-3-6
     *@param executionId
     *@param pamras
     *@return void
     */
    public void setExecutionVariables(String executionId, Map<String, Object> pamras);

    /**
     * 簽收任務:當一個用戶處於一個任務的候選人員中時,在完成任務前需要先將組任務接替為個人任務
     * 調用此方法即可
     * 候選人員:一個任務的候選人員中,或者屬於一個任務的分配組中
     *@author 47Gamer
     *@date 2019-3-6
     *@param userId
     *@param taskId
     *@return void
     */
    public void takeTask(String userId, String taskId);

    /**
     * 通過變量名獲取一個任務上下文中的變量值
     *@author 47Gamer
     *@date 2019-3-6
     *@param executionId
     *@param variableName
     *@return Object
     */
    public Object getTaskVariable(String taskId, String variableName);

    /**
     * 獲取任務上下文的所有變量
     *@author 47Gamer
     *@date 2019-3-6
     *@param executionId
     *@return Map<String, Object>
     */
    public Map<String, Object> getTaskVariables(String taskId);

    /**
     * 向一個任務上下文中存入一個變量值
     * 如果對應的variableName已存在於任務上下文中,則新賦予的值會覆蓋以前的值
     *@author 47Gamer
     *@date 2019-3-6
     *@param executionId
     *@param variableName
     *@param value
     *@return void
     */
    public void setTaskVariable(String taskId, String variableName, String value);

    /**
     * 向任務上下文中批量存入變量值
     * 如果對應的variableName已存在於執行上下文中,則新賦予的值會覆蓋以前的值
     *@author 47Gamer
     *@date 2019-3-6
     *@param executionId
     *@param pamras
     *@return void
     */
    public void setTaskVariables(String taskId, Map<String, Object> pamras);

    /**
     * 斷言指定的用戶是否擁有指定的任務
     *@author 47Gamer
     *@date 2019-3-11
     *@param userId
     *@param taskId
     *@return
     *@return boolean
     */
    public void assertUserTask(String userId, String taskId);

    /**
     * 斷言流程是否結束,如果結束返回結束結點的名稱,否則返回null
     *@author 47Gamer
     *@date 2019-3-13
     *@param taskId
     *@return void
     */
    public String assertProcessInstanceEnd(String processId);

    /**
     * 完成任務,將流程從該任務流向下一任務,如果這是最后一個任務,則流程結束
     * 不帶參數
     *@author 47Gamer
     *@date 2019-3-6
     *@param taskId
     *@return void
     */
    public String completeTask(String userId, String taskId);

    /**
     * 完成任務,將流程從該任務流向下一任務,如果這是最后一個任務,則流程結束
     * params中針對不同的任務會有不同的參數
     *@author 47Gamer
     *@date 2019-3-6
     *@param params
     *@return void
     */
    public String completeTask(String userId, String taskId, Map<String, Object> params);

    /**
     * 獲取指定用戶的個人待辦任務
     * params必須包含一個userId
     *@author 47Gamer
     *@date 2019-3-6
     *@param params
     *@return ListVo<Task>
     */
    public List<Task> getPersonalTask(Map<String, Object> params);

    /**
     * 通過流程實例id獲取流程圖,前提是在上傳的zip資源包上有
     *@author 47Gamer
     *@date 2019-3-6
     *@param deploymentId
     *@return InputStream
     */
    public InputStream getImage(String processInstanceId);

    /**
     * 添加activiti的用戶,這里我們將該用戶映射為業務系統的User
     * 因為要關聯業務系統的用戶管理,所以要保證activiti的用戶表與業務系統的用戶表同步
     * 因此該方法一般是在業務系統addUser方法之后調用,並且必須在一個事務中
     * 備注:因為中文名字不存在firstName,lastName之說,所以這里我們約定
     * firstName存入用戶的真實姓名,lastName存入用戶的登錄名
     * 如果在流程中有事件觸發機制,比如啟動發郵件,那么email必須傳入,如果沒有傳入空字符串
     * 如果指定的userId已存在則該方法會執行update操作。
     *@author 47Gamer
     *@date 2019-3-6
     *@param id
     *@param firstName
     *@param lastName
     *@param email
     *@param password
     *@return void
     */
    public void saveUser(String id, String firstName, String lastName, String email, String password);

    /**
     * 刪除一個用戶,如果指定的userId不存在,該方法將被ignored
     *@author 47Gamer
     *@date 2019-3-11
     *@param id
     *@return void
     */
    public void deleteUser(String ids);

    /**
     * 添加activiti用戶組,這里我們將該用戶組映射為業務系統的角色Role
     * 如果指定的groupId存在,則執行update操作
     * 該方法一般是在業務系統addRole方法之后調用
     *@author 47Gamer
     *@date 2019-3-6
     *@param id
     *@param name
     *@param type
     *@return void
     */
    public void saveGroup(String id, String name, String type);

    /**
     * 刪除一個已存在的工作組
     * 如果指定的groupId不存在,指該方法將被ignored
     *@author 47Gamer
     *@date 2019-3-11
     *@param id
     *@return void
     */
    public void deleteGroup(String ids);

    /**
     * 添加activiti用戶與組的關系,這里我們將該關系映射為業務系統的UserRole
     * 該方法一般是在業務系統addUserRole方法之后
     *@author 47Gamer
     *@date 2019-3-6
     *@param userId
     *@param groupId
     *@return void
     */
    public void createMembership(String userId, String groupId);

    /**
     * 刪除activiti用戶與組的關系
     * 該方法一般是在業務系統deleteUserRole方法之后
     *@author 47Gamer
     *@date 2019-3-6
     *@param userId
     *@param groupId
     *@return void
     */
    public void deleteMembership(String userId, String groupId);

    /**
     * 上傳新的流程定義模板,當前上傳的.zip的名字在存放資源包的路徑下存在,則當前上傳會覆蓋以前的資源包
     *@author 47Gamer
     *@date 2019-3-12
     *@param file
     *@param fileName
     *@return void
     */
    public void uploadProcessInstanceDefinition(File temp, String fileName);

    /**
     * 瀏覽服務器存在的資源包,以樹的形式展示
     *@author 47Gamer
     *@date 2019-3-12
     *@return void
     */
    public String viewServerZip();

    /**
     * 刪除服務器的zip資源包
     *@author 47Gamer
     *@date 2019-3-12
     *@param fileName
     *@return void
     */
    public void deleteServerZip(String fileName);

    /**
     * 查看流程定義的png圖片
     *@author 47Gamer
     *@date 2019-3-12
     *@return
     *@return InputStream
     */
    public InputStream viewProcessInstancePng(String deployId);

    /**
     * 查看流程定義的bpmn定義
     *@author 47Gamer
     *@date 2019-3-12
     *@return
     *@return InputStream
     */
    public InputStream viewProcessInstanceBpmn(String deployId);

    /**
     * 獲取流程過程
     *@author 47Gamer
     *@date 2019-3-14
     *@param processId
     *@return
     *@return JSONObject
     */
    public JSONObject getProcessIntanceProcedure(String processId);

    /**
     * 通過執行上下文id獲取自定義流程信息
     * @param executionId
     * @return Object
     */
    public Object getProcessInfoByExecutionId(String executionId);

    /**
     * 獲取模板名稱即中文名
     * @return
     */
    public String getTemplateName(String definitionInfoId);


    /**
     * 保存流程執行環節的變量,通常是審批意見與審批結果
     * @param processInfoId
     * @param taskId
     * @param variables
     */
    public void saveProcessLinkVariables(String processInfoId, String taskId, Map<String, Object> variables, Person person, String result);

    /**
     * 獲取流程環節變量
     * @param processId
     * @param taskName
     * @return
     */
    public List<Object> getProcessLinkVariables(String processId, String taskName);

    /**
     * 根據taskId獲取任務
     *@author 47號Gamer
     *@date 2019-4-17
     *@param taskId
     *@return Task
     */
    public Task getTaskById(String taskId);

    public void deleteUserIdentityLink(String taskId, String userIds, String identityLinkType);

    public void addUserIdentityLink(String taskId, String userIds, String identityLinkType);

    /**
     * 根據processInfoId獲取當前task
     *
     *@author 47號Gamer
     *@date 2019-8-27
     *@param processInfoId
     *@return Map<String, Object>
     */
    public Map<String, Object> getTaskByProcessInfoId(int processInfoId);

    /**
     * 刪除歷史流程
     * @author 47Gamer
     * @date 2017-2-24
     * @param processIntanceId
     * void
     *
     */
    public void deleteHistoryProcessIntance(String executionId);

    /**
     * 檢索與特定任務相關的identitylinks。
     * @param taskId
     * @return
     */
    public List<IdentityLink> getIdentityLinksForTask(String id);

    /**
     * 刪除的identitylinktype候選組和任務之間的關聯
     * @param taskId
     * @param groupIds
     * @param identityLinkType
     */
    public void deleteCandidateGroup(String id, String groupId);

    /**
     * 添加的identitylinktype候選用戶和任務之間的關聯
     * @param taskId
     * @param groupIds
     * @param identityLinkType
     */
    public void addCandidateUser(String id, String ids);
}

ActivitiServiceImpl.java

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.ProcessEngineImpl;
import org.activiti.engine.impl.bpmn.diagram.ProcessDiagramGenerator;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.persistence.entity.GroupEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.ibatis.session.RowBounds;
import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sckj.base.common.constant.SystemConstant;
import com.sckj.base.entity.activiti.ProcessDefinitionInfo;
import com.sckj.base.entity.activiti.ProcessInfo;
import com.sckj.base.entity.activiti.ProcessVariable;
import com.sckj.base.entity.admin.Person;
import com.sckj.base.exception.ServiceException;
import com.sckj.base.service.BaseServiceImpl;
import com.sckj.base.util.DateUtil;
import com.sckj.base.vo.ComboVo;
import com.sckj.macb.query.IObjectQuery;
import com.sckj.macb.query.ListVo;
import com.sckj.macb.query.ObjectQueryImpl;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * Activity相關服務實現
 * @author 47Gamer
 */
@Service(value = "activitiService")
public class ActivitiServiceImpl extends BaseServiceImpl implements IActivitiService {

  

   /**activiti存放資源包的路徑,相對於WebContent的相對路徑*/
   public static final String ACTIVITI_PATH = "activiti";


    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private IdentityService identityService;

    @Override
    public void deployProcessDefinition(String definitionName) {
        try {
            String definitionNameEn = definitionName.split("[-]")[0];
            String definitionNameCn = definitionName.split("[-]")[1];
            String ACTIVITI_PATH = ServletActionContext.getServletContext().getRealPath(SystemConstant.ACTIVITI_PATH);
            File file = new File(ACTIVITI_PATH + File.separator + definitionName + ".zip");
            InputStream in = new FileInputStream(file);
            ZipInputStream zis = new ZipInputStream(in);
            DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
            deploymentBuilder.addZipInputStream(zis).category(definitionNameEn).name(definitionNameEn);
            Deployment deployment = deploymentBuilder.deploy();
            ProcessDefinitionInfo processDefinitionInfo = new ProcessDefinitionInfo();
            processDefinitionInfo.setDeployId(deployment.getId());
            processDefinitionInfo.setDefinitionName(definitionNameEn);
            processDefinitionInfo.setTemplateName(definitionNameCn);
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
            processDefinitionInfo.setKeyVersion(pd.getVersion());
            this.add(processDefinitionInfo);
        } catch (ActivitiException e) {
            throw new ServiceException(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e);
        }
    }

    @Override
    public List<ComboVo> getWaitDefinition() {
        List<ComboVo> list = new ArrayList<ComboVo>();
        String ACTIVITI_PATH = ServletActionContext.getServletContext().getRealPath(SystemConstant.ACTIVITI_PATH);
        File[] fileList = new File(ACTIVITI_PATH).listFiles();
        ComboVo vo = null;
        Integer index = null;
        for (File file : fileList) {
            vo = new ComboVo();
            String name = file.getName();
            index = name.lastIndexOf("-");
            if (index == -1) {
                continue;
            }
            vo.setValue(name.substring(0, index));
            vo.setDisplayValue(name.substring(index + 1, name.length() - 4));
            list.add(vo);
        }
        return list;
    }

    @Override
    public List<Object> getProcessDefinitionList() {
        ListVo<Object> listVo = new ListVo<Object>();
        try {
            IObjectQuery<ProcessDefinitionInfo> query = new ObjectQueryImpl<ProcessDefinitionInfo, Integer>(ProcessDefinitionInfo.class);
            query.orderAsc("templateName").orderAsc("keyVersion");
            listVo = this.mybatisDao.getObjectPage(query.sqlMap(), null);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        return listVo.getList();
    }

    @SuppressWarnings("unchecked")
    @Override
    public String getDeployIdByProcessInfoId(String processInfoId) {
        try {
            IObjectQuery<ProcessInfo> query = new ObjectQueryImpl<ProcessInfo, Integer>(ProcessInfo.class);
            query.equals("id", processInfoId);
            List<Object> list = this.mybatisDao.getObjectList(query.sqlMap());
            Map<String, Object> map = (Map<String, Object>) list.get(0);
            String processId = map.get("processId") + "";
            String definitionId = this.getHistoricProcessInstanceById(processId).getProcessDefinitionId();
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery().processDefinitionId(definitionId).singleResult();
            return pd.getDeploymentId() + "@" + processId;
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void deleteDeployment(String deploymentIds) {
        try {
            Map<String, Object> params = new HashMap<String, Object>();
            String[] idArray = deploymentIds.split(",");
            for (String id : idArray) {
                repositoryService.deleteDeployment(id);
                params.put("deployId", id);
                this.mybatisDao.delete("activiti.deleteSystemDefinition", params);
            }
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void deleteDeploymentCascade(String deploymentIds) {
        try {
            Map<String, Object> params = new HashMap<String, Object>();
            String[] idArray = deploymentIds.split(",");
            for (String id : idArray) {

                /** 執行activity的徹底刪除流程定義操作 **/
                repositoryService.deleteDeployment(id, true);

                params.put("deployId", id);

                /** 刪除系統表存儲的流程實例保存的變量 **/
                this.mybatisDao.delete("activiti.deleteProcessInstanceVariableByDeployId", params);

                /** 刪除系統表存儲的流程**/
                this.mybatisDao.delete("activiti.deleteSystemProcessInstance", params);

                /** 刪除系統表存儲的流程定義 **/
                this.mybatisDao.delete("activiti.deleteSystemDefinition", params);
            }
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public Integer startProcessInstanceByKey(String key, String businessKey, Map<String, Object> params, Person person) {
        try {
            List<ProcessDefinition> processDefinitions = this.repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).list();
            if (processDefinitions == null || processDefinitions.size() == 0) {
                throw new ServiceException("流程啟動異常,沒有找到相關流程定義!");
            }
            ProcessInstance pi = this.runtimeService.startProcessInstanceByKey(key, params);
            ProcessDefinition lastProcessDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).latestVersion().singleResult();
            IObjectQuery<ProcessDefinitionInfo> query = new ObjectQueryImpl<ProcessDefinitionInfo, Integer>(ProcessDefinitionInfo.class);
            query.equals("deployId", lastProcessDefinition.getDeploymentId());
            Map<String, Object> object = (Map<String, Object>) (this.mybatisDao.getObjectList(query.sqlMap()).get(0));
            ProcessInfo processInfo = new ProcessInfo();
            processInfo.setProcessId(pi.getId());
            processInfo.setDefinitionInfoId(NumberUtils.toInt(object.get("id") + ""));
            processInfo.setUserCardId(person.getCard());
            processInfo.setStatus("active");
            processInfo.setProcessType(key);
            processInfo.setCreateDate(new Date());
            processInfo.setUserName(person.getUserName());
            processInfo.setBusinessKey(businessKey);
            this.add(processInfo);
            return processInfo.getId();
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public Integer startProcessInstanceById(String id, Map<String, Object> params, Person person) {
        try {
            ProcessDefinition processDefinition = this.repositoryService.createProcessDefinitionQuery().processDefinitionId(id).singleResult();
            if (processDefinition == null) {
                throw new ServiceException("流程啟動異常,沒有找到相關流程定義!");
            }
            ProcessInstance pi = this.runtimeService.startProcessInstanceById(id, params);
            IObjectQuery<ProcessDefinitionInfo> query = new ObjectQueryImpl<ProcessDefinitionInfo, Integer>(ProcessDefinitionInfo.class);
            query.equals("deployId", processDefinition.getDeploymentId());
            Map<String, Object> object = (Map<String, Object>) (this.mybatisDao.getObjectList(query.sqlMap()).get(0));
            ProcessInfo processInfo = new ProcessInfo();
            processInfo.setProcessId(pi.getId());
            processInfo.setDefinitionInfoId(NumberUtils.toInt(object.get("id") + ""));
            processInfo.setUserCardId(person.getCard());
            processInfo.setStatus("active");
            processInfo.setProcessType(object.get("definitionName") + "");
            processInfo.setCreateDate(new Date());
            processInfo.setUserName(person.getUserName());
            this.add(processInfo);
            return processInfo.getId();
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId) {
        HistoricProcessInstance historicProcessInstance = null;
        try {
            historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        return historicProcessInstance;
    }

    @Override
    public ProcessInstance getProcessInstanceById(String processInstanceId) {
        ProcessInstance processInstance = null;
        try {
            processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        return processInstance;
    }

    @Override
    public void deleteProcessInstance(String processInstanceId, String processInstanceInfoId, String deleteReason) {
        try {
            runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
            Map<String, Object> param = new HashMap<String, Object>();
            param.put("processinfoId", processInstanceInfoId);
            param.put("complateDate", DateUtil.dateToString(new Date(), "yyyy-MM-dd HH:mm:ss"));
            this.mybatisDao.update("activiti.updateProcessInstanceWhenDeleteProcess", param);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public ListVo<Object> getProcessInstanceList(Map<String, Object> params) {
        ListVo<Object> listVo = new ListVo<Object>();
        try {
            String start = params.get("start") + "";
            String limit = params.get("limit") + "";
            Object status = params.get("status");
            IObjectQuery<ProcessInfo> query = new ObjectQueryImpl<ProcessInfo, Integer>(ProcessInfo.class);
            query.equals("status", status).orderDesc("status").orderDesc("id");
            RowBounds rowBounds = new RowBounds(NumberUtils.toInt(start), NumberUtils.toInt(limit));
            listVo = this.mybatisDao.getObjectPage(query.sqlMap(), rowBounds);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        return listVo;
    }

    public void signal(String executionId, @SuppressWarnings("unchecked") Map<String, Object>... pamras) {
        try {
            if (pamras.length == 0) {
                runtimeService.signal(executionId);
                return;
            }
            runtimeService.signal(executionId, pamras[0]);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    public Object getExecutionVariable(String executionId, String variableName) {
        Object object = null;
        try {
            object = runtimeService.getVariable(executionId, variableName);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        return object;
    }

    public Map<String, Object> getExecutionVariables(String executionId) {
        Map<String, Object> object = null;
        try {
            object = runtimeService.getVariables(executionId);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        return object;
    }

    public void setExecutionVariable(String executionId, String variableName, String value) {
        try {
            runtimeService.setVariable(executionId, variableName, value);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    public void setExecutionVariables(String executionId, Map<String, Object> pamras) {
        try {
            if (null == pamras)
                return;
            runtimeService.setVariables(executionId, pamras);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void takeTask(String userId, String taskId) {
        try {
            taskService.claim(taskId, userId);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e);
        }
    }

    public Object getTaskVariable(String taskId, String variableName) {
        Object object = null;
        try {
            object = taskService.getVariable(taskId, variableName);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e);
        }
        return object;
    }

    public Map<String, Object> getTaskVariables(String taskId) {
        Map<String, Object> object = null;
        try {
            object = taskService.getVariables(taskId);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        return object;
    }

    public void setTaskVariable(String taskId, String variableName, String value) {
        try {
            taskService.setVariable(taskId, variableName, value);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    public void setTaskVariables(String taskId, Map<String, Object> pamras) {
        try {
            if (null == pamras)
                return;
            taskService.setVariables(taskId, pamras);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void assertUserTask(String userId, String taskId) {
        try {
            List<Task> assignTaskList = taskService.createTaskQuery().taskAssignee(userId).list();
            for (Task task : assignTaskList) {
                if (task.getId().equals(taskId)) {
                    return;
                }
            }
            throw new ServiceException("候選任務還沒有被分配,或者用戶不具有該任務!");
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public String assertProcessInstanceEnd(String processId) {
        return this.assertProcessEnd(processId, false);
    }

    public String assertProcessEnd(String processId, boolean flag) {
        ProcessInstance pi = this.getProcessInstanceById(processId);
        HistoricProcessInstance hpi = this.getHistoricProcessInstanceById(processId);
        if (null == hpi) {
            throw new ServiceException("指定的流程不存在!");
        }
        if (pi == null) {
            if (flag) {
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("processId", processId);
                params.put("complateDate", DateUtil.dateToString(new Date(), "yyyy-MM-dd HH:mm:ss"));
                this.mybatisDao.update("activiti.updateProcessInfoStatus", params);
            }
            HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
            @SuppressWarnings("deprecation")
            HistoricActivityInstance endActivity = historicActivityInstanceQuery.processInstanceId(processId).activityId(hpi.getEndActivityId()).singleResult();
            return endActivity.getActivityName();
        }
        return null;
    }

    @Override
    public String completeTask(String userId, String taskId) {
        return this.complete(userId, taskId, null);
    }

    @Override
    public String completeTask(String userId, String taskId, Map<String, Object> params) {
        return this.complete(userId, taskId, params);
    }

    public String complete(String userId, String taskId, Map<String, Object> params) {
        try {
            assertUserTask(userId, taskId);
            String processInstanceId = taskService.createTaskQuery().taskId(taskId).singleResult().getProcessInstanceId();
            taskService.complete(taskId, params);
            return assertProcessEnd(processInstanceId, true);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
    }

    @Override
    public List<Task> getPersonalTask(Map<String, Object> params) {
        List<Task> list = new ArrayList<Task>();
        String userId = params.get("card") + "";
        /** only select tasks which are assigned to the given user.  **/
        list.addAll(taskService.createTaskQuery().taskAssignee(userId).list());

        /** only select tasks for which the given user is a candidate.  **/
        list.addAll(taskService.createTaskQuery().taskCandidateUser(userId).list());
        
        /*String userGroupQuerySQL = "SELECT ap.* FROM ACT_ID_MEMBERSHIP am, ACT_ID_GROUP ap WHERE am.GROUP_ID_ = ap.ID_ AND am.USER_ID_ = '"+userId+"'";
        List<Group> userGroups = identityService.createNativeGroupQuery().sql(userGroupQuerySQL).list();
        for(Group g : userGroups){
            obj = taskService.createTaskQuery().taskCandidateGroup(g.getId()).list();
            list.addAll(obj);
        }*/
        return list;
    }

    public List<Task> filterTasks(List<Task> taskList, String realId) {
        List<Task> tasks = new ArrayList<Task>();
        for (Task task : taskList) {
            Object unitIds = this.getExecutionVariable(task.getExecutionId(), "orgId");
            String[] unitIdsArray = unitIds.toString().split(",");
            Arrays.sort(unitIdsArray);
            int index = Arrays.binarySearch(unitIdsArray, realId);
            if (index >= 0) {
                tasks.add(task);
            }
        }
        return tasks;
    }

    @Override
    public InputStream getImage(String processInstanceId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (null == processInstance) {
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            if (null == historicProcessInstance) {
                throw new ServiceException("沒有找到對應的流程實例!");
            }
            String definitionId = historicProcessInstance.getProcessDefinitionId();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(definitionId).singleResult();
            return repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getDiagramResourceName());
        }
        try {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
            HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
            List<HistoricActivityInstance> activityInstances = historicActivityInstanceQuery.processInstanceId(processInstanceId)
                    .orderByHistoricActivityInstanceStartTime().asc().list();
            List<String> activitiIds = new ArrayList<String>();
            List<String> flowIds = new ArrayList<String>();
            ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());
            flowIds = this.getHighLightedFlows(processDefinition, activityInstances);
            for (HistoricActivityInstance hai : activityInstances) {
                activitiIds.add(hai.getActivityId());
            }
            ProcessEngineImpl defaultProcessEngine = (ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine();
            ProcessEngineConfiguration processEngineConfiguration = defaultProcessEngine.getProcessEngineConfiguration();
            Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration);
            return ProcessDiagramGenerator.generateDiagram(bpmnModel, "png", activitiIds, flowIds);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e);
        }
    }

    public List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinitionEntity, List<HistoricActivityInstance> historicActivityInstances) {
        List<String> highFlows = new ArrayList<String>();
        for (int i = 0; i < historicActivityInstances.size() - 1; i++) {
            ActivityImpl activityImpl = processDefinitionEntity.findActivity(historicActivityInstances.get(i).getActivityId());
            ActivityImpl nextActivityImpl = processDefinitionEntity.findActivity(historicActivityInstances.get(i + 1).getActivityId());
            List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();
            for (PvmTransition pvmTransition : pvmTransitions) {
                ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getDestination();
                if (pvmActivityImpl.getId().equals(nextActivityImpl.getId())) {
                    highFlows.add(pvmTransition.getId());
                }
            }
        }
        return highFlows;
    }

    @Override
    public JSONObject getProcessIntanceProcedure(String processId) {
        JSONObject json = new JSONObject();
        try {
            HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService.createHistoricActivityInstanceQuery();
            List<HistoricActivityInstance> activityInstances = historicActivityInstanceQuery.processInstanceId(processId)
                    .orderByHistoricActivityInstanceStartTime().asc().list();
            HistoricProcessInstance historicProcessInstance = this.getHistoricProcessInstanceById(processId);
            ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(historicProcessInstance.getProcessDefinitionId());
            JSONArray arr = new JSONArray();
            for (int i = 0; i < activityInstances.size(); i++) {
                HistoricActivityInstance activityIntance = activityInstances.get(i);
                Map<String, Object> map = new HashMap<String, Object>();
                ActivityImpl activityImpl = processDefinition.findActivity(activityIntance.getActivityId());
                map.put("activityName", activityIntance.getActivityName());
                map.put("activityType", activityIntance.getActivityType());
                map.put("left", activityImpl.getX() - 4);
                map.put("top", activityImpl.getY() - 4);
                map.put("width", activityImpl.getWidth());
                map.put("height", activityImpl.getHeight());
                map.put("processId", processId);
                String endActivityName = this.assertProcessInstanceEnd(processId);
                if (endActivityName != null) {
                    map.put("active", false);
                } else {
                    ProcessInstance pi = this.getProcessInstanceById(processId);
                    String activitingId = pi.getActivityId();
                    if (activityIntance.getActivityId().equals(activitingId))
                        map.put("active", true);
                    else
                        map.put("active", false);
                }
                arr.add(map);
            }
            json.put("data", arr);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
        return json;
    }

    @Override
    public void saveUser(String id, String firstName, String lastName, String email, String password) {
        try {
            User user = identityService.createUserQuery().userId(id).singleResult();
            if (user != null) {
                user.setFirstName(firstName);
                user.setLastName(lastName);
                user.setEmail(email);
                user.setPassword(password);
                identityService.saveUser(user);
                return;
            }
            User user1 = new UserEntity();
            user1.setId(id);
            user1.setFirstName(firstName);
            user1.setLastName(lastName);
            user1.setEmail(email);
            user1.setPassword(password);
            identityService.saveUser(user1);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    public void deleteUser(String ids) {
        try {
            String[] idArray = ids.split(",");
            for (String id : idArray) {
                identityService.deleteUser(id);
            }
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void saveGroup(String id, String name, String type) {
        try {
            Group group = identityService.createGroupQuery().groupId(id).singleResult();
            if (group != null) {
                group.setName(name);
                group.setType(type);
                identityService.saveGroup(group);
                return;
            }
            Group group1 = new GroupEntity();
            group1.setId(id);
            group1.setName(name);
            group1.setType(type);
            identityService.saveGroup(group1);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void deleteGroup(String ids) {
        try {
            String[] idArray = ids.split(",");
            for (String id : idArray) {
                identityService.deleteGroup(id);
            }
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void createMembership(String userId, String groupId) {
        try {
            identityService.createMembership(userId, groupId);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void deleteMembership(String userId, String groupId) {
        try {
            identityService.deleteMembership(userId, groupId);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void uploadProcessInstanceDefinition(File temp, String fileName) {
        try {
            String zipPath = ServletActionContext.getServletContext().getRealPath(SystemConstant.ACTIVITI_PATH);
            File[] fileList = new File(zipPath).listFiles();
            for (File file : fileList) {
                if (file.getName().equals(fileName)) {
                    file.delete();
                    break;
                }
            }
            File newTemplate = new File(zipPath, fileName);
            FileUtils.copyFile(temp, newTemplate);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public String viewServerZip() {
        StringBuffer json = new StringBuffer("[");
        List<ComboVo> list = this.getWaitDefinition();
        for (int i = 0; i < list.size(); i++) {
            StringBuffer child = new StringBuffer("{text:'");
            child.append(list.get(i).getValue() + "-" + list.get(i).getDisplayValue() + ".zip',iconCls:'zip-button',leaf:true}");
            json.append(child);
            if (i != list.size() - 1) {
                json.append(",");
            }
        }
        json.append("]");
        return json.toString();
    }

    @Override
    public void deleteServerZip(String fileName) {
        try {
            String zipPath = ServletActionContext.getServletContext().getRealPath(SystemConstant.ACTIVITI_PATH);
            File file = new File(zipPath + "/" + fileName);
            if (file.exists()) {
                file.delete();
            }
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public InputStream viewProcessInstancePng(String deployId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
        return repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getDiagramResourceName());
    }

    @Override
    public InputStream viewProcessInstanceBpmn(String deployId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
        return repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
    }

    @Override
    public Object getProcessInfoByExecutionId(String executionId) {
        IObjectQuery<ProcessInfo> query = new ObjectQueryImpl<ProcessInfo, Integer>(ProcessInfo.class);
        query.equals("processId", executionId);
        List<Object> list = this.mybatisDao.getObjectList(query.sqlMap());
        if (list != null && list.size() != 0) {
            return list.get(0);
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public String getTemplateName(String definitionInfoId) {
        IObjectQuery<ProcessDefinitionInfo> query = new ObjectQueryImpl<ProcessDefinitionInfo, Integer>(ProcessDefinitionInfo.class);
        query.id(definitionInfoId);
        List<Object> list = this.mybatisDao.getObjectList(query.sqlMap());
        if (list != null && list.size() != 0) {
            return ((Map<String, Object>) list.get(0)).get("templateName").toString();
        }
        return "";
    }

    @Override
    public void saveProcessLinkVariables(String processInfoId, String taskId, Map<String, Object> variables, Person person, String result) {
        //Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        HistoricTaskInstance hti = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        ProcessVariable pv = null;
        for (Map.Entry<String, Object> entry : variables.entrySet()) {
            pv = new ProcessVariable();
            pv.setExecutionId(hti.getExecutionId());
            pv.setTaskId(taskId);
            pv.setTaskName(hti.getName());
            pv.setProcessInfoId(NumberUtils.toInt(processInfoId));
            pv.setT_key(entry.getKey());
            pv.setT_value(entry.getValue().toString());
            pv.setTime(new Date());
            pv.setUserName(person.getUserName());
            pv.setUserCard(person.getCard());
            pv.setResult(result);//保存審批結果
            pv.setSort(getTaskVariableSort(hti.getName(), entry.getKey(), hti.getExecutionId()));
            this.add(pv);
        }
    }

    public Integer getTaskVariableSort(String taskName, String t_key, String executionId) {
        IObjectQuery<ProcessVariable> query = new ObjectQueryImpl<ProcessVariable, Integer>(ProcessVariable.class);
        query.equals("taskName", taskName).equals("t_key", t_key).equals("executionId", executionId);
        List<Object> list = this.mybatisDao.getObjectList(query.sqlMap());
        if (list == null || list.size() == 0) {
            return 0;
        }
        return list.size();
    }

    @Override
    public List<Object> getProcessLinkVariables(String processId, String taskName) {
        IObjectQuery<ProcessVariable> query = new ObjectQueryImpl<ProcessVariable, Integer>(ProcessVariable.class);
        query.equals("executionId", processId).equals("taskName", taskName).orderDesc("sort");
        List<Object> list = this.mybatisDao.getObjectList(query.sqlMap());
        return list;
    }

    @Override
    public Task getTaskById(String taskId) {
        return this.taskService.createTaskQuery().taskId(taskId).singleResult();
    }

    @Override
    public void deleteUserIdentityLink(String taskId, String userIds, String identityLinkType) {
        try {
            String[] ids = userIds.split(",");
            for (String id : ids) {
                taskService.deleteUserIdentityLink(taskId, id, identityLinkType);
            }
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void addUserIdentityLink(String taskId, String userIds, String identityLinkType) {
        try {
            String[] ids = userIds.split(",");
            for (String id : ids) {
                taskService.addUserIdentityLink(taskId, id, identityLinkType);
            }
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public Map<String, Object> getTaskByProcessInfoId(int processInfoId) {
        try {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("processInfoId", processInfoId);
            return (Map<String, Object>) this.mybatisDao.getUniqueObject("activiti.getTaskByProcessInfoId", params);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e);
        }
    }

    @Override
    public void deleteHistoryProcessIntance(String executionId) {
        historyService.deleteHistoricProcessInstance(executionId);
    }

    @Override
    public List<IdentityLink> getIdentityLinksForTask(String taskId) {
        return taskService.getIdentityLinksForTask(taskId);
    }

    @Override
    public void deleteCandidateGroup(String taskId, String groupIds) {
        String[] groupIdArray = groupIds.split(",");
        try {
            for (String id : groupIdArray) {
                taskService.deleteCandidateGroup(taskId, id);
            }
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

    @Override
    public void addCandidateUser(String taskId, String userIds) {
        String[] userIdArray = userIds.split(",");
        try {
            for (String id : userIdArray) {
                taskService.addCandidateUser(taskId, id);
            }
        } catch (Exception e) {
            throw new ServiceException(e);
        }
    }

}

Mybatis映射SQL

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "./dtd/mybatis-3-mapper.dtd">
<mapper namespace="activiti">
    <!-- 根據ProcessInfoId獲取任務 -->
    <select id="getTaskByProcessInfoId" parameterType="java.util.HashMap" resultType="java.util.HashMap">
        select
        t.ID_ as taskId,
        t.NAME_ as taskName,
        t.DESCRIPTION_ as description
        from act_ru_task t
        inner join
        t_processinfo t1
        on
        t1.PROCESSID = t.EXECUTION_ID_
        where
        t1.PK_ID = #{processInfoId}
        limit 1
    </select>

    <!-- 更新流程狀態 -->
    <update id="updateProcessInfoStatus" parameterType="java.util.Map">
        update
        T_PROCESSINFO o set o.STATUS = 'end',o.COMPLATE_DATE =
        #{complateDate}
        where o.PROCESSID = #{processId}
    </update>

    <!-- 當刪除運行時流程時,更新processInfo表信息 -->
    <update id="updateProcessInstanceWhenDeleteProcess" parameterType="java.util.Map">
        update T_PROCESSINFO o set o.STATUS =
        'delete',o.COMPLATE_DATE = #{complateDate}
        where o.PK_ID =
        #{processinfoId}
    </update>

    <!-- 根據部署id刪除系統流程定義 -->
    <delete id="deleteSystemDefinition" parameterType="java.util.Map">
        delete from
        T_PROCESSDEFINITIONINFO
        where DEPLOYID = #{deployId}
    </delete>

    <!-- 根據部署id刪除系統流程 -->
    <delete id="deleteSystemProcessInstance" parameterType="java.util.Map">
        delete t
        from T_PROCESSINFO t
        where t.DEFINITIONINFOID in(
        select t1.PK_ID from
        T_PROCESSDEFINITIONINFO t1
        where t1.DEPLOYID = #{deployId}
        )
    </delete>

    <!-- 根據部署id來刪除流程變量 -->
    <delete id="deleteProcessInstanceVariableByDeployId" parameterType="java.util.Map">
        delete t from T_PROCESSVARIABLE t
        where t.PROCESSINFOID
        in(
        select t1.PK_ID from T_PROCESSINFO t1
        where t1.DEFINITIONINFOID in(
        select t2.PK_ID from T_PROCESSDEFINITIONINFO t2
        where t2.DEPLOYID =
        #{deployId}
        )
        )
    </delete>
</mapper>

大家可以自行測試:(調用上面部署流程的方法)

用activiti插件生成bpmn和png圖片之后,壓縮到一個zip格式的壓縮包中。

 

 

執行測試用例並查看結果

  • act_re_deployment 流程定義部署表新增一條記錄

  • act_re_procdef 流程定義表中VERSION_字段 版本升級了,KEY依然是一樣的;

  • act_ge_bytearry 資源文件表,多了兩條記錄

  • 這里再提一個表 act_ge_property 屬性表,這里的next_dbid是主鍵策略,就是規定好了下一次生成的id就是10001;

測試:

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.activiti.engine.task.Task;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.springframework.beans.factory.annotation.Autowired;

import com.sckj.base.common.constant.SystemConstant;
import com.sckj.base.entity.admin.Person;
import com.sckj.base.exception.ServiceException;
import com.sckj.base.util.DateUtil;
import com.sckj.base.vo.ComboVo;
import com.sckj.macb.query.ListVo;
import com.sckj.plugins.org.entity.OPerson;
import com.sckj.plugins.org.service.IOrgService;

import net.sf.json.JSONObject;


/**
 * 流程管理action
 * @author LuoYu
 */
public class ActivitiAction extends ActivitiBaseAction {

    /** serialVersionUID **/
    private static final long serialVersionUID = 4022483438757978770L;

    private File newTemplate;

    private String newTemplateName;

    @Autowired
    private IOrgService orgService;

    @Override
    @Action(value = "*", results = {@Result(name = "success", location = "/WEB-INF/pages/admin/process/{1}.jsp")})
    public String execute() throws Exception {
        return super.execute();
    }

    /**
     * 部署流程定義
     *@return void
     */
    @Action(value = "deployProcessInstanceDefinition")
    public void deployProcessInstanceDefinition() {
        String definitionName = this.getHttpServletRequest().getParameter("definitionName");
        try {
            this.getActivitiService().deployProcessDefinition(definitionName);
            this.outSuccess("部署流程模板成功!");
        } catch (ServiceException e) {
            this.outError("msg:" + e.getMessageKey());
        } catch (Exception e) {
            this.outError("部署流程模板失敗!");
        }
    }

    /**
     * 獲取待部署的流程定義模板
     *@return void
     */
    @Action(value = "getWaitDefinition")
    public void getWaitDefinition() {
        List<ComboVo> list = this.getActivitiService().getWaitDefinition();
        this.out(list);
    }

    /**
     * 獲取已發布的流程定義模板
     *@return void
     */
    @Action(value = "getProcessDefinitionList")
    public void getProcessDefinitionList() {
        try {
            List<Object> list = this.getActivitiService().getProcessDefinitionList();
            this.out(list);
        } catch (Exception e) {
            this.outError("獲取流程定義失敗!");
            e.printStackTrace();
        }
    }

    /**
     * 刪除流程定義
     *@return void
     */
    @Action(value = "deleteProcessInstanceDefinition")
    public void deleteProcessInstanceDefinition() {
        String ids = this.getHttpServletRequest().getParameter("ids");
        String cascade = this.getHttpServletRequest().getParameter("cascade");
        try {
            if (cascade.equals("yes")) {
                this.getActivitiService().deleteDeploymentCascade(ids);
            } else {
                this.getActivitiService().deleteDeployment(ids);
            }
            this.outSuccess("刪除流程實例成功!");
        } catch (Exception e) {
            this.outError("刪除流程實例失敗!");
        }
    }

    /**
     * 獲取所有的流程實例
     *@return void
     */
    @Action(value = "getProcessList")
    public void getProcessList() {
        HttpServletRequest request = this.getHttpServletRequest();
        String start = request.getParameter("start");
        String limit = request.getParameter("limit");
        String status = request.getParameter("status");
        if (null != status && status.equals("")) {
            status = null;
        }
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("start", start);
        params.put("limit", limit);
        params.put("status", status);
        try {
            ListVo<Object> listVo = this.getActivitiService().getProcessInstanceList(params);
            this.out(listVo);
        } catch (Exception e) {
            this.outError("獲取流程實例失敗!");
            e.printStackTrace();
        }
    }


    /**
     * 刪除流程實例
     *@return void
     */
    @Action(value = "deleteProcessInstance")
    public void deleteProcessInstance() {
        HttpServletRequest request = this.getHttpServletRequest();
        String processInfoId = request.getParameter("processInfoId");
        String processId = request.getParameter("processId");
        String deleteReason = request.getParameter("deleteReason");
        try {
            this.getActivitiService().deleteProcessInstance(processId, processInfoId, deleteReason);
            this.outSuccess("刪除流程實例成功!");
        } catch (Exception e) {
            this.outError("刪除流程實例失敗!");
        }
    }

    /**
     * 上傳新的流程模板
     *@return void
     */
    @Action(value = "uploadTemplate")
    public void uploadTemplate() {
        try {
            this.getActivitiService().uploadProcessInstanceDefinition(newTemplate, newTemplateName);
            this.outSuccess("上傳流程模板成功!");
        } catch (Exception e) {
            this.outError("上傳流程模板失敗!");
        }
    }

    /**
     * 瀏覽服務器存在的部署資源包
     *@return void
     */
    @Action(value = "viewServerZip")
    public void viewServerZip() {
        this.out(this.getActivitiService().viewServerZip());
    }

    /**
     * 刪除服務器存在的zip資源包
     *@return void
     */
    @Action(value = "deleteServerZip")
    public void deleteServerZip() {
        String fileName = this.getHttpServletRequest().getParameter("fileName");
        try {
            this.getActivitiService().deleteServerZip(fileName);
            this.outString("刪除資源包成功!");
        } catch (Exception e) {
            this.outError("刪除資源包失敗!");
        }
    }

    /**
     * 查看流程定義的png圖片
     *@return void
     */
    @Action(value = "viewProcessInstancePng")
    public void viewProcessInstancePng() {
        try {
            String deployId = this.getHttpServletRequest().getParameter("deployId");
            InputStream is = this.getActivitiService().viewProcessInstancePng(deployId);
            byte[] b = new byte[1024];
            int len = 0;
            while ((len = is.read(b, 0, 1024)) != -1) {
                this.getHttpServletResponse().getOutputStream().write(b, 0, len);
            }
        } catch (Exception e) {
            this.outError("獲取圖片失敗!");
        }
    }

    /**
     * 查看流程定義BPMN
     *@return void
     */
    @Action(value = "viewProcessInstanceBpmn")
    public void viewProcessInstanceBpmn() {
        try {
            String deployId = this.getHttpServletRequest().getParameter("deployId");
            InputStream is = this.getActivitiService().viewProcessInstanceBpmn(deployId);
            byte[] b = new byte[1024];
            int len = 0;
            while ((len = is.read(b, 0, 1024)) != -1) {
                this.getHttpServletResponse().getOutputStream().write(b, 0, len);
            }
        } catch (Exception e) {
            this.outError("獲取BPMN文件失敗!");
        }
    }

    @Action(value = "gotoImage", results = {@Result(location = "/WEB-INF/pages/admin/viewProcessImg.jsp")})
    public String gotoImage() {
        String processInfoId = this.getHttpServletRequest().getParameter("processInfoId");
        String string = this.getActivitiService().getDeployIdByProcessInfoId(processInfoId);
        this.getHttpServletRequest().setAttribute("deployId", string.split("@")[0]);
        this.getHttpServletRequest().setAttribute("processId", string.split("@")[1]);
        return SUCCESS;
    }

    /**
     * 獲取流程過程流向
     *@return void
     */
    @Action(value = "getProcessIntanceProcedure")
    public void getProcessIntanceProcedure() {
        String processId = this.getHttpServletRequest().getParameter("processId");
        JSONObject jsonObject = this.getActivitiService().getProcessIntanceProcedure(processId);
        this.out(jsonObject);
    }

    /**
     * 獲取用戶待辦任務列表
     */
    @SuppressWarnings("unchecked")
    @Action(value = "getPersonalTask")
    public void getPersonalTask() {
        try {
            Map<String, Object> params = new HashMap<String, Object>();
            Person account = this.getCurrentAccount();
            if (!account.isAdmin()) {
                params.put("card", account.getCard().toString());
                params.put("dwId", account.getOrgId());
                List<Task> taskList = this.getActivitiService().getPersonalTask(params);
                ListVo<Map<String, String>> listVo = new ListVo<Map<String, String>>();
                List<Map<String, String>> list = new ArrayList<Map<String, String>>();
                Map<String, String> map = null;
                JSONObject jsonObject = null;
                Map<String, Object> processInfo = null;
                for (Task task : taskList) {
                    map = new HashMap<String, String>();
                    processInfo = (Map<String, Object>) this.getActivitiService().getProcessInfoByExecutionId(task.getExecutionId());
                    String userCard = processInfo.get("userCardId").toString();
                    if (StringUtils.isNotBlank(userCard)) {
                        OPerson person = this.orgService.queryPersonByCard(userCard);
                        if (person != null) {
                            map.put("bmPath", person.getDepartmentId());
                        }
                    }

                    map.put("infoId", processInfo.get("id").toString());//流程info的id
                    map.put("sponsor", processInfo.get("userName").toString());//流程發起人
                    map.put("processType", this.getActivitiService().getTemplateName(processInfo.get("definitionInfoId").toString()));//流程類型
                    map.put("createDate", processInfo.get("createDate").toString());//流程創建時間
                    map.put("taskId", task.getId());//任務id
                    map.put("taskName", task.getName());//任務名稱
                    map.put("executionId", task.getExecutionId());//執行id
                    Map<String, Object> variables = this.getActivitiService().getExecutionVariables(task.getExecutionId());
                    map.put("variables", JSONObject.fromObject(variables).toString());//流程變量
                    map.put("businessKey", (String) processInfo.get("businessKey"));//業務鍵
                    jsonObject = JSONObject.fromObject(task.getDescription());

                    if (processInfo.get("taskUrl") != null) {
                        map.put("taskUrl", processInfo.get("taskUrl").toString());
                    } else {
                        map.put("taskUrl", jsonObject.get("taskUrl").toString());//處理taskUrl
                    }

                    map.put("documentation", jsonObject.get("documentation").toString());//任務備注

                    list.add(map);
                }
                Collections.sort(list, new Comparator<Map<String, String>>() {
                    @Override
                    public int compare(Map<String, String> o1, Map<String, String> o2) {
                        Date date1 = DateUtil.stringToDate(o1.get("createDate").toString(), SystemConstant.TIME_PATTEN);
                        Date date2 = DateUtil.stringToDate(o2.get("createDate").toString(), SystemConstant.TIME_PATTEN);
                        if (date1.after(date2)) {
                            return -1;
                        } else {
                            return 1;
                        }
                    }
                });
                listVo.setList(list);
                listVo.setTotalSize(taskList.size());
                this.out(listVo);
            }
        } catch (Exception e) {
            e.printStackTrace();
            this.outError("獲取任務信息失敗!");
        }
    }

    @Action(value = "getActivityVariables")
    @SuppressWarnings("unchecked")
    public void getActivityVariables() {
        try {
            HttpServletRequest request = this.getHttpServletRequest();
            String processId = request.getParameter("processId");
            String taskName = request.getParameter("taskName");
            List<Object> list = this.getActivitiService().getProcessLinkVariables(processId, taskName);
            Map<String, Object> processInfo = (Map<String, Object>) this.getActivitiService().getProcessInfoByExecutionId(processId);
            for (Object variable : list) {
                Map<String, Object> tempMap = (Map<String, Object>) variable;

                tempMap.put("processType", this.getActivitiService().getTemplateName(processInfo.get("definitionInfoId").toString()));//流程類型
            }
            this.out(list);
        } catch (Exception e) {
            e.printStackTrace();
            this.outError("獲取任務信息失敗!");
        }
    }

    @Action(value = "invoke")
    public void invoke() {
        /*Map<String, Object> map = new HashMap<String, Object>();
        map.put("outcome", "pass");
        this.getActivitiService().startProcessInstanceByKey("TaskTest", map);*/
        /*this.getActivitiService().completeTask("4", "4414");*/
        /*Map<String, Object> map = new HashMap<String, Object>();
        map.put("userId", "4");
        Task task = this.getActivitiService().getPersonalTask(map).get(0);
        JSONObject jsonObject = JSONObject.fromObject(task.getDescription());
        System.out.println(jsonObject.get("taskUrl"));
        System.out.println(jsonObject.get("documentation").equals(""));*/
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("userId", "4");
        Task task = this.getActivitiService().getPersonalTask(map).get(0);

    }

    public File getNewTemplate() {
        return newTemplate;
    }

    public void setNewTemplate(File newTemplate) {
        this.newTemplate = newTemplate;
    }

    public String getNewTemplateName() {
        return newTemplateName;
    }

    public void setNewTemplateName(String newTemplateName) {
        this.newTemplateName = newTemplateName;
    }

}

以上就是本人對activity的一些封裝和測試~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM