此文以简单的宝马广告申请流程为示例
一 创建Activiti工作流所需要的23张表
配置文件 activiti.cfg.xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee" 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/context http://www.springframework.org/schema/context/spring-context-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/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcDriver" value="oracle.jdbc.driver.OracleDriver">property>
<property name="jdbcUrl" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl">property>
<property name="jdbcUsername" value="activiti">property>
<property name="jdbcPassword" value="activiti">property>
<property name="databaseSchemaUpdate" value="true">property>
bean>
beans>
代码:
/**
*
*
*Description:使用代码创建工作流需要的23张表
*
* @author:SongJia
*
* @date: 2017-3-27下午4:09:40
*
*/
@Test
public void createTable(){
ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
//创建Oracle数据库连接
configuration.setJdbcDriver("oracle.jdbc.driver.OracleDriver");
configuration.setJdbcUrl("jdbc:oracle:thin:@127.0.0.1:1521:orcl");
configuration.setJdbcUsername("activiti");
configuration.setJdbcPassword("activiti");
//ProcessEngineConfiguration.DB_SCHEMA_UPDATE_CREATE_DROP;先删除表再创建表
//ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE;不能自动创建表,需要表存在
//ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE;自动创建表
configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
ProcessEngine buildProcessEngine = configuration.buildProcessEngine();
System.out.println(buildProcessEngine);
}
/**
*
*
*Description:使用配置文件创建工作流需要的23张表
*
*
* @author
*
* @date
*
*/
@Test
public void createTable_Config(){
ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
ProcessEngine buildProcessEngine = configuration.buildProcessEngine();
System.out.println(buildProcessEngine);
}
二 流程
代码:
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="BavarianMotorWorks" name="BavarianMotorWorks" isExecutable="true">
<startEvent id="startevent1" name="Start">startEvent>
<endEvent id="endevent1" name="End">endEvent>
<userTask id="usertask1" name="申请" activiti:candidateGroups="员工">userTask>
<userTask id="usertask2" name="审核" activiti:candidateGroups="部门经理">userTask>
<userTask id="usertask3" name="批准" activiti:candidateGroups="总经理">userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1">sequenceFlow>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2">sequenceFlow>
<sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3">sequenceFlow>
<sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1">sequenceFlow>
<sequenceFlow id="flow5" name="驳回" sourceRef="usertask2" targetRef="usertask1">sequenceFlow>
process>
<bpmndi:BPMNDiagram id="BPMNDiagram_BavarianMotorWorks">
<bpmndi:BPMNPlane bpmnElement="BavarianMotorWorks" id="BPMNPlane_BavarianMotorWorks">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="430.0" y="100.0">omgdc:Bounds>
bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="430.0" y="430.0">omgdc:Bounds>
bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="395.0" y="170.0">omgdc:Bounds>
bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="395.0" y="260.0">omgdc:Bounds>
bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
<omgdc:Bounds height="55.0" width="105.0" x="395.0" y="350.0">omgdc:Bounds>
bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="447.0" y="135.0">omgdi:waypoint>
<omgdi:waypoint x="447.0" y="170.0">omgdi:waypoint>
bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="447.0" y="225.0">omgdi:waypoint>
<omgdi:waypoint x="447.0" y="260.0">omgdi:waypoint>
bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="447.0" y="315.0">omgdi:waypoint>
<omgdi:waypoint x="447.0" y="350.0">omgdi:waypoint>
bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="447.0" y="405.0">omgdi:waypoint>
<omgdi:waypoint x="447.0" y="430.0">omgdi:waypoint>
bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
<omgdi:waypoint x="500.0" y="287.0">omgdi:waypoint>
<omgdi:waypoint x="563.0" y="287.0">omgdi:waypoint>
<omgdi:waypoint x="563.0" y="197.0">omgdi:waypoint>
<omgdi:waypoint x="500.0" y="197.0">omgdi:waypoint>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="14.0" width="100.0" x="10.0" y="0.0">omgdc:Bounds>
bpmndi:BPMNLabel>
bpmndi:BPMNEdge>
bpmndi:BPMNPlane>
bpmndi:BPMNDiagram>
definitions>
三 部署、删除流程定义
部署流程定义:
/**
*
*
*Description:部署流程定义
*
* @author:SongJia
*
* @date: 2017-3-14下午4:12:31
*
*/
@RequestMapping(value = "/deploymentProcessDefinition")
@ResponseBody
public String deploymentProcessDefinition(String processname,String deploymentname){
Gson gson = new Gson();
BaseBean> bean = new BaseBean>();
try {
ProcessEngine engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("config/activiti.cfg.xml").buildProcessEngine();
//与流程定义和部署相关的service
RepositoryService service = engine.getRepositoryService();
//创建一个部署对象
DeploymentBuilder createDeployment = service.createDeployment().name(deploymentname);//添加名称
//加载文件
DeploymentBuilder addClasspathResource = createDeployment.addClasspathResource("diagrams/"+processname+".bpmn");
//部署完成
Deployment deployment = addClasspathResource.deploy();
if(deployment!=null){
bean.setMessage("部署流程定义成功");
bean.setCode("0");
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}else{
bean.setMessage("部署流程定义失败");
bean.setCode("1");
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}
} catch (Exception e) {
bean.setMessage("部署流程定义失败");
bean.setCode("1");
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}
}
删除流程定义:(建议以流程实例ID的方式用代码方式删除流程、如果在数据库中直接用SQL删除,因为表之间有关系,会出现很多难以解决的问题)
/**
*
*
*Description:删除流程定义
*
* @author:SongJia
*
* @date: 2017-3-21下午3:50:37
*
*/
@RequestMapping(value = "/removedifinition")
@ResponseBody
public String removeDifinition(String id){
ProcessEngine engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("config/activiti.cfg.xml").buildProcessEngine();
engine.getRepositoryService().deleteDeployment(id, true);
Gson gson = new Gson();
BaseBean> bean = new BaseBean>();
try {
bean.setMessage("删除流程定义成功");
bean.setCode("0");
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
} catch (Exception e) {
bean.setMessage("部署流程定义失败");
bean.setCode("1");
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}
}
删除全部流程定义:
/**
*
*
*Description:删除全部流程定义
*
* @author:SongJia
*
* @date: 2017-3-15上午10:15:00
*
*/
@Test
public void delProcessDefinition(){
ProcessDefinitionQuery createProcessDefinitionQuery = engine.getRepositoryService().createProcessDefinitionQuery();
List list = createProcessDefinitionQuery.list();
for (ProcessDefinition processDefinition : list) {
//只能删除没有启动的流程,如果启动,则会抛出异常
//Error updating database. Cause: java.sql.SQLException: ORA-02292: 违反完整约束条件 (ACTIVITI.ACT_FK_EXE_PROCDEF) - 已找到子记录
//engine.getRepositoryService().deleteDeployment("1");
//删除和流程引擎相关的数据,连级删除。
engine.getRepositoryService().deleteDeployment(processDefinition.getDeploymentId(), true);
System.out.println("删除的流程定义:"+processDefinition.getDeploymentId());
}
}
获取已部署流程定义:(针对查出来的流程定义ProcessDefinition不能直接用GSON转成JSON字符串,所以将查询出来的ProcessDefinition用自己创建的DefinitionBean来重新封装并转换成JSON字符串返回给客户端)
/**
*
*
*Description:获取已部署流程定义
*
* @author:SongJia
*
* @date: 2017-3-21上午10:06:04
*
*/
@RequestMapping(value = "/getProcessDefinitions")
@ResponseBody
public String getProcessDefinitions(){
Gson gson = new Gson();
BaseBean> bean = new BaseBean>();
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
try {
ProcessEngine engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("config/activiti.cfg.xml").buildProcessEngine();
List list = engine.getRepositoryService().createProcessDefinitionQuery().orderByProcessDefinitionVersion().desc().list();
List beans = new ArrayList();
if(list!=null){
for (ProcessDefinition processDefinition : list) {
DefinitionBean definitionBean = new DefinitionBean();
Deployment singleResult = engine.getRepositoryService().createDeploymentQuery().deploymentId(processDefinition.getDeploymentId()).singleResult();
definitionBean.setId(processDefinition.getId());
definitionBean.setKey(processDefinition.getKey());
definitionBean.setPro_defi_name(processDefinition.getName());
definitionBean.setPro_devl_name(singleResult.getName());
definitionBean.setPro_devl_time(format.format(singleResult.getDeploymentTime()));
definitionBean.setVersion(processDefinition.getVersion()+"");
definitionBean.setDeployment_id(processDefinition.getDeploymentId());
beans.add(definitionBean);
}
bean.setMessage("获取流程定义成功");
bean.setCode("0");
bean.setDate(beans);
}else{
bean.setMessage("未获取到流程定义");
bean.setCode("1");
}
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
} catch (Exception e) {
e.printStackTrace();
bean.setMessage("获取流程定义失败");
bean.setCode("1");
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}
}
四 启动流程
启动流程:以流程实例id启动流程
/**
*
*
*Description:启动流程
*
* @author:SongJia
*
* @date: 2017-3-16上午9:25:35
*
*/
@RequestMapping(value = "/startprocess")
@ResponseBody
public String startProcess(String key){
Gson gson = new Gson();
BaseBean> bean = new BaseBean>();
try {
if(key==null){
bean.setMessage("缺少必要参数");
bean.setCode("1");
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}
ProcessEngine engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("config/activiti.cfg.xml").buildProcessEngine();
ProcessInstance startProcessInstanceByKey = engine.getRuntimeService().startProcessInstanceByKey(key);
if(startProcessInstanceByKey!=null){
bean.setMessage("启动成功");
bean.setCode("0");
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}
bean.setMessage("启动失败");
bean.setCode("1");
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
} catch (Exception e) {
bean.setMessage("启动失败");
bean.setCode("1");
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}
}
五 查询待办
查询个人任务:
/**
*
*
*Description:查询个人任务
*
* @author:SongJia
*
* @date: 2017-3-16上午9:25:35
*
*/
@RequestMapping(value = "/queryPersonalTask")
@ResponseBody
public String queryPersonalTask(String assignee){
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
Gson gson = new Gson();
BaseBean> bean = new BaseBean>();
if(assignee==null){
bean.setMessage("缺少必要参数");
bean.setCode("1");
String json = gson.toJson(bean);
return json;
}
ProcessEngine engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("config/activiti.cfg.xml").buildProcessEngine();
List list = engine.getTaskService().createTaskQuery().taskAssignee(assignee).orderByTaskCreateTime().desc().list();
if(list!=null){
List taskBeans = new ArrayList();
for (Task task : list) {
TaskBean taskBean = new TaskBean();
taskBean.setTask_id(task.getId());
taskBean.setTask_name(task.getName());
taskBean.setTask_create_time(format.format(task.getCreateTime()));
taskBean.setTask_assignee(task.getAssignee());
taskBeans.add(taskBean);
}
bean.setDate(taskBeans);
bean.setMessage("查询成功");
bean.setCode("0");
}else{
bean.setMessage("查询失败");
bean.setCode("1");
}
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}
查询组任务:
/**
*
*
*Description:查询当前用户组任务
*
* @author:SongJia
*
* @date: 2017-3-21下午5:17:56
*
*
*/
@RequestMapping(value = "/querygrouptask")
@ResponseBody
public String queryGroupTask(String assignee){
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
Gson gson = new Gson();
BaseBean> bean = new BaseBean>();
ProcessEngine engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("config/activiti.cfg.xml").buildProcessEngine();
List list = engine.getTaskService()// 与正在执行的任务管理相关的Service
.createTaskQuery()// 创建任务查询对象
/** 查询条件(where部分) */
.taskCandidateUser(assignee)// 组任务的办理人查询
/** 排序 */
.orderByTaskCreateTime().asc()// 使用创建时间的升序排列
/** 返回结果集 */
.list();// 返回列表
if(list!=null){
List taskBeans = new ArrayList();
for (Task task : list) {
TaskBean taskBean = new TaskBean();
taskBean.setTask_id(task.getId());
taskBean.setTask_name(task.getName());
taskBean.setTask_create_time(format.format(task.getCreateTime()));
taskBean.setTask_assignee(task.getAssignee());
taskBeans.add(taskBean);
}
bean.setDate(taskBeans);
bean.setMessage("查询成功");
bean.setCode("0");
}else{
bean.setMessage("查询失败");
bean.setCode("1");
}
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}
六 办理任务
办理任务:
/**
*
*
*Description:办理任务
*
* @author:SongJia
*
* @date: 2017-3-16上午9:25:35
*
*/
@RequestMapping(value = "/completeTask")
@ResponseBody
public String completeTask(String taskid,String comuser){
System.out.println(comuser);
Gson gson = new Gson();
BaseBean> bean = new BaseBean>();
if(taskid==null){
bean.setMessage("缺少必要参数");
bean.setCode("1");
String json = gson.toJson(bean);
return json;
}
ProcessEngine engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("config/activiti.cfg.xml").buildProcessEngine();
try {
engine.getTaskService().claim(taskid, comuser);
engine.getTaskService().complete(taskid);
bean.setMessage("办理成功");
bean.setCode("1");
} catch (Exception e) {
bean.setMessage("办理失败");
bean.setCode("1");
}
String json = gson.toJson(bean,new TypeToken>>() { }.getType());
return json;
}
驳回任务:
/**
*
*
*Description:流程驳回
*
* @author:SongJia
*
* @date: 2017-3-24下午2:57:08
*
*/
public void processReject(){
String taskId="";
ProcessEngine engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("config/activiti.cfg.xml").buildProcessEngine();
HistoryService historyService = engine.getHistoryService();
RuntimeService runtimeService = engine.getRuntimeService();
RepositoryService repositoryService = engine.getRepositoryService();
TaskService taskService = engine.getTaskService();
try {
Map variables;
// 取得当前任务
HistoricTaskInstance currTask = historyService
.createHistoricTaskInstanceQuery().taskId(taskId)
.singleResult();
// 取得流程实例
ProcessInstance instance = runtimeService
.createProcessInstanceQuery()
.processInstanceId(currTask.getProcessInstanceId())
.singleResult();
if (instance == null) {
//流程已经结束
}
variables = instance.getProcessVariables();
// 取得流程定义
ProcessDefinitionEntity definition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(currTask
.getProcessDefinitionId());
if (definition == null) {
//流程定义未找到
}
// 取得上一步活动
ActivityImpl currActivity = ((ProcessDefinitionImpl) definition)
.findActivity(currTask.getTaskDefinitionKey());
List nextTransitionList = currActivity
.getIncomingTransitions();
// 清除当前活动的出口
List oriPvmTransitionList = new ArrayList();
List pvmTransitionList = currActivity
.getOutgoingTransitions();
for (PvmTransition pvmTransition : pvmTransitionList) {
oriPvmTransitionList.add(pvmTransition);
}
pvmTransitionList.clear();
// 建立新出口
List newTransitions = new ArrayList();
for (PvmTransition nextTransition : nextTransitionList) {
PvmActivity nextActivity = nextTransition.getSource();
ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definition)
.findActivity(nextActivity.getId());
TransitionImpl newTransition = currActivity
.createOutgoingTransition();
newTransition.setDestination(nextActivityImpl);
newTransitions.add(newTransition);
}
// 完成任务
List tasks = taskService.createTaskQuery()
.processInstanceId(instance.getId())
.taskDefinitionKey(currTask.getTaskDefinitionKey()).list();
for (Task task : tasks) {
taskService.complete(task.getId(), variables);
historyService.deleteHistoricTaskInstance(task.getId());
}
// 恢复方向
for (TransitionImpl transitionImpl : newTransitions) {
currActivity.getOutgoingTransitions().remove(transitionImpl);
}
for (PvmTransition pvmTransition : oriPvmTransitionList) {
pvmTransitionList.add(pvmTransition);
}
//成功
} catch (Exception e) {
//失败
}
}
七 查询任务办理记录
/**
*
*
*Description:查询任务办理记录
*
* @author:SongJia
*
* @date: 2017-3-22上午8:54:01
*
*/
@RequestMapping(value = "/queryhistorypersontask")
@ResponseBody
public String queryHistoryPersonTask(String processInstanceId){
Gson gson = new Gson();
BaseBean> basebean = new BaseBean>();
ProcessEngine engine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("config/activiti.cfg.xml").buildProcessEngine();
List list = engine.getHistoryService().createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list();
SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
List beans = new ArrayList();
if(list!=null){
for (HistoricTaskInstance historicTaskInstance : list) {
HistoricTaskInstanceBean bean = new HistoricTaskInstanceBean();
bean.setId(historicTaskInstance.getId());
bean.setProcess_definition_id(historicTaskInstance.getProcessDefinitionId());
bean.setProcess_instance_id(historicTaskInstance.getProcessInstanceId());
bean.setExecution_id(historicTaskInstance.getExecutionId());
bean.setTenant_id(historicTaskInstance.getTenantId());
bean.setName(historicTaskInstance.getName());
bean.setAssignee(historicTaskInstance.getAssignee());
bean.setStart_time(format.format(historicTaskInstance.getStartTime()));
bean.setEnd_time(format.format(historicTaskInstance.getEndTime()));
bean.setDuration_in_millis(historicTaskInstance.getDurationInMillis()+"");
beans.add(bean);
}
basebean.setMessage("获取任务执行信息成功");
basebean.setCode("0");
basebean.setDate(beans);
String json = gson.toJson(basebean);
return json;
}else{
basebean.setMessage("获取任务执行信息失败");
basebean.setCode("1");
String json = gson.toJson(basebean);
return json;
}
}