<?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: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.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="activitiTransactionManager" />
<!-- 设置数据库schema的更新方式 -->
<property name="databaseSchemaUpdate" value="false" />
<!-- 是否启动jobExecutor -->
<property name="jobExecutorActivate" value="true" />
<property name="activityFontName" value="宋体"/>
<property name="labelFontName" value="宋体"/>
<property name="annotationFontName" value="宋体"/>
<!-- 解析xml流程文件所使用的字符集,默认为utf8,依据数据库来
<property name="xmlEncoding" value="utf8"/>-->
</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="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" />
<bean id="formService" factory-bean="processEngine"
factory-method="getFormService" />
</beans>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>5.22.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>5.22.0</version>
</dependency>
@Service
public class Process {
@Autowired
ProcessEngine processEngine;
@Autowired
ProcessEngineConfiguration processEngineConfiguration;
@Autowired
RepositoryService repositoryService;
@Autowired
ManagementService managementService;
@Autowired
RuntimeService runtimeService;
@Autowired
HistoryService historyService;
@Autowired
TaskService taskService;
@Value("${activiti.save.path}")
private String activitiPath;
/**
* 发布流程
*
* @param bpmnPath
* 流程路径 非空
* @param name
* 流程图名称
* @version 0.1.0 2016/12/04
*
*/
public Deployment deployClasspathResource(String bpmnPath, String name) {
/** 1:创建一个部署对象;2:添加部署的名称;3:从classpath的资源中加载,一次只能加载一个文件;4:完成部署 */
Deployment deployment = repositoryService.createDeployment().name(name).addClasspathResource(bpmnPath).deploy();
return deployment;
}
public Deployment deployInputStream(InputStream bpmnPath, InputStream pngPath, String name) {
Deployment deployment = repositoryService.createDeployment().name(name).addInputStream(name + ".bpmn", bpmnPath).addInputStream(name + ".png", pngPath).deploy();
return deployment;
}
public Deployment deployString(String bpmnXml, String name) {
Deployment deployment = repositoryService.createDeployment().name(name).addString(name + ".bpmn", bpmnXml).deploy();
return deployment;
}
/**
* 删除流程定义
*
* @param id
* 流程id
* @param flag
* ture删除启动的流程定义;false未启动的流程定义 默认false
* @version 0.1.0 2016/12/04
*
*/
public void deleteProcessDefinition(String id, boolean flag) {
if (flag) {
// 删除流程定义 包括启动过的流程
repositoryService.deleteDeployment(id, flag);
} else {
// 只能删除没有启动的流程定义,如果流程启动则抛出异常
repositoryService.deleteDeployment(id);// 删除流程定义 id为流程id
}
}
/**
* 启动流程实例
*
* @param processDefinitionKey
* 流程key
* @version 0.1.0 2016/12/04
*
*/
public ProcessInstance startProessInstance(String processDefinitionKey, String businessKey, Map<String, Object> jsnVariables) throws Exception {
ProcessInstance processInstance = null;
if (StringUtils.isNotBlank(businessKey)) {
if (jsnVariables != null & !jsnVariables.isEmpty()) {
processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, jsnVariables);
} else {
processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey);
}
} else {
if (jsnVariables != null & !jsnVariables.isEmpty()) {
processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, jsnVariables);
} else {
processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey);
}
}
return processInstance;
}
/**
* 查看个人任务
*
* @param assignee
* 审核人
* @version 0.1.0 2016/12/04
*
*/
public List<Task> queryAssigneeTask(String assignee) throws Exception {
/** 这里使用TaskService完成任务的查询 */
List<Task> tasks = taskService.createTaskQuery().taskAssignee(assignee).list();
return tasks;
}
public List<Task> queryTaskProcessInstanceId(String processInstanceId, Map<String, Object> jsnVariables) throws Exception {
TaskQuery query = null;
if (jsnVariables != null && StringUtils.isNotBlank(jsnVariables.getOrDefault("assignee", "").toString()))
query = taskService.createTaskQuery().processInstanceId(processInstanceId).taskAssignee(jsnVariables.getOrDefault("assignee", "").toString()).orderByTaskName().asc();
else
query = taskService.createTaskQuery().processInstanceId(processInstanceId).orderByTaskName().asc();
List<Task> tasks = null;
if (query != null) {
tasks = query.list();
}
return tasks;
}
/**
* 查看参与者任务
*/
@Override
@Transactional(value = FinalConstant.TRANSACTION_ACTIVITI, propagation = Propagation.REQUIRED)
public List<Task> queryCandidateUserTask(String candidateUser) throws Exception {
/** 这里使用TaskService完成任务的查询 */
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser(candidateUser).list();
return tasks;
}
/**
* 查看组任务
*/
public List<Task> queryCandidateGroupTask(List<String> candidateGroup) throws Exception {
/** 这里使用完成任务的查询 */
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroupIn(candidateGroup).list();
return tasks;
}
/**
* 完成任务
*
* @param taskId
* 任务id
* @param variables
* 流程变量
* @version 0.1.0 2016/12/04
*
*/
public void completeTask(String taskId, Map<String, Object> variables) throws Exception {
/** 这里使用TaskService完成任务的办理 */
if (variables != null)
taskService.complete(taskId, variables);
else
taskService.complete(taskId);
}
/**
* 实现自动完成任务
*
* @param processInstanceId
* 实例id
* @param assignee
* 处理人
* @param variables
* 流程变量
*/
public void completeTaskProcessInstanceId(String processInstanceId, String assignee, Map<String, Object> variables) {
TaskQuery query = taskService.createTaskQuery().processInstanceId(processInstanceId).taskAssignee(assignee).orderByTaskName().asc();
List<Task> tasks = query.list();
for (Task task : tasks) {
if (variables != null)
taskService.complete(task.getId(), variables);
else
taskService.complete(task.getId());
}
}
public ProcessInstance getProcessInstanceByBusinessKey(String businessKey) throws Exception {
return runtimeService.createProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
}
public ProcessInstance getProcessInstanceById(String processInstanceId) throws Exception {
return runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
}
public Task getTaskByBusinessKey(String businessKey) {
// TODO Auto-generated method stub
return taskService.createTaskQuery().processInstanceBusinessKey(businessKey).singleResult();
}
/**
* 认领任务 通常一个任务为公共任务任务都有一个以上的候选者
*/
public void takeTask(String taskId, String userId) throws Exception {
// claim 认领
taskService.claim(taskId, userId);
}
/**
* 委托
*/
public void delegatedTask(String taskId, String userId) throws Exception {
// 委托
taskService.delegateTask(taskId, userId);
// 结果:所有者是Owner李四,处理人Assignee是userId
}
/**
* 流程是否已经结束
*
* @param processInstanceId
* 流程实例ID
* @version 0.1.0 2016/12/04
*
*/
public boolean isFinished(String processInstanceId) {
return historyService.createHistoricProcessInstanceQuery().finished().processInstanceId(processInstanceId).count() > 0;
}
/** 向组任务中添加成员 */
public void addGroupUser(String taskId, String userId) {
taskService.addCandidateUser(taskId, userId);
}
/** 向组任务中删除成员 */
public void deleteGroupUser(String taskId, String userId) {
taskService.deleteCandidateUser(taskId, userId);
}
/**
* 查询流程定义
*
* @param deploymentId
* 部署对象id
* @param processDefinitionId
* 程定义id
* @param processDefinitionKey
* 流程定义key
* @param processDefinitionKeyLike
* 流程定义key
* @param ascOrDesc
* 降序或升序 1降序 默认升序
* @version 0.1.0 2016/12/04
*
*/
public List<JSONObject> findProcessDefintion(String deploymentId, String processDefinitionId, String processDefinitionKey, String processDefinitionKeyLike, String ascOrDesc) {
ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
// 指定查询条件
if (StringUtils.isNotBlank(deploymentId)) {
processDefinitionQuery.deploymentId(deploymentId);// 使用部署对象id查询
}
if (StringUtils.isNotBlank(processDefinitionId)) {
processDefinitionQuery.processDefinitionId(processDefinitionId);// 使用流程定义id查询
}
if (StringUtils.isNotBlank(processDefinitionKey)) {
processDefinitionQuery.processDefinitionKey(processDefinitionKey);// 使用流程定义key查询
}
if (StringUtils.isNotBlank(processDefinitionKeyLike)) {
processDefinitionQuery.processDefinitionKeyLike(processDefinitionKeyLike);// 使用流程定义key模糊查询
}
// 排序
if (StringUtils.isBlank(ascOrDesc) || StringUtils.equalsIgnoreCase(ascOrDesc, "1")) {
processDefinitionQuery.orderByProcessDefinitionVersion().asc();// 按照版本升序排列
} else {
processDefinitionQuery.orderByProcessDefinitionVersion().desc();// 按照版本降序排列
}
// 返回结果集
List<ProcessDefinition> list = processDefinitionQuery.list();// 返回一个集合列表,封装流程定义
List<JSONObject> alProcess = new ArrayList<>();
JSONObject jsn;
if (list != null && list.size() > 0) {
for (ProcessDefinition pd : list) {
jsn = (JSONObject) JSONObject.toJSON(pd);
alProcess.add(jsn);
}
list.clear();
}
return alProcess;
}
/**
* 获得高亮线
*
* @param processDefinitionEntity
* 流程定义实体
* @param historicActivityInstances
* 历史活动实体
* @return 线ID集合
* @version 0.1.0 2016/12/04
*
*/
private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinitionEntity, List<HistoricActivityInstance> historicActivityInstances) {
List<String> highFlows = new ArrayList<>();// 用以保存高亮的线flowId
for (int i = 0; i < historicActivityInstances.size(); i++) {// 对历史流程节点进行遍历
ActivityImpl activityImpl = processDefinitionEntity.findActivity(historicActivityInstances.get(i).getActivityId());// 得
// 到节点定义的详细信息
List<ActivityImpl> sameStartTimeNodes = new ArrayList<>();// 用以保存后需开始时间相同的节点
if ((i + 1) >= historicActivityInstances.size()) {
break;
}
ActivityImpl sameActivityImpl1 = processDefinitionEntity.findActivity(historicActivityInstances.get(i + 1).getActivityId());// 将后面第一个节点放在时间相同节点的集合里
sameStartTimeNodes.add(sameActivityImpl1);
for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 后续第一个节点
HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 后续第二个节点
Calendar calendar = Calendar.getInstance();
calendar.setTime(activityImpl1.getStartTime());
calendar.set(Calendar.MILLISECOND, 0);
Calendar calendar1 = Calendar.getInstance();
calendar1.setTime(activityImpl2.getStartTime());
calendar1.set(Calendar.MILLISECOND, 0);
if (calendar.compareTo(calendar1) == 0) {// 如果第一个节点和第二个节点开始时间相同保存
ActivityImpl sameActivityImpl2 = processDefinitionEntity.findActivity(activityImpl2.getActivityId());
sameStartTimeNodes.add(sameActivityImpl2);
} else {// 有不相同跳出循环
break;
}
}
List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();// 取出节点的所有出去的线
for (PvmTransition pvmTransition : pvmTransitions) {// 对所有的线进行遍历
ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getDestination();// 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示
if (sameStartTimeNodes.contains(pvmActivityImpl)) {
highFlows.add(pvmTransition.getId());
}
}
}
return highFlows;
}
/**
* 流程跟踪图片
*
* @param processDefinitionId
* 流程定义ID
* @param executionId
* 流程运行ID
* @param out
* 输出流
* @throws Exception
* @version 0.1.0 2016/12/04
*
*/
public InputStream processTracking(String processDefinitionId, String executionId) throws Exception {
// 当前活动节点、活动线
List<String> activeActivityIds = new ArrayList<>();
List<String> highLightedFlows;
// 获得当前活动的节点
if (this.isFinished(executionId)) {// 如果流程已经结束,则得到结束节点
activeActivityIds.add(historyService.createHistoricActivityInstanceQuery().executionId(executionId).activityType("endEvent").singleResult().getActivityId());
} else {// 如果流程没有结束,则取当前活动节点
// 根据流程实例ID获得当前处于活动状态的ActivityId合集
activeActivityIds = runtimeService.getActiveActivityIds(executionId);
}
// 获得当前活动的节点-结束
// 获得活动的线
// 获得历史活动记录实体(通过启动时间正序排序,不然有的线可以绘制不出来)
List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery().processInstanceId(executionId).orderByHistoricActivityInstanceStartTime().asc()
.list();
// 计算活动线
highLightedFlows = getHighLightedFlows((ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processDefinitionId), historicActivityInstances);
// 获得活动的线-结束
// 绘制图形
if (null != activeActivityIds) {
InputStream imageStream = null;
try {
// 根据流程定义ID获得BpmnModel
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
// 输出资源内容到相应对象
imageStream = new DefaultProcessDiagramGenerator().generateDiagram(bpmnModel, "jpg", activeActivityIds, highLightedFlows, processEngineConfiguration.getActivityFontName(),
processEngineConfiguration.getLabelFontName(), processEngineConfiguration.getAnnotationFontName(), processEngineConfiguration.getClassLoader(), 1.0);
// IOUtils.copy(imageStream, out);
return imageStream;
} catch (Exception e) {
return imageStream;
} finally {
IOUtils.closeQuietly(imageStream);
}
}
return null;
}
public Collection<FlowElement> queryFlowElement(InputStream resouceStream) {
Collection<FlowElement> flowElements = null;
try {
InputStreamReader in = new InputStreamReader(resouceStream, "UTF-8");
XMLStreamReader xtr = XMLInputFactory.newInstance().createXMLStreamReader(in);
BpmnModel model = new BpmnXMLConverter().convertToBpmnModel(xtr);
flowElements = model.getMainProcess().getFlowElements();
} catch (Exception e) {
e.printStackTrace();
}
return flowElements;
}
/*
* 删除key值相同的所有不同版本的流程定义
*/
public void deleteProcessDefinitionByKey(String processDefinitionKey) {
// 先使用流程定义的key查询流程定义,查询出所有的版本
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey)// 使用流程定义的key查询
.list();
// 遍历,获取每个流程定义的部署ID
if (list != null && list.size() > 0) {
for (ProcessDefinition pd : list) {
// 获取部署ID
String deploymentId = pd.getDeploymentId();
repositoryService.deleteDeployment(deploymentId, true);
}
}
}
public InputStream getDiagramByDeploymentId(String deploymentId) throws IOException {
// 获取图片资源名称
List<String> list = repositoryService.getDeploymentResourceNames(deploymentId);
// 定义图片资源的名称
String resourceName = "";
if (list != null && list.size() > 0) {
for (String name : list) {
if (name.indexOf(".png") >= 0) {
resourceName = name;
}
}
}
return repositoryService.getResourceAsStream(deploymentId, resourceName);
}
public Task queryTaskById(String taskId) {
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
return task;
}
public Map<String, Object> getTaskVariables(String taskId) throws IOException {
try {
return taskService.getVariables(taskId);
} catch (Exception e) {
return null;
}
}
public HistoricProcessInstance findHistoryProcessInstanceByBusKey(String businessKey) throws Exception {
return historyService.createHistoricProcessInstanceQuery()
.processInstanceBusinessKey(businessKey).singleResult();
}
}