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