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;
}
}