SSH与工作流Activiti的集成开发

Activiti 数据库表结构说明:

数据库表结构说明:

·             ACT_GE_PROPERTY:属性数据表。存储整个流程引擎级别的数据。

1. NAME_:属性名称

2. VALUE_:属性值

3. REV_INT:版本号?

·             ACT_GE_BYTEARRAY:用来保存部署文件的大文本数据的。

1. ID_:资源文件编号,自增长

2. REV_INT:版本号?

3. NAME_:资源文件名称

4. DEPLOYMENT_ID_:来自于父表ACT_RE_DEPLOYMENT中的主键

5. BYTES_:大文本类型,存储文本字节流

·             ACT_RE_DEPLOYMENT:用来存储部署时需要被持久化保存下来的信息。

1. ID_:部署编号,自增长

2. NAME_:部署的包名称

3. DEPLOY_TIME_:部署时间

·             ACT_RE_PROCDEF:业务流程定义数据表。

1. ID_:流程ID,由“流程编号:流程版本号:自增长ID ” 组成

2. CATEGORY_:流程命令空间(该编号就是流程文件targetNamespace的属性值)

3. NAME_:流程名称(该编号就是流程文件process元素的name属性值)

4. KEY_:流程编号(该编号就是流程文件process元素的id属性值)

5. VERSION_:流程版本号(由程序控制,新增即为1,修改后依次加1来完成的)

6. DEPLOYMENT_ID_:部署编号

7. RESOURCE_NAME_:资源文件名称

8. DGRM_RESOURCE_NAME_:图片资源文件名称

9. HAS_START_FORM_KEY_:是否有Start Form Key。

注意:此表与ACT_RE_DEPLOYMENT是多对一的关系,即,一个部署的bar包里可能包含多个流程定义文件,每个流程定义文件都会有一条记录在ACT_RE_PROCDEF表内,每条流程定义的数据,都会对应ACT_GE_BYTEARRAY表内的一个资源文件和PNG图片文件。与ACT_GE_BYTEARRAY的关联是通过程序用ACT_GE_BYTEARRAY.NAME_ACT_RE_PROCDEF.RESOURCE_NAME_完成的,在数据库表结构内没有体现。

·             ACT_ID_GROUP:用来保存用户组信息。

1. ID_:用户组名

2. REV_INT:版本号?

3. NAME_:用户组描述信息

4. TYPE_:用户组类型

·             ACT_ID_MEMBERSHIP:用来保存用户分组信息。

1. USER_ID_:用户名

2. GROUP_ID_:用户组名

·             ACT_ID_USER:用来保存用户信息。

1. ID_:用户名

2. REV_INT:版本号?

3. FIRST_:用户名称

4. LAST_:用户姓氏

5. EMAIL_:邮箱

6. PWD_:登录密码

·             ACT_RU_EXECUTION:

1. ID_:

2. REV_:版本号?

3. PROC_INST_ID_:流程实例编号

4. BUSINESS_KEY_:业务编号

5. PARENT_ID_:

6. PROC_DEF_ID_:流程ID

7. SUPER_EXEC_:

8. ACT_ID_:

9. IS_ACTIVE_:

10.            IS_CONCURRENT_:

11.            IS_SCOPE_:

·             ACT_RU_JOB:运行时定时任务数据表。

1. ID_:

2. REV_:

3. TYPE_:

4. LOCK_EXP_TIME_:

5. LOCK_OWNER_:

6. EXCLUSIVE_:

7. EXECUTION_ID_:

8. PROCESS_INSTANCE_ID_:

9. RETRIES_:

10.            EXCEPTION_STACK_ID_:

11.            EXCEPTION_MSG_:

12.            DUEDATE_:

13.            REPEAT_:

14.            HANDLER_TYPE_:

15.            HANDLER_CFG_:

·             ACT_RU_TASK:运行时任务数据表。

1. ID_:

2. REV_:

3. EXECUTION_ID_:

4. PROC_INST_ID_:

5. PROC_DEF_ID_:

6. NAME_:

7. DESCRIPTION_:

8. TASK_DEF_KEY_:

9. ASSIGNEE_:

10.            PRIORITY_:

11.            CREATE_TIME_:

·             ACT_RU_IDENTITYLINK:任务参与者数据表。主要存储当前节点参与者的信息。

1. ID_:

2. REV_:

3. GROUP_ID_:

4. TYPE_:

5. USER_ID_:

6. TASK_ID_:

·             ACT_RU_VARIABLE:运行时流程变量数据表。

1. ID_:

2. REV_:

3. TYPE_:

4. NAME_:

5. EXECUTION_ID_:

6. PROC_INST_ID_:

7. TASK_ID_:

8. BYTEARRAY_ID_:

9. DOUBLE_:

10.            LONG_:

11.            TEXT_:

12.            TEXT2_:

·             ACT_HI_PROCINST:

·             ACT_HI_ACTINST:

·             ACT_HI_TASKINST:

·             ACT_HI_DETAIL:

3、结论及改造建议

  •  
    • 流程文件部署主要涉及到3个表,分别是:ACT_GE_BYTEARRAY、ACT_RE_DEPLOYMENT、ACT_RE_PROCDEF。主要完成“部署包”-->“流程定义文件”-->“所有包内文件”的解析部署关系。从表结构中可以看出,流程定义的元素需要每次从数据库加载并解析,因为流程定义的元素没有转化成数据库表来完成,当然流程元素解析后是放在缓存中的,具体的还需要后面详细研究。
    • 流程定义中的java类文件不保存在数据库里 。
    • 组织机构的管理相对较弱,如果要纳入单点登录体系内还需要改造完成,具体改造方法有待研究。
    • 运行时对象的执行与数据库记录之间的关系需要继续研究
    • 历史数据的保存及作用需要继续研究。 

       
  • 集成到SSH中所需jar包:

mybatis最新jar包+

 

配置文件:

<?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:tx="http://www.springframework.org/schema/tx"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/tx
 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
 ">

 <!-- Activiti Configcation -->
 <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="databaseType" value="mysql" /> 
        <property name="jobExecutorActivate" value="false" /> 
        <property name="history" value="full" /> 
      
       <property name="beans"> 
            <map> 
                <entry key="ITResReqsProcess_CurrentDepartmentApproval" value="DevDepartment"/> 
                <entry key="ITResReqsProcess_ITDepartmentApprova" value="ITDepartment"/> 
                <entry key="ITResReqsProcess_OperationMaintenanceDepartmentApproval" value="OperationMaintenanceDepartment"/> 
            </map> 
        </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="formService" factory-bean="processEngine" factory-method="getFormService" /> 
    <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" /> 
    <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="userBean" class="org.activiti.spring.test.UserBean">   
  <property name="runtimeService" ref="runtimeService" /> 
 </bean> 
 <bean id="printer" class="org.activiti.spring.test.Printer" />-->
 
</beans>

 

 

工作流查询代码(仅选取可关键部分的代码),如需全部源码,请发送邮件到我的邮箱索取([email protected]):

package com.workflow.service.impl;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.spring.ProcessEngineFactoryBean;
import org.apache.commons.io.FilenameUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.jeecg.pageModel.DataGrid;
import com.jeecg.service.impl.BaseServiceImpl;
import com.workflow.pageModel.Activiti;
import com.workflow.pageModel.ActivitiInstance;
import com.workflow.service.ActivitiServiceI;

/**
 * Activiti Service 工作流
 * <p>
 * ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 * RuntimeService runtimeService = processEngine.getRuntimeService();
 * RepositoryService repositoryService = processEngine.getRepositoryService();
 * TaskService taskService = processEngine.getTaskService(); ManagementService
 * managementService = processEngine.getManagementService(); IdentityService
 * identityService = processEngine.getIdentityService(); HistoryService
 * historyService = processEngine.getHistoryService(); FormService formService =
 * processEngine.getFormService();
 * 这些服务的名称是相当一目了然的。更多关于服务和引擎 API
 * </p>
 *
 * @author HurryJiang
 *
 */
@Service("activitiService")
public class ActivitiServiceImpl extends BaseServiceImpl implements
  ActivitiServiceI {
 private static final Logger logger = Logger.getLogger(ActivitiServiceImpl.class);
 private static final String SORTBY_ID = "id";
 private static final String SORTBY_INSTANCEID = "processInstanceId";
 private static final String SORTBY_DEPLOYEMENTID = "deploymentId";
 private static final String SORTBY_NAME = "name";
 private static final String SORTBY_VERSION = "version";
 private static final String SORTBY_KEY = "key";
 private static final String SORTBY_CATEGORY = "category";
 
 private static final String ORDERBY_ASC = "asc";
 private static final String ORDERBY_DESC = "desc";
 
 private ProcessEngineFactoryBean processEngine;
 private RepositoryService repositoryService;
 private RuntimeService runtimeService;
 private FormService formService;
 private IdentityService identityService;
 private TaskService taskService;
 private WorkflowTraceService traceService;
 private HistoryService historyService;
 private ManagementService managementService;
 
 public ActivitiServiceImpl(){

 }
 /**
  * Get ActivitiEngine
  *
  * @return
  */
 public ProcessEngineFactoryBean getProcessEngine() {
  return processEngine;
 }

 @Autowired
 public void setProcessEngine(ProcessEngineFactoryBean processEngine) {
  this.processEngine = processEngine;
 }

 public RuntimeService getRuntimeService() {
  return runtimeService;
 }

 @Autowired
 public void setRuntimeService(RuntimeService runtimeService) {
  this.runtimeService = runtimeService;
 }

 public FormService getFormService() {
  return formService;
 }

 @Autowired
 public void setFormService(FormService formService) {
  this.formService = formService;
 }

 public IdentityService getIdentityService() {
  return identityService;
 }

 @Autowired
 public void setIdentityService(IdentityService identityService) {
  this.identityService = identityService;
 }

 public TaskService getTaskService() {
  return taskService;
 }

 @Autowired
 public void setTaskService(TaskService taskService) {
  this.taskService = taskService;
 }

 public HistoryService getHistoryService() {
  return historyService;
 }

 @Autowired
 public void setHistoryService(HistoryService historyService) {
  this.historyService = historyService;
 }

 public ManagementService getManagementService() {
  return managementService;
 }

 @Autowired
 public void setManagementService(ManagementService managementService) {
  this.managementService = managementService;
 }

 public RepositoryService getRepositoryService() {
  return repositoryService;
 }
 @Autowired
 public void setRepositoryService(RepositoryService repositoryService) {
  this.repositoryService = repositoryService;
 }

 @Transactional(propagation = Propagation.SUPPORTS)
 public DataGrid datagrid(Activiti entity) {
  DataGrid j = new DataGrid();
  /*
      * 查询两个对象,一个是ProcessDefinition(流程定义),一个是Deployment(流程部署)
      */
  ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
  //查询总数
  long total = query.count();
  //查询分页记录(根据条件)
  if(entity.getSort()!=null){
   if(entity.getSort().equals(ActivitiServiceImpl.SORTBY_ID)){
    query = query.orderByProcessDefinitionId();
   }else if(entity.getSort().equals(ActivitiServiceImpl.SORTBY_NAME)){
    query = query.orderByProcessDefinitionName();
   }else if(entity.getSort().equals(ActivitiServiceImpl.SORTBY_CATEGORY)){
    query = query.orderByProcessDefinitionCategory();
   }else if(entity.getSort().equals(ActivitiServiceImpl.SORTBY_KEY)){
    query = query.orderByProcessDefinitionKey();
   }else if(entity.getSort().equals(ActivitiServiceImpl.SORTBY_VERSION)){
    query = query.orderByProcessDefinitionVersion();
   }else if(entity.getSort().equals(ActivitiServiceImpl.SORTBY_DEPLOYEMENTID)){
    query = query.orderByDeploymentId();
   }
  }
  if(entity.getOrder()!=null){
   if( entity.equals(ActivitiServiceImpl.ORDERBY_DESC)){
    query = query.desc();
   }else{
    query = query.asc();
   }
  }
  if(entity.getRows()>0 && entity.getPage()>=0){//分页查询
   query.listPage((entity.getPage() - 1) * entity.getRows(), entity.getRows() );//listPage(int firstResult, int maxResults);
  }
     List<ProcessDefinition> processDefinitionList = query.list();
    
  j.setRows(getActivitisFromProcessDefinitions(processDefinitionList));
  j.setTotal(total);
  return j;
 }

 private List<Activiti> getActivitisFromProcessDefinitions(List<ProcessDefinition> defs) {
  List<Activiti> acts = new ArrayList<Activiti>();
  if (defs != null && defs.size() > 0) {
   for (ProcessDefinition tb : defs) {
    Activiti b = new Activiti();
    BeanUtils.copyProperties(tb, b);
    String deploymentId = tb.getDeploymentId();
       Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
    if(deployment!=null){
     b.setDeploymentTime(deployment.getDeploymentTime());
     b.setCategory(deployment.getCategory());
    }
       acts.add(b);
   }
  }
  return acts;
 }

 private String addWhere(Activiti entity, String hql, List<Object> values) {
  return hql;
 }

 public void add(Activiti entity) {
  logger.debug("add...");
 }

 public void update(Activiti entity) {
  logger.debug("update...");
 }

 /**
  * 可选择级联删除
  * @param ids
  */
 public void deleteByCascade(String ids,boolean cascade) {
  if (ids != null) {
   for (String id : ids.split(",")) {
    ProcessDefinition def = repositoryService.getProcessDefinition(id);
    if (def != null) {
     repositoryService.deleteDeployment(id,cascade);
     logger.debug("delete..."+id);
    }
   }
  }
 }
 /**
  * 强制级联删除已部署的流程(非流程定义)
  * @param ids
  */
 public void deleteDeployment(String ids) {
  if (ids != null) {
   for (String id : ids.split(",")) {
    DeploymentQuery depQuery = repositoryService.createDeploymentQuery().deploymentId(id);
    if (depQuery != null && depQuery.list()!=null) {
     repositoryService.deleteDeployment(id,true);
     logger.debug("delete..."+id);
    }
   }
  }
 }
 /**
  * 强制级联删除已上传的流程定义(ProcessDefinition)
  * @param ids
  */
 public void deleteProcdef(String ids) {
  if (ids != null) {
   for (String id : ids.split(",")) {
    ProcessDefinition def = repositoryService.getProcessDefinition(id);
    if (def != null) {
     repositoryService.deleteDeployment(id,true);
     logger.debug("delete..."+id);
    }
   }
  }
 }

 @Override
 public ProcessDefinition get(Activiti entity) {
  if(entity!=null){
   ProcessDefinition def = repositoryService.getProcessDefinition(entity.getId());
   return def;
  }
  return null;
 }
 @Override
 public void deploy(InputStream fileInputStream,String fileName) {
   try {
        String extension = FilenameUtils.getExtension(fileName);
        logger.info("File extension:"+extension);
        if (extension.equals("zip") || extension.equals("bar")) {
          ZipInputStream zip = new ZipInputStream(fileInputStream);
          repositoryService.createDeployment().addZipInputStream(zip).deploy();
        } else if (extension.equals("png")) {
          repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();
        } else if (fileName.indexOf("bpmn20.xml") != -1) {
          repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();
        } else if (extension.equals("bpmn")) {
          /*
           * bpmn扩展名特殊处理,转换为bpmn20.xml
           */
          String baseName = FilenameUtils.getBaseName(fileName);
          repositoryService.createDeployment().addInputStream(baseName + ".bpmn20.xml", fileInputStream).deploy();
        } else if (extension.equals("tmp")) {
         ZipInputStream zip = new ZipInputStream(fileInputStream);
         repositoryService.createDeployment().addZipInputStream(zip).deploy();
        }else {
          throw new ActivitiException("no support file type of " + extension);
        }
      } catch (Exception e) {
       logger.error("error on deploy process, because of file input stream", e);
      }
 }
 
 @Override
 public InputStream getResourceAsStreamByDeployment(String deploymentId,
   String resourceName) {
  return repositoryService.getResourceAsStream(deploymentId, resourceName);
 }
 
 @Override
 public InputStream getResourceAsStreamByProcessInstance(
   String processInstanceId, String resourceType) {
  InputStream resourceAsStream = null;
     ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
     ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId())
             .singleResult();

     String resourceName = "";
     if (resourceType.equals("image")) {
       resourceName = processDefinition.getDiagramResourceName();
     } else if (resourceType.equals("xml")) {
       resourceName = processDefinition.getResourceName();
     }
     resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
     return resourceAsStream;
 }
 
 @Override
 public List<Map<String, Object>> traceProcess(String processInstanceId) throws Exception {
  return traceService.traceProcess(processInstanceId);
 }
 public WorkflowTraceService getTraceService() {
  return traceService;
 }
 public void setTraceService(WorkflowTraceService traceService) {
  this.traceService = traceService;
 }
 @Override
 public DataGrid datagridForInstance(ActivitiInstance entity) {
  DataGrid j = new DataGrid();
  ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery();
  //查询总数
  long total = query.count();
  //查询分页记录(根据条件)
  if(entity.getSort()!=null){
   if(entity.getSort().equals(ActivitiServiceImpl.SORTBY_ID)){
    query = query.orderByProcessDefinitionId();
   }else if(entity.getSort().equals(ActivitiServiceImpl.SORTBY_INSTANCEID)){
    query = query.orderByProcessInstanceId();
   }else if(entity.getSort().equals(ActivitiServiceImpl.SORTBY_KEY)){
    query = query.orderByProcessDefinitionKey();
   }
  }
  if(entity.getOrder()!=null){
   if( entity.equals(ActivitiServiceImpl.ORDERBY_DESC)){
    query = query.desc();
   }else{
    query = query.asc();
   }
  }
  if(entity.getRows()>0 && entity.getPage()>=0){//分页查询
   query.listPage((entity.getPage() - 1) * entity.getRows(), entity.getRows() );//listPage(int firstResult, int maxResults);
  }
  List<ProcessInstance> processInstanceList = query.list();
    
  j.setRows(getActivitisFromProcessInstances(processInstanceList));
  j.setTotal(total);
  return j;
 }
 private List<ActivitiInstance> getActivitisFromProcessInstances(List<ProcessInstance> ins) {
  List<ActivitiInstance> acts = new ArrayList<ActivitiInstance>();
  if (ins != null && ins.size() > 0) {
   for (ProcessInstance tb : ins) {
    ActivitiInstance b = new ActivitiInstance();
    BeanUtils.copyProperties(tb, b);
    String deploymentId = tb.getProcessDefinitionId();
       Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
    if(deployment!=null){
     b.setName(deployment.getName());
     b.setDeploymentTime(deployment.getDeploymentTime());
     b.setCategory(deployment.getCategory());
    }
       acts.add(b);
   }
  }
  return acts;
 }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章