Pārlūkot izejas kodu

提交工作流相关代码

chenken 8 gadi atpakaļ
vecāks
revīzija
c52074ae4d

+ 46 - 27
cqb-flow-core/pom.xml

@@ -1,27 +1,46 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>comm-ques-bank</artifactId>
-        <groupId>com.qmth.cqb</groupId>
-        <version>0.1.0</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>cqb-flow-core</artifactId>
-    <packaging>jar</packaging>
-
-    <name>cqb-flow-core</name>
-
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>3.8.1</version>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>comm-ques-bank</artifactId>
+        <groupId>com.qmth.cqb</groupId>
+        <version>0.1.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>cqb-flow-core</artifactId>
+    <packaging>jar</packaging>
+
+    <name>cqb-flow-core</name>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <activiti.version>5.17.0</activiti.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        
+        <dependency>
+		    <groupId>org.activiti</groupId>
+		    <artifactId>spring-boot-starter-basic</artifactId>
+		    <version>${activiti.version}</version>
+		</dependency>
+		<dependency>
+		    <groupId>com.h2database</groupId>
+		    <artifactId>h2</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+		</dependency>
+		<dependency>
+		    <groupId>commons-httpclient</groupId>
+		    <artifactId>commons-httpclient</artifactId>
+		    <version>3.1</version>
+		</dependency>
+    </dependencies>
+</project>

+ 248 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/model/ProcessModel.java

@@ -0,0 +1,248 @@
+package com.qmth.cqb.flow.model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.activiti.engine.history.HistoricProcessInstance;
+import org.activiti.engine.repository.Deployment;
+import org.activiti.engine.repository.ProcessDefinition;
+import org.activiti.engine.runtime.ProcessInstance;
+
+/**
+ * 
+ * @Title: 流程定义模型
+ * @Description: TODO
+ * @author chenken
+ * @date   2016年9月9日
+ */
+public class ProcessModel implements Serializable{
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -4693236062286086835L;
+	
+	/**
+	 * 流程执行id
+	 */
+	private String processExecutionId;
+	/**
+	 * 流程定义id
+	 */
+	private String processDefinitionId;
+	/**
+	 * 流程实例id
+	 */
+	private String processInstanceId;
+	
+	/**
+	 * 流程定义key
+	 */
+	private String processDefinitionKey;
+	
+	/**
+	 * 流程定义名称
+	 */
+	private String processDefinitionName;
+	/**
+	 * 版本
+	 */
+	private Integer version;
+	/**
+	 * 流程发起人
+	 */
+	private String startUserId;
+	/**
+	 * 流程开始时间
+	 */
+	private Date startTime;
+	
+	/**
+	 * 流程结束时间
+	 */
+	private Date endTime;
+	/**
+	 * 流程耗时
+	 */
+	private Long durationInMillis;
+	/**
+	 * 流程部署时间
+	 */
+	private Date deploymentTime;
+	/**
+	 * 流程部署ID
+	 */
+	private String deploymentId;
+	/**
+	 * 分类
+	 */
+	private String category;
+	/**
+	 * 资源名称
+	 */
+	private String resourceName;
+	
+	public ProcessModel(){}
+	
+	/**
+	 * 组装运行时流程信息
+	 * @param processInstance
+	 * @param historicProcessInstance
+	 */
+	public ProcessModel(ProcessInstance processInstance,HistoricProcessInstance historicProcessInstance) {
+		super();
+		this.processExecutionId = processInstance.getId();
+		this.processDefinitionId = processInstance.getProcessDefinitionId();
+		this.processInstanceId = processInstance.getProcessInstanceId();
+		this.processDefinitionName = processInstance.getProcessDefinitionName();
+		this.startUserId = historicProcessInstance.getStartUserId();
+		this.startTime = historicProcessInstance.getStartTime();
+	}
+	
+	/**
+	 * 组装流程信息
+	 * @param processDefinition
+	 * @param historicProcessInstance
+	 */
+	public ProcessModel(ProcessDefinition processDefinition,HistoricProcessInstance historicProcessInstance) {
+		this.processDefinitionId = processDefinition.getId();
+		this.processDefinitionName = processDefinition.getName();
+		this.processDefinitionKey = processDefinition.getKey();
+		this.category = processDefinition.getCategory();
+		this.version = processDefinition.getVersion();
+		this.processInstanceId = historicProcessInstance.getId();
+		this.startUserId = historicProcessInstance.getStartUserId();
+		this.startTime = historicProcessInstance.getStartTime();
+		this.endTime = historicProcessInstance.getEndTime();
+		this.durationInMillis = historicProcessInstance.getDurationInMillis();
+	}
+	
+	/**
+	 * 组装流程部署信息
+	 * @param processDefinition
+	 * @param deployment
+	 */
+	public ProcessModel(ProcessDefinition processDefinition,Deployment deployment) {
+		this.processDefinitionId = processDefinition.getId();
+		this.processDefinitionName = processDefinition.getName();
+		this.processDefinitionKey = processDefinition.getKey();
+		this.version = processDefinition.getVersion();
+		this.category = processDefinition.getCategory();
+		this.resourceName = processDefinition.getResourceName();
+		this.deploymentTime = deployment.getDeploymentTime();
+		this.deploymentId = deployment.getId();
+	}
+
+	public String getProcessExecutionId() {
+		return processExecutionId;
+	}
+
+	public void setProcessExecutionId(String processExecutionId) {
+		this.processExecutionId = processExecutionId;
+	}
+
+	public String getProcessDefinitionId() {
+		return processDefinitionId;
+	}
+
+	public void setProcessDefinitionId(String processDefinitionId) {
+		this.processDefinitionId = processDefinitionId;
+	}
+
+	public String getProcessInstanceId() {
+		return processInstanceId;
+	}
+
+	public void setProcessInstanceId(String processInstanceId) {
+		this.processInstanceId = processInstanceId;
+	}
+
+	public String getProcessDefinitionKey() {
+		return processDefinitionKey;
+	}
+
+	public void setProcessDefinitionKey(String processDefinitionKey) {
+		this.processDefinitionKey = processDefinitionKey;
+	}
+
+	public String getProcessDefinitionName() {
+		return processDefinitionName;
+	}
+
+	public void setProcessDefinitionName(String processDefinitionName) {
+		this.processDefinitionName = processDefinitionName;
+	}
+
+	public Integer getVersion() {
+		return version;
+	}
+
+	public void setVersion(Integer version) {
+		this.version = version;
+	}
+
+	public String getStartUserId() {
+		return startUserId;
+	}
+
+	public void setStartUserId(String startUserId) {
+		this.startUserId = startUserId;
+	}
+
+	public Date getStartTime() {
+		return startTime;
+	}
+
+	public void setStartTime(Date startTime) {
+		this.startTime = startTime;
+	}
+
+	public Date getEndTime() {
+		return endTime;
+	}
+
+	public void setEndTime(Date endTime) {
+		this.endTime = endTime;
+	}
+
+	public Long getDurationInMillis() {
+		return durationInMillis;
+	}
+
+	public void setDurationInMillis(Long durationInMillis) {
+		this.durationInMillis = durationInMillis;
+	}
+
+	public Date getDeploymentTime() {
+		return deploymentTime;
+	}
+
+	public void setDeploymentTime(Date deploymentTime) {
+		this.deploymentTime = deploymentTime;
+	}
+
+	public String getDeploymentId() {
+		return deploymentId;
+	}
+
+	public void setDeploymentId(String deploymentId) {
+		this.deploymentId = deploymentId;
+	}
+
+	public String getCategory() {
+		return category;
+	}
+
+	public void setCategory(String category) {
+		this.category = category;
+	}
+
+	public String getResourceName() {
+		return resourceName;
+	}
+
+	public void setResourceName(String resourceName) {
+		this.resourceName = resourceName;
+	}
+	
+}

+ 120 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/model/TaskModel.java

@@ -0,0 +1,120 @@
+package com.qmth.cqb.flow.model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.activiti.engine.repository.ProcessDefinition;
+import org.activiti.engine.task.Task;
+
+public class TaskModel implements Serializable{
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = -2964362922431697531L;
+	/**
+	 * 任务ID
+	 */
+	private String taskId;
+	/**
+	 * 任务名称
+	 */
+	private String taskName;
+	/**
+	 * 任务办理人
+	 */
+	private String taskAssignee;
+	/**
+	 * 任务办理角色
+	 */
+	private String taskRole;
+	/**
+	 * 流程名称
+	 */
+	private String processName;
+	/**
+	 * 流程实例ID
+	 */
+	private String processInstanceId;
+	/**
+	 * 流程定义ID
+	 */
+	private String processDefinitionId;
+	/**
+	 * 归属系统
+	 */
+	private String category;
+	/**
+	 * 任务开始时间
+	 */
+	private Date startTime;
+	
+	public TaskModel() {
+	}
+	
+	public TaskModel(Task task, ProcessDefinition processDefinition) {
+		this.taskId = task.getId();
+		this.taskName = task.getName();
+		this.startTime = task.getCreateTime();
+		this.taskAssignee = task.getAssignee();
+		this.processInstanceId = task.getProcessInstanceId();
+		this.processDefinitionId = task.getProcessDefinitionId();
+		this.processName = processDefinition.getName();
+		this.category = processDefinition.getCategory();
+	}
+	
+	public String getTaskId() {
+		return taskId;
+	}
+	public void setTaskId(String taskId) {
+		this.taskId = taskId;
+	}
+	public String getTaskName() {
+		return taskName;
+	}
+	public void setTaskName(String taskName) {
+		this.taskName = taskName;
+	}
+	public String getTaskAssignee() {
+		return taskAssignee;
+	}
+	public void setTaskAssignee(String taskAssignee) {
+		this.taskAssignee = taskAssignee;
+	}
+	public String getProcessName() {
+		return processName;
+	}
+	public void setProcessName(String processName) {
+		this.processName = processName;
+	}
+	public String getCategory() {
+		return category;
+	}
+	public void setCategory(String category) {
+		this.category = category;
+	}
+	public Date getStartTime() {
+		return startTime;
+	}
+	public void setStartTime(Date startTime) {
+		this.startTime = startTime;
+	}
+	public String getProcessInstanceId() {
+		return processInstanceId;
+	}
+	public void setProcessInstanceId(String processInstanceId) {
+		this.processInstanceId = processInstanceId;
+	}
+	public String getProcessDefinitionId() {
+		return processDefinitionId;
+	}
+	public void setProcessDefinitionId(String processDefinitionId) {
+		this.processDefinitionId = processDefinitionId;
+	}
+	public String getTaskRole() {
+		return taskRole;
+	}
+	public void setTaskRole(String taskRole) {
+		this.taskRole = taskRole;
+	}
+	
+}

+ 148 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/model/WorkFlowModel.java

@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2016, FPX and/or its affiliates. All rights reserved.
+ * Use, Copy is subject to authorized license.
+*/
+package com.qmth.cqb.flow.model;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Title: 工作流公共model
+ * @Description:TODO
+ * @Company:4px
+ * @author chenken
+ * @date 2016年6月27日
+ * @since v1.0.0
+ */
+public class WorkFlowModel  implements Serializable {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 605787172551035649L;
+	/**
+	 * 流程定义ID
+	 */
+	private String processDefinitionId;
+	/**
+	 * 流程实例ID
+	 */
+	private String processInstanceId;
+	/**
+	 * 流程启动者
+	 */
+	private String starter;
+	/**
+	 * 当前任务id
+	 */
+	private String taskId;
+	/**
+	 * 当前任务名称
+	 */
+	private String taskName;
+	/**
+	 * 当前节点service 名称
+	 */
+	private String nodeServiceName;
+	/**
+	 * 当前节点操作人
+	 */
+	private String assignee;
+	/**
+	 * 下一节点操作人
+	 * 
+	 * 可在当前节点任务完成时,通过该字段设置下一节点操作人
+	 * 注意在流程节点中设置变量${operator}
+	 */
+	private String nextOperator;
+	/**
+	 * 条件  当产生分支的时候,条件判断 
+	 * 例如 ${condition=='a'}  走向a分支   
+	 * 	  ${condition=='b'} 走向b分支 
+	 * 是否通过/不通过
+	 * 同意/不同意
+	 *  ${condition=='1'}  通过  
+	 *  ${condition=='0'}  打回
+	 * 统一用该字段 
+	 */
+	private String condition;
+	
+	private String category;
+	
+	private Map<String,Object> variables = new HashMap<String, Object>();
+	
+	public WorkFlowModel(){}
+	
+	public String getStarter() {
+		return starter;
+	}
+	public void setStarter(String starter) {
+		this.starter = starter;
+	}
+	public String getNodeServiceName() {
+		return nodeServiceName;
+	}
+	public void setNodeServiceName(String nodeServiceName) {
+		this.nodeServiceName = nodeServiceName;
+	}
+	public String getTaskId() {
+		return taskId;
+	}
+	public void setTaskId(String taskId) {
+		this.taskId = taskId;
+	}
+	public String getProcessInstanceId() {
+		return processInstanceId;
+	}
+	public void setProcessInstanceId(String processInstanceId) {
+		this.processInstanceId = processInstanceId;
+	}
+	public String getTaskName() {
+		return taskName;
+	}
+	public void setTaskName(String taskName) {
+		this.taskName = taskName;
+	}
+	public String getAssignee() {
+		return assignee;
+	}
+	public void setAssignee(String assignee) {
+		this.assignee = assignee;
+	}
+	public String getProcessDefinitionId() {
+		return processDefinitionId;
+	}
+	public void setProcessDefinitionId(String processDefinitionId) {
+		this.processDefinitionId = processDefinitionId;
+	}
+	public String getCondition() {
+		return condition;
+	}
+	public void setCondition(String condition) {
+		this.condition = condition;
+	}
+	public String getNextOperator() {
+		return nextOperator;
+	}
+	public void setNextOperator(String nextOperator) {
+		this.nextOperator = nextOperator;
+	}
+
+	public Map<String, Object> getVariables() {
+		return variables;
+	}
+
+	public void setVariables(Map<String, Object> variables) {
+		this.variables = variables;
+	}
+
+	public String getCategory() {
+		return category;
+	}
+
+	public void setCategory(String category) {
+		this.category = category;
+	}
+	
+}

+ 93 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/service/ComProcessService.java

@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016, FPX and/or its affiliates. All rights reserved.
+ * Use, Copy is subject to authorized license.
+*/
+package com.qmth.cqb.flow.service;
+
+import java.io.InputStream;
+import java.util.List;
+
+import org.activiti.engine.repository.ProcessDefinition;
+
+import com.qmth.cqb.flow.model.ProcessModel;
+import com.qmth.cqb.flow.model.WorkFlowModel;
+
+
+
+/**
+ * @Title: ComTaskService
+ * @Description:TODO
+ * @Company:4px
+ * @author chenken
+ * @date 2016年6月24日
+ * @since v1.0.0
+ */
+public interface ComProcessService {
+	/**
+	 * 通过读取classpath下的文件部署流程定义
+	* @Title: deployProcess  
+	* @Description: TODO(这里用一句话描述这个方法的作用)
+	* @param
+	* @return  
+	* @throws
+	 */
+	public void deployProcess(String processName,String exportDir) throws Exception;
+	/**
+	 * 通过二进制流部署流程定义
+	 * @param inputStream
+	 * @param processName
+	 * @throws Exception
+	 */
+	public void deployProcessByInputStream(InputStream inputStream,String processName) throws Exception;
+
+	/**
+     * 根据流程实例ID查询流程定义对象{@link ProcessDefinition}
+     *
+     * @param processInstanceId 流程实例ID
+     * @return 流程定义对象{@link ProcessDefinition}
+     */
+	public ProcessDefinition findProcessDefinitionByPid(String processInstanceId);
+	/**
+     * 根据流程定义ID查询流程定义对象{@link ProcessDefinition}
+     *
+     * @param processDefinitionId 流程定义对象ID
+     * @return 流程定义对象{@link ProcessDefinition}
+     */
+	public ProcessDefinition findProcessDefinition(String processDefinitionId);
+	/**
+	 * 启动流程
+	* @Title: tranStartProcess  
+	* @Description: 启动流程
+	* @param	processDefinitionKey  流程定义key
+	* @return  
+	* @throws
+	 */
+	public String tranStartProcess(String processDefinitionKey,WorkFlowModel workFlowModel) throws Exception;
+	/**
+	 * 
+	* @Title: 获取流程定义 信息
+	* @Description: TODO(这里用一句话描述这个方法的作用)
+	* @param
+	* @return  
+	* @throws
+	 */
+	public List<ProcessModel> getProcessDefinitionList();
+	/**
+	 * 
+	* @Title: deleteProcessDefinition  
+	* @Description: 删除流程定义
+	* @param
+	* @return  
+	* @throws
+	 */
+	public void deleteProcessDefinition(String deploymentId);
+	/**
+	 * 获取流程资源
+	* @Title: getResourceByProcessDefinition  
+	* @Description: TODO(这里用一句话描述这个方法的作用)
+	* @param
+	* @return  
+	* @throws
+	 */
+	public InputStream getResourceByProcessDefinitionId(String processDefinitionId,String resourceType);
+}

+ 91 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/service/ComTaskService.java

@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, FPX and/or its affiliates. All rights reserved.
+ * Use, Copy is subject to authorized license.
+*/
+package com.qmth.cqb.flow.service;
+
+import java.util.List;
+import java.util.Map;
+
+import org.activiti.engine.impl.task.TaskDefinition;
+
+import com.qmth.cqb.flow.model.TaskModel;
+import com.qmth.cqb.flow.model.WorkFlowModel;
+
+
+
+/**
+ * @Title: ComTaskService
+ * @Description:TODO
+ * @Company:4px
+ * @author chenken
+ * @date 2016年6月24日
+ * @since v1.0.0
+ */
+public interface ComTaskService {
+	/**
+	* 查询个人可以办理的任务
+	* assignee	任务办理人		必须
+	* category	系统类别		非必须
+	* @param assignee 用户ID
+	* @return  
+	* @throws
+	 */
+	public List<TaskModel> findPersonalTaskList(String assignee,String category) throws Exception;
+	/**
+	 * 使用角色(groupId)查询可以领取的任务
+	 * @param groupId  角色ID	 必须
+	 * @param category 系统类别  非必须
+	 * @return
+	 * @throws Exception
+	 */
+	public List<TaskModel> findClaimTask(String groupId,String category) throws Exception;
+	
+	/**
+	 * 找到当前人可办理和可领取的任务
+	 * @param assignee
+	 * @param groupId
+	 * @param category
+	 * @return
+	 * @throws Exception
+	 */
+	public List<TaskModel> findAssigneedOrClaimTask(String assignee,String groupId,String category) throws Exception;
+	
+	/**
+	 * 任务办理人领取任务
+	 * @param taskId   任务ID
+	 * @param assignee 领取人
+	 */
+	public void claimTask(String taskId,String assignee);
+	
+	/**
+	 * 任务办理人完成任务
+	 * 状态:正在使用的
+	 * 描述:对外提供
+     */
+	public void completeTask(WorkFlowModel workFlowModel) throws Exception;
+	
+	/**
+	 * 任务委派
+	 * @param taskId		   任务ID
+	 * @param delegateUserId 被委派人ID
+	 */
+	public void delegateTask(String taskId,String delegateUserId);
+	/**
+	 * 
+	* @Title: completeTaskByProcInstId  
+	* @Description: 通过流程ID和任务处理人完成任务
+	* @param
+	* @return  
+	* @throws
+	 */
+	public void completeTaskByProcInstId(String procInstId,Map<String, Object> variables) throws Exception;
+	
+	/**
+	 * 根据当前任务ID获取下一节点任务信息
+	 * @param processDefinitionId   当前流程实例ID
+	 * @param activitiId   当前任务ID
+	 * @param elString 分支条件el表达式	
+	 */
+	public TaskDefinition nextTaskDefinition(String processInstanceId,String activitiId,String elString);
+}

+ 31 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/service/CompleteUserTaskService.java

@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, FPX and/or its affiliates. All rights reserved.
+ * Use, Copy is subject to authorized license.
+*/
+package com.qmth.cqb.flow.service;
+
+import com.qmth.cqb.flow.model.WorkFlowModel;
+
+
+
+/**
+ * @Title: 完成用户任务接口
+ * @Description:TODO
+ * @Company:4px
+ * @author chenken
+ * @date 2016年6月24日
+ * @since v1.0.0
+ */
+public interface CompleteUserTaskService {
+	/**
+	 * 
+	* @Title: disposeBusiness  
+	* @Description: 处理业务
+	* @param
+	* @return  
+	* @throws
+	 */
+	public void completeUserTask(WorkFlowModel workFlowModel) throws Exception;
+	
+	
+}

+ 197 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/serviceImpl/ComProcessServiceImpl.java

@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2016, FPX and/or its affiliates. All rights reserved.
+ * Use, Copy is subject to authorized license.
+*/
+package com.qmth.cqb.flow.serviceImpl;
+
+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.HistoryService;
+import org.activiti.engine.IdentityService;
+import org.activiti.engine.RepositoryService;
+import org.activiti.engine.RuntimeService;
+import org.activiti.engine.history.HistoricProcessInstance;
+import org.activiti.engine.repository.Deployment;
+import org.activiti.engine.repository.ProcessDefinition;
+import org.activiti.engine.repository.ProcessDefinitionQuery;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import com.qmth.cqb.flow.model.ProcessModel;
+import com.qmth.cqb.flow.model.WorkFlowModel;
+import com.qmth.cqb.flow.service.ComProcessService;
+
+
+
+
+/**
+ * @Title: 流程相关service
+ * @Description:TODO
+ * @Company:4px
+ * @author chenken
+ * @date 2016年6月24日
+ * @since v1.0.0
+ */
+@Service("comProcessService")
+public class ComProcessServiceImpl implements ComProcessService{
+	 protected Logger logger = LoggerFactory.getLogger(getClass());
+	 
+	 @Autowired
+     protected RuntimeService runtimeService;
+
+     @Autowired
+     protected RepositoryService repositoryService;
+
+     @Autowired
+     protected HistoryService historyService;
+     
+     @Autowired
+     protected IdentityService identityService;
+	/**
+	 * 发布流程定义
+	 */
+	@Override
+	public void deployProcess(String processPath,String processName) throws Exception {
+		ResourceLoader resourceLoader = new DefaultResourceLoader();
+		String classpathResourceUrl = "classpath:/diagrams/"+processPath;
+        logger.debug("read workflow from: {}", classpathResourceUrl);
+        Resource resource = resourceLoader.getResource(classpathResourceUrl);
+        InputStream inputStream = resource.getInputStream();
+        if (inputStream == null) {
+            logger.warn("ignore deploy workflow module: {}", classpathResourceUrl);
+        } else {
+            logger.debug("finded workflow module: {}, deploy it!", classpathResourceUrl);
+            String fileSuffix = processPath.substring(processPath.lastIndexOf(".")+1,processPath.length());
+            //Deployment deployment = null;
+            if("ZIP".equals(fileSuffix.toUpperCase())){
+            	 ZipInputStream zis = new ZipInputStream(inputStream);
+                 repositoryService.createDeployment().addZipInputStream(zis).name(processName).deploy();
+            }else{
+            	 repositoryService.createDeployment().addInputStream(processPath, inputStream).name(processName).deploy();
+            }
+            /*if(deployment!=null){
+	            // export diagram
+	            List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list();
+	            for (ProcessDefinition processDefinition : list) {
+	                WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir);
+	            }
+            }*/
+        }
+	}
+	
+	/**
+	 * 发布流程定义
+	 */
+	@Override
+	public void deployProcessByInputStream(InputStream inputStream,String processName) throws Exception {
+        if (inputStream == null) {
+            logger.warn("流程资源为空!");
+        } else {
+            logger.debug("找到流程资源,开始部署!");
+            String fileSuffix = processName.substring(processName.lastIndexOf(".")+1,processName.length());
+            Deployment deployment = null;
+            if("ZIP".equals(fileSuffix.toUpperCase())){
+            	 ZipInputStream zis = new ZipInputStream(inputStream);
+                 deployment = repositoryService.createDeployment().addZipInputStream(zis).deploy();
+            }else{
+            	 deployment = repositoryService.createDeployment().addInputStream(processName, inputStream).deploy();
+            }
+        }
+	}
+	
+	/**
+     * 根据流程实例ID查询流程定义对象{@link ProcessDefinition}
+     *
+     * @param processInstanceId 流程实例ID
+     * @return 流程定义对象{@link ProcessDefinition}
+     */
+    public ProcessDefinition findProcessDefinitionByPid(String processInstanceId) {
+        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
+        String processDefinitionId = historicProcessInstance.getProcessDefinitionId();
+        ProcessDefinition processDefinition = findProcessDefinition(processDefinitionId);
+        return processDefinition;
+    }
+    
+	/**
+     * 根据流程定义ID查询流程定义对象{@link ProcessDefinition}
+     *
+     * @param processDefinitionId 流程定义对象ID
+     * @return 流程定义对象{@link ProcessDefinition}
+     */
+    public ProcessDefinition findProcessDefinition(String processDefinitionId) {
+        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
+        return processDefinition;
+    }
+    
+	/**
+	 * 启动流程
+	 */
+	@Override
+	public String tranStartProcess(String processDefinitionKey,WorkFlowModel workFlowModel) throws Exception {
+		Assert.hasText(processDefinitionKey, "流程定义Key不能为空");
+		Assert.hasText(workFlowModel.getStarter(), "流程发起人不能为空");
+		 // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator
+        identityService.setAuthenticatedUserId(workFlowModel.getStarter());
+        Map<String,Object> variables = workFlowModel.getVariables();
+        if(StringUtils.isBlank(workFlowModel.getNextOperator())){
+			variables.put("operator",null);
+		}else{
+			variables.put("operator",workFlowModel.getNextOperator());
+		}
+        String processInstanceId = runtimeService.startProcessInstanceByKey(processDefinitionKey,variables).getProcessInstanceId();
+		return processInstanceId;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.fpx.workflow.activiti.service.ComProcessService#getProcessDefinitionList()
+	 */
+	@Override
+	public List<ProcessModel> getProcessDefinitionList() {
+		List<ProcessModel> processModelList = new ArrayList<ProcessModel>();
+		ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().orderByDeploymentId().desc();  
+		List<ProcessDefinition> processDefinitionList = processDefinitionQuery.list();  
+		for (ProcessDefinition processDefinition : processDefinitionList) {  
+	        String deploymentId = processDefinition.getDeploymentId();  
+	        Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
+	        processModelList.add(new ProcessModel(processDefinition, deployment));  
+	    } 
+		return processModelList;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.fpx.workflow.activiti.service.ComProcessService#deleteProcessDefinition()
+	 */
+	@Override
+	public void deleteProcessDefinition(String deploymentId) {
+		//true 表示把流程相关的数据删除
+		repositoryService.deleteDeployment(deploymentId, true);
+	}
+
+	@Override
+	public InputStream getResourceByProcessDefinitionId(String processDefinitionId,String resourceType){
+		//流程定义对象
+         ProcessDefinition processDefinition = repositoryService
+        		.createProcessDefinitionQuery()
+        		.processDefinitionId(processDefinitionId)
+                .singleResult();
+		 String resourceName = "";
+         if (resourceType.equals("image")) {
+            resourceName = processDefinition.getDiagramResourceName();
+         } else if (resourceType.equals("xml")) {
+            resourceName = processDefinition.getResourceName();
+         }
+	     return repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
+	}
+
+}

+ 262 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/serviceImpl/ComTaskServiceImpl.java

@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2016, FPX and/or its affiliates. All rights reserved.
+ * Use, Copy is subject to authorized license.
+*/
+package com.qmth.cqb.flow.serviceImpl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Resource;
+
+import org.activiti.engine.RepositoryService;
+import org.activiti.engine.RuntimeService;
+import org.activiti.engine.TaskService;
+import org.activiti.engine.impl.RepositoryServiceImpl;
+import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
+import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
+import org.activiti.engine.impl.pvm.PvmActivity;
+import org.activiti.engine.impl.pvm.PvmTransition;
+import org.activiti.engine.impl.pvm.process.ActivityImpl;
+import org.activiti.engine.impl.task.TaskDefinition;
+import org.activiti.engine.repository.ProcessDefinition;
+import org.activiti.engine.repository.ProcessDefinitionQuery;
+import org.activiti.engine.runtime.Execution;
+import org.activiti.engine.task.DelegationState;
+import org.activiti.engine.task.Task;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import com.qmth.cqb.flow.model.TaskModel;
+import com.qmth.cqb.flow.model.WorkFlowModel;
+import com.qmth.cqb.flow.service.ComTaskService;
+
+
+
+/**
+ * @Title: 任务处理service
+ * @Description:TODO
+ * @Company:4px
+ * @author chenken
+ * @date 2016年6月24日
+ * @since v1.0.0
+ */
+@Service("comTaskService")
+public class ComTaskServiceImpl implements ComTaskService{
+	
+	@Resource
+	private TaskService taskService;
+	@Resource
+	private RepositoryService repositoryService;
+	@Resource
+	private RuntimeService runtimeService;
+	
+	@Override
+	public List<TaskModel> findPersonalTaskList(String assignee,String category) throws Exception {
+		Assert.hasText(assignee, "任务办理人assignee不能为空");
+		List<TaskModel> taskModelList = new ArrayList<TaskModel>();
+		List<Task> taskList = taskService.createTaskQuery().taskAssignee(assignee).list();
+		if(taskList.size()>0){
+			for(Task task:taskList){
+				String processDefinitionId = task.getProcessDefinitionId();
+				ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId);
+				if(StringUtils.isNotBlank(category)){
+					processDefinitionQuery = processDefinitionQuery.processDefinitionCategory(category);
+				}
+				ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
+				if(processDefinition!=null){
+					taskModelList.add(new TaskModel(task,processDefinition));
+				}
+			}
+		}
+		return taskModelList;
+	}
+
+	@Override
+	public List<TaskModel> findClaimTask(String roleId,String category){
+		Assert.hasText(roleId, "任务办理角色roleId不能为空");
+		List<TaskModel> taskModelList = new ArrayList<TaskModel>();
+		List<Task> taskList = taskService.createTaskQuery().taskCandidateGroup(roleId).active().list();
+		if(taskList.size()>0){
+			for(Task task:taskList){
+				String processDefinitionId = task.getProcessDefinitionId();
+				ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId);
+				if(StringUtils.isNotBlank(category)){
+					processDefinitionQuery = processDefinitionQuery.processDefinitionCategory(category);
+				}
+				ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
+				if(processDefinition!=null){
+					TaskModel taskModel = new TaskModel(task,processDefinition);
+					taskModel.setTaskRole(roleId);
+					taskModelList.add(taskModel);
+				}
+			}
+		}
+		return  taskModelList;
+	}
+	
+	/**
+	 * 完成任务
+	 */
+	@Override
+	public void completeTask(WorkFlowModel workFlowModel) throws Exception {
+		/**
+		 * 验证
+		 */
+		Assert.hasText(workFlowModel.getTaskId(), "任务ID不能为空");
+		Assert.hasText(workFlowModel.getAssignee(), "当前操作人不能为空");
+		
+		String taskId = workFlowModel.getTaskId();
+		
+		Map<String, Object> variables = workFlowModel.getVariables();
+		//当前节点操作人
+		variables.put("assignee", workFlowModel.getAssignee());
+		//如果有分支,设置分支条件
+		variables.put("condition", workFlowModel.getCondition());
+		//下一节点操作人如果为null,任务会分派给角色领取
+		if(StringUtils.isBlank(workFlowModel.getNextOperator())){
+			variables.put("operator",null);
+		}else{
+			variables.put("operator",workFlowModel.getNextOperator());
+		}
+		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
+		//如果任务处于委派状态,须调用特定的委派回归处理方法
+		if(task.getDelegationState() == DelegationState.PENDING){
+			taskService.resolveTask(taskId, variables);
+		}else{
+			taskService.complete(taskId, variables);
+		}
+	}
+	/**
+	 * 领取任务
+	 */
+	@Override
+	public void claimTask(String taskId,String assignee) {
+		Assert.hasText(taskId, "任务ID不能为空");
+		Assert.hasText(assignee, "任务领取人不能为空");
+		taskService.claim(taskId, assignee);
+	}
+	
+	@Override
+	public void completeTaskByProcInstId(String procInstId,Map<String, Object> variables) throws Exception{
+		String assignee = variables.get("assignee")+"";
+		if(StringUtils.isNotBlank(assignee)){
+			Task task = taskService.createTaskQuery()
+					 	.processInstanceId(procInstId)
+					 	.taskAssignee(assignee)
+					 	.active()
+					 	.singleResult();
+			if (task!=null) {
+				taskService.complete(task.getId(), variables);
+			}
+		}
+	}
+
+	/**
+	 * 委派任务
+	 */
+	@Override
+	public void delegateTask(String taskId, String delegateUserId) {
+		Assert.hasText(taskId, "任务ID不能为空");
+		Assert.hasText(delegateUserId, "被委派人不能为空");
+		
+		taskService.delegateTask(taskId, delegateUserId);
+	}
+
+	@Override
+	public List<TaskModel> findAssigneedOrClaimTask(String assignee,String groupId, String category) throws Exception {
+		List<TaskModel> taskModelList = new ArrayList<TaskModel>();
+		taskModelList.addAll(findPersonalTaskList(assignee, category));
+		taskModelList.addAll(findClaimTask(groupId, category));
+		return taskModelList;
+	}
+
+	@Override
+	public TaskDefinition nextTaskDefinition(String processInstanceId,String activitiId,String elString) {
+         String id = null;  
+         TaskDefinition task = null;  
+         ProcessDefinitionEntity processDefinitionEntity = null;
+	     String processDefinitionId = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult().getProcessDefinitionId();  
+	     processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processDefinitionId);  
+	     //获取当前流程所有节点信息   
+	     List<ActivityImpl> activitiList = processDefinitionEntity.getActivities();  
+	     //遍历所有节点信息   
+         for(ActivityImpl activityImpl : activitiList){      
+            id = activityImpl.getId();     
+            // 找到当前节点信息  
+            if (activitiId.equals(id)) {  
+                //获取下一个节点信息   
+            	task =  nextTaskDefinition(activityImpl,activitiId,elString,processInstanceId);  
+            	break;
+            }  
+         }  
+	     return task;
+	}
+	  /**  
+     * 下一个任务节点信息,  
+     *  
+     * 如果下一个节点为用户任务则直接返回,  
+     *  
+     * 如果下一个节点为排他网关, 获取排他网关Id信息, 根据排他网关Id信息和execution获取流程实例排他网关Id为key的变量值,  
+     * 根据变量值分别执行排他网关后线路中的el表达式, 并找到el表达式通过的线路后的用户任务信息  
+     * @param ActivityImpl activityImpl     流程节点信息  
+     * @param String activityId             当前流程节点Id信息  
+     * @param String elString               排他网关顺序流线段判断条件, 例如排他网关顺序留线段判断条件为${money>1000}, 若满足流程启动时设置variables中的money>1000, 则流程流向该顺序流信息  
+     * @param String processInstanceId      流程实例Id信息  
+     * @return  
+     */    
+    private TaskDefinition nextTaskDefinition(ActivityImpl activityImpl, String activityId, String elString, String processInstanceId){   
+        PvmActivity ac = null;  
+        Object s = null;  
+        //如果遍历节点为用户任务并且节点不是当前节点信息   
+        if("userTask".equals(activityImpl.getProperty("type")) && !activityId.equals(activityImpl.getId())){    
+            //获取该节点下一个节点信息   
+            TaskDefinition taskDefinition = ((UserTaskActivityBehavior)activityImpl.getActivityBehavior()).getTaskDefinition();    
+            return taskDefinition;    
+        }else{    
+            //获取节点所有流向线路信息   
+            List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();    
+            List<PvmTransition> outTransitionsTemp = null;    
+            for(PvmTransition tr : outTransitions){      
+                ac = tr.getDestination(); //获取线路的终点节点      
+                //如果流向线路为排他网关   
+                if("exclusiveGateway".equals(ac.getProperty("type"))){    
+                    outTransitionsTemp = ac.getOutgoingTransitions();  
+                    //如果网关路线判断条件为空信息   
+                    if(StringUtils.isEmpty(elString)) {  
+                        //获取流程启动时设置的网关判断条件信息   
+                       elString = getGatewayCondition(ac.getId(), processInstanceId);  
+                    }  
+                    //如果排他网关只有一条线路信息   
+                    if(outTransitionsTemp.size() == 1){    
+                        return nextTaskDefinition((ActivityImpl)outTransitionsTemp.get(0).getDestination(), activityId, elString, processInstanceId);    
+                    }else if(outTransitionsTemp.size() > 1){  //如果排他网关有多条线路信息   
+                        for(PvmTransition tr1 : outTransitionsTemp){    
+                            s = tr1.getProperty("conditionText");  //获取排他网关线路判断条件信息   
+                            //判断el表达式是否成立   
+                            if(elString.equals(s)){    
+                                return nextTaskDefinition((ActivityImpl)tr1.getDestination(), activityId, elString, processInstanceId);    
+                            }    
+                        }    
+                    }    
+                }else if("userTask".equals(ac.getProperty("type"))){    
+                    return ((UserTaskActivityBehavior)((ActivityImpl)ac).getActivityBehavior()).getTaskDefinition();    
+                }else{    
+                }    
+           }     
+           return null;    
+        }    
+    }
+    /** 
+     * 查询流程启动时设置排他网关判断条件信息  
+     * @param String gatewayId          排他网关Id信息, 流程启动时设置网关路线判断条件key为网关Id信息  
+     * @param String processInstanceId  流程实例Id信息  
+     * @return 
+     */  
+    private String getGatewayCondition(String gatewayId, String processInstanceId) {  
+        Execution execution = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).singleResult();  
+        return runtimeService.getVariable(execution.getId(), gatewayId)+"";  
+    }  
+}

+ 37 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/serviceImpl/CompleteUserTaskServiceImpl.java

@@ -0,0 +1,37 @@
+package com.qmth.cqb.flow.serviceImpl;
+
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Resource;
+
+import org.springframework.stereotype.Service;
+
+import com.qmth.cqb.flow.model.WorkFlowModel;
+import com.qmth.cqb.flow.service.ComTaskService;
+import com.qmth.cqb.flow.service.CompleteUserTaskService;
+
+
+
+@Service("completeUserTaskService")
+public class CompleteUserTaskServiceImpl implements CompleteUserTaskService{
+	
+	@Resource
+	private ComTaskService comTaskService;
+	@Override
+	public void completeUserTask(WorkFlowModel workFlowModel) throws Exception {
+		//1.处理业务
+		//doSomething()
+		//设置下一步系统任务调用的http地址
+		Map<String,Object> variables = new HashMap<String, Object>();
+		//variables.put("nextHttpUrl", "http://127.0.0.1:8080/testServiceTaskController/testServiceTaskMethod?param=1");
+		variables.put("condition", workFlowModel.getCondition());
+		variables.put("assignee", workFlowModel.getAssignee());
+		workFlowModel.setVariables(variables);
+		//2.调用工作流接口,完成任务
+		comTaskService.completeTask(workFlowModel);
+	}
+	
+}

+ 63 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/util/FileUtil.java

@@ -0,0 +1,63 @@
+package com.qmth.cqb.flow.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+
+public class FileUtil {
+	/**
+	 * 
+	 * 单个文件上传到本地
+	 * @param is
+	 * @param fileName	文件名称
+	 * @param folderLocalPath	本地文件夹路径
+	 */
+	public static File upFile(InputStream is, String fileName, String folderLocalPath) {
+		FileOutputStream fos = null;
+		BufferedOutputStream bos = null;
+		BufferedInputStream bis = null;
+		File folder = new File(folderLocalPath);
+		//如果文件夹不存在,就创建
+		if (!folder.exists()) {
+			folder.mkdirs();
+		}
+		File file = new File(folderLocalPath + "/" + fileName);
+		try {
+			bis = new BufferedInputStream(is);
+			fos = new FileOutputStream(file);
+			bos = new BufferedOutputStream(fos);
+			byte[] buffer = new byte[4096];
+			int len = 0;
+			while ((len = bis.read(buffer)) > 0) {
+				bos.write(buffer, 0, len);
+			}
+			bos.flush();
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			try {
+				if (null != bos) {
+					bos.close();
+					bos = null;
+				}
+				if (null != fos) {
+					fos.close();
+					fos = null;
+				}
+				if (null != is) {
+					is.close();
+					is = null;
+				}
+				if (null != bis) {
+					bis.close();
+					bis = null;
+				}
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+		return file;
+	}
+}

+ 86 - 0
cqb-flow-core/src/main/java/com/qmth/cqb/flow/util/HttpConnectUtil.java

@@ -0,0 +1,86 @@
+package com.qmth.cqb.flow.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+
+public class HttpConnectUtil {
+	
+	private static String DUOSHUO_SHORTNAME = "yoodb";//多说短域名 ****.yoodb.****
+	private static String DUOSHUO_SECRET = "xxxxxxxxxxxxxxxxx";//多说秘钥
+	
+	/**
+	 * get方式
+	 * @param url
+	 * @author www.yoodb.com
+	 * @return
+	 */
+	public static String getHttp(String url) {
+		String responseMsg = "";
+		HttpClient httpClient = new HttpClient();
+		GetMethod getMethod = new GetMethod(url);
+		getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler());
+		try {
+			httpClient.executeMethod(getMethod);
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+			InputStream in = getMethod.getResponseBodyAsStream();
+			int len = 0;
+			byte[] buf = new byte[1024];
+			while((len=in.read(buf))!=-1){
+				out.write(buf, 0, len);
+			}
+			responseMsg = out.toString("UTF-8");
+		} catch (HttpException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} finally {
+			//释放连接
+			getMethod.releaseConnection();
+		}
+		return responseMsg;
+	}
+
+	/**
+	 * post方式
+	 * @param url
+	 * @param code
+	 * @param type
+	 * @author www.yoodb.com
+	 * @return
+	 */
+	public static String postHttp(String url,String code,String type) {
+		String responseMsg = "";
+		HttpClient httpClient = new HttpClient();
+		httpClient.getParams().setContentCharset("GBK");
+		PostMethod postMethod = new PostMethod(url);
+		postMethod.addParameter(type, code);
+		postMethod.addParameter("client_id", DUOSHUO_SHORTNAME);
+		postMethod.addParameter("client_secret", DUOSHUO_SECRET);
+		try {
+			httpClient.executeMethod(postMethod);
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+			InputStream in = postMethod.getResponseBodyAsStream();
+			int len = 0;
+			byte[] buf = new byte[1024];
+			while((len=in.read(buf))!=-1){
+				out.write(buf, 0, len);
+			}
+			responseMsg = out.toString("UTF-8");
+		} catch (HttpException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} finally {
+			postMethod.releaseConnection();
+		}
+		return responseMsg;
+	}
+}

+ 121 - 122
cqb-starter/pom.xml

@@ -1,122 +1,121 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>comm-ques-bank</artifactId>
-        <groupId>com.qmth.cqb</groupId>
-        <version>0.1.0</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>cqb-starter</artifactId>
-    <packaging>jar</packaging>
-
-    <name>cqb-starter</name>
-
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.qmth.cqb</groupId>
-            <artifactId>cqb-base</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.qmth.cqb</groupId>
-            <artifactId>cqb-comm-utils</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.qmth.cqb</groupId>
-            <artifactId>cqb-flow-core</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.qmth.cqb</groupId>
-            <artifactId>cqb-flow-college</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.qmth.cqb</groupId>
-            <artifactId>cqb-flow-zk</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.qmth.cqb</groupId>
-            <artifactId>cqb-question-resource</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.qmth.cqb</groupId>
-            <artifactId>cqb-gen-paper</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.qmth.cqb</groupId>
-            <artifactId>cqb-paper</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.boot</groupId>
-                    <artifactId>spring-boot-starter-logging</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-log4j2</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-devtools</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-feign</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-eureka</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>cn.com.qmth.examcloud.common</groupId>
-            <artifactId>common-uac</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-
-    </dependencies>
-
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <version>${spring.boot.version}</version>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <configuration>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>comm-ques-bank</artifactId>
+        <groupId>com.qmth.cqb</groupId>
+        <version>0.1.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>cqb-starter</artifactId>
+    <packaging>jar</packaging>
+
+    <name>cqb-starter</name>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.qmth.cqb</groupId>
+            <artifactId>cqb-base</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.cqb</groupId>
+            <artifactId>cqb-comm-utils</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.cqb</groupId>
+            <artifactId>cqb-flow-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.cqb</groupId>
+            <artifactId>cqb-flow-college</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.cqb</groupId>
+            <artifactId>cqb-flow-zk</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.cqb</groupId>
+            <artifactId>cqb-question-resource</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.cqb</groupId>
+            <artifactId>cqb-gen-paper</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qmth.cqb</groupId>
+            <artifactId>cqb-paper</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-logging</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-log4j2</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-feign</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-eureka</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.com.qmth.examcloud.common</groupId>
+            <artifactId>common-uac</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+    </dependencies>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 10 - 3
cqb-starter/src/main/resources/application-dev.properties

@@ -1,3 +1,10 @@
-spring.data.mongodb.uri=mongodb://192.168.1.99:27017/comm-ques-bank
-spring.data.mongodb.grid-fs-database=comm-ques-bank
-eureka.client.serviceUrl.defaultZone=http://192.168.1.161:1111/eureka/
+spring.data.mongodb.uri=mongodb://192.168.1.99:27017/comm-ques-bank
+spring.data.mongodb.grid-fs-database=comm-ques-bank
+eureka.client.serviceUrl.defaultZone=http://192.168.1.161:1111/eureka/
+
+spring.jpa.hibernate.ddl-auto=update
+spring.jpa.database=MYSQL
+spring.datasource.url=jdbc:mysql://192.168.1.99:3306/workflow?characterEncoding=UTF-8
+spring.datasource.username=root
+spring.datasource.password=root
+spring.datasource.driver-class-name=com.mysql.jdbc.Driver

+ 84 - 0
cqb-starter/src/main/resources/diagrams/B-register-v1.0.bpmn

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 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="MerchantRegistedFlow" name="B类客户注册流程v1.0" isExecutable="true">
+    <startEvent id="startmerchant" name="Start" activiti:initiator="initiator"></startEvent>
+    <userTask id="createMerchant" name="创建B端客户" activiti:assignee="${operator}"></userTask>
+    <sequenceFlow id="flow1" sourceRef="startmerchant" targetRef="createMerchant"></sequenceFlow>
+    <userTask id="approveMerchant" name="审核B端客户" activiti:candidateGroups="aduiter"></userTask>
+    <exclusiveGateway id="exclusiveapprove" name="Exclusive Gateway"></exclusiveGateway>
+    <serviceTask id="saveMerchant" name="保存B端客户数据到数据库" activiti:class="com.fpx.workflow.merchantregister.workflowservice.SaveMerchantServiceImpl"></serviceTask>
+    <endEvent id="endmerchant" name="End"></endEvent>
+    <sequenceFlow id="flow6" name="通过" sourceRef="exclusiveapprove" targetRef="saveMerchant">
+      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${approval == "backward-completed"}]]></conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="flow7" sourceRef="createMerchant" targetRef="approveMerchant"></sequenceFlow>
+    <sequenceFlow id="flow8" sourceRef="approveMerchant" targetRef="exclusiveapprove"></sequenceFlow>
+    <sequenceFlow id="flow9" sourceRef="saveMerchant" targetRef="endmerchant"></sequenceFlow>
+    <serviceTask id="changeStatus" name="修改状态" activiti:class="com.fpx.workflow.merchantregister.workflowservice.ChangeStatusServiceImpl"></serviceTask>
+    <sequenceFlow id="flow10" name="不通过" sourceRef="exclusiveapprove" targetRef="changeStatus">
+      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${approval == "backward-back"}]]></conditionExpression>
+    </sequenceFlow>
+    <sequenceFlow id="flow11" sourceRef="changeStatus" targetRef="createMerchant"></sequenceFlow>
+  </process>
+  <bpmndi:BPMNDiagram id="BPMNDiagram_MerchantRegistedFlow">
+    <bpmndi:BPMNPlane bpmnElement="MerchantRegistedFlow" id="BPMNPlane_MerchantRegistedFlow">
+      <bpmndi:BPMNShape bpmnElement="startmerchant" id="BPMNShape_startmerchant">
+        <omgdc:Bounds height="35.0" width="35.0" x="390.0" y="10.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="createMerchant" id="BPMNShape_createMerchant">
+        <omgdc:Bounds height="55.0" width="105.0" x="355.0" y="130.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="approveMerchant" id="BPMNShape_approveMerchant">
+        <omgdc:Bounds height="55.0" width="105.0" x="355.0" y="250.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="exclusiveapprove" id="BPMNShape_exclusiveapprove">
+        <omgdc:Bounds height="40.0" width="40.0" x="387.0" y="370.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="saveMerchant" id="BPMNShape_saveMerchant">
+        <omgdc:Bounds height="71.0" width="105.0" x="355.0" y="460.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="endmerchant" id="BPMNShape_endmerchant">
+        <omgdc:Bounds height="35.0" width="35.0" x="390.0" y="580.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape bpmnElement="changeStatus" id="BPMNShape_changeStatus">
+        <omgdc:Bounds height="55.0" width="105.0" x="540.0" y="250.0"></omgdc:Bounds>
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
+        <omgdi:waypoint x="407.0" y="45.0"></omgdi:waypoint>
+        <omgdi:waypoint x="407.0" y="130.0"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow6" id="BPMNEdge_flow6">
+        <omgdi:waypoint x="407.0" y="410.0"></omgdi:waypoint>
+        <omgdi:waypoint x="407.0" y="460.0"></omgdi:waypoint>
+        <bpmndi:BPMNLabel>
+          <omgdc:Bounds height="14.0" width="24.0" x="420.0" y="419.0"></omgdc:Bounds>
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow7" id="BPMNEdge_flow7">
+        <omgdi:waypoint x="407.0" y="185.0"></omgdi:waypoint>
+        <omgdi:waypoint x="407.0" y="250.0"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow8" id="BPMNEdge_flow8">
+        <omgdi:waypoint x="407.0" y="305.0"></omgdi:waypoint>
+        <omgdi:waypoint x="407.0" y="370.0"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow9" id="BPMNEdge_flow9">
+        <omgdi:waypoint x="407.0" y="531.0"></omgdi:waypoint>
+        <omgdi:waypoint x="407.0" y="580.0"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow10" id="BPMNEdge_flow10">
+        <omgdi:waypoint x="427.0" y="390.0"></omgdi:waypoint>
+        <omgdi:waypoint x="592.0" y="389.0"></omgdi:waypoint>
+        <omgdi:waypoint x="592.0" y="305.0"></omgdi:waypoint>
+        <bpmndi:BPMNLabel>
+          <omgdc:Bounds height="14.0" width="36.0" x="479.0" y="398.0"></omgdc:Bounds>
+        </bpmndi:BPMNLabel>
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge bpmnElement="flow11" id="BPMNEdge_flow11">
+        <omgdi:waypoint x="592.0" y="250.0"></omgdi:waypoint>
+        <omgdi:waypoint x="592.0" y="158.0"></omgdi:waypoint>
+        <omgdi:waypoint x="460.0" y="157.0"></omgdi:waypoint>
+      </bpmndi:BPMNEdge>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</definitions>

+ 231 - 0
cqb-starter/src/test/java/com/qmth/cqb/FlowTest.java

@@ -0,0 +1,231 @@
+package com.qmth.cqb;
+
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.activiti.engine.HistoryService;
+import org.activiti.engine.IdentityService;
+import org.activiti.engine.RepositoryService;
+import org.activiti.engine.RuntimeService;
+import org.activiti.engine.TaskService;
+import org.activiti.engine.history.HistoricActivityInstance;
+import org.activiti.engine.history.HistoricVariableInstance;
+import org.activiti.engine.identity.Group;
+import org.activiti.engine.identity.User;
+import org.activiti.engine.repository.ProcessDefinition;
+import org.activiti.engine.task.Task;
+import org.activiti.engine.test.Deployment;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.qmth.cqb.flow.model.WorkFlowModel;
+import com.qmth.cqb.flow.service.ComProcessService;
+import com.qmth.cqb.flow.service.ComTaskService;
+
+
+
+
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class FlowTest{
+	
+	@Resource
+	public ComProcessService comProcessService;
+	@Resource
+	private TaskService taskService;
+	@Resource
+	private HistoryService historyService;
+	@Resource
+	private IdentityService identityService;
+	@Resource
+	private ComTaskService comTaskService;
+	@Resource
+	private RuntimeService runtimeService;
+	@Resource
+    protected RepositoryService repositoryService;
+	
+	@Test
+	@Deployment
+	public void testDeploy() throws Exception{
+		 //流程文件名不能使用中文
+		 comProcessService.deployProcess("B-register-v1.0.bpmn", "D:/workflow_diagrams");
+	}
+	 @Test 
+	public void testQueryAllTask(){
+		List<Task> taskList = taskService.createTaskQuery().list();
+		for(Task task:taskList){
+			String processDefinitionId = task.getProcessDefinitionId();
+			ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
+			Assert.assertNotNull(processDefinition);
+		}
+		System.out.println(taskList);
+	}
+	
+    /**查询我的个人任务,没有执行结果*/  
+    @Test  
+    public void findPersonalTaskList() {  
+        // 任务办理人  
+        String assignee = "chenken";  
+        List<Task> list = taskService//  
+                .createTaskQuery()//  
+                .taskAssignee(assignee)// 个人任务的查询  
+                .list();  
+        if (list != null && list.size() > 0) {  
+            for (Task task : list) {  
+                System.out.println("任务ID:" + task.getId());  
+                System.out.println("任务的办理人:" + task.getAssignee());  
+                System.out.println("任务名称:" + task.getName());  
+                System.out.println("任务的创建时间:" + task.getCreateTime());  
+                System.out.println("流程实例ID:" + task.getProcessInstanceId());  
+                System.out.println("#######################################");  
+            }  
+        }  
+    }  
+    /**查询组任务*/
+	@Test
+	public void findGroupTaskList(){
+		 // 任务办理人  
+        String candidateUser = "admin";  
+		List<Task> list = taskService  
+                .createTaskQuery() 
+                .taskCandidateUser(candidateUser)// 参与者,组任务查询  
+                .list(); 
+		if (list != null && list.size() > 0) {  
+            for (Task task : list) {  
+                System.out.println("任务ID:" + task.getId());  
+                System.out.println("任务的办理人:" + task.getAssignee());  
+                System.out.println("任务名称:" + task.getName());  
+                System.out.println("任务的创建时间:" + task.getCreateTime());  
+                System.out.println("流程实例ID:" + task.getProcessInstanceId());  
+                System.out.println("#######################################");  
+            }  
+        }
+	}
+	
+	 /**完成任务*/  
+    @Test  
+    public void completeTask() {  
+        // 任务ID  
+        String taskId = "742506";  
+        taskService.complete(taskId);  
+        System.out.println("完成任务:" + taskId);  
+    } 
+    /**
+     * 查询流程变量
+     */
+    @Test 
+    public void getRuTaskVariable(){
+    	System.out.println(taskService.getVariable("87511", "businessStr"));
+    }
+    
+    @Test 
+    public void getHistoryActivity(){
+    	String processInstanceId = "100001";
+    	List<HistoricActivityInstance> historicActivityInstances = 
+    	historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
+    	List<HistoricVariableInstance> historicVariableInstances =
+    			historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();
+    }
+    /**
+     * 用户与组之间的关系
+     */
+    @Test
+    public void testUserAndGroupMemership(){
+    	/*创建组
+    	Group group = identityService.newGroup("aduiter");
+    	group.setName("B端客户审核员");
+    	identityService.saveGroup(group);*/
+    	//创建用户
+    	User user = identityService.newUser("ck");
+    	user.setFirstName("chen");
+    	user.setLastName("ken");
+    	user.setEmail("1234567@qq.com");
+    	identityService.saveUser(user);
+    	//把用户ck加入到组aduiter中
+    	Group group = identityService.createGroupQuery().groupId("aduiter").singleResult();
+    	identityService.createMembership(user.getId(), group.getId());
+    	//查询组aduiter 下的用户
+    	List<User> users = identityService.createUserQuery().memberOfGroup(group.getId()).list();
+    	Assert.assertEquals("ck",users.get(0).getId());
+    	//查询ck所在的组
+    	Group groupContainsCk = identityService.createGroupQuery().groupMember(user.getId()).singleResult();
+    	Assert.assertNotNull(groupContainsCk);
+    	Assert.assertEquals("aduiter", groupContainsCk.getId());
+    }
+    @Test
+    public void testGroup(){
+    	List<Group> groupList = identityService.createGroupQuery().groupId("aduiter").list();
+    	Assert.assertEquals(1,groupList.size());
+    }
+    @Test
+    public void deleteMembership(){
+    	identityService.deleteMembership("ck", "aduiter");
+    	identityService.deleteGroup("aduiter");
+    	identityService.deleteUser("ck");
+    }
+    
+    @Test
+    public void getTaskByGroupId(){
+    	//根据角色ID查询用户任务
+    	List<Task> taskList = taskService.createTaskQuery().taskCandidateGroup("aduiter").active().list();
+    	//lihao领取任务
+    	for(Task task:taskList){
+    		taskService.claim(task.getId(), "lihao");
+    	}
+    	/*
+    	Task task = taskService.createTaskQuery().taskAssignee("lihao").active().singleResult();
+    	
+    	System.out.println(task);
+    	Map<String,Object> valiables = new HashMap<String,Object>();
+    	valiables.put("approval", "backward-completed");
+    	taskService.complete(task.getId(),valiables);
+    	task = taskService.createTaskQuery().taskAssignee("lihao").active().singleResult();
+    	
+    	System.out.println(task);*/
+    }
+    
+    @Test
+    public void testStartTask() throws Exception{
+    	WorkFlowModel workFlowModel = new WorkFlowModel();
+    	workFlowModel.setStarter("liuyun");
+    	workFlowModel.setNextOperator("chenken");
+    	String  processInstanceId = comProcessService.tranStartProcess("",workFlowModel);
+    	System.out.println(processInstanceId);
+    }
+    
+    @Test
+    public void testCompleteTask() throws Exception{
+    	/*//String category = EnumSystem.CRM.getName();
+    	String roleId = "group1";
+    	String assignee = "chenken";
+    	//找到可领取的任务
+    	List<TaskModel> claimTasks = comTaskService.findClaimTask(roleId,"ABCD");
+    	for(TaskModel task:claimTasks){
+    		//领取任务
+    		comTaskService.claimTask(task.getTaskId(),assignee);
+    	}
+    	//找到可完成的任务
+    	List<TaskModel> tasks = comTaskService.findPersonalTaskList(assignee,category);
+    	*//**
+    	 * 委派
+    	 * comTaskService.delegateTask(tasks.get(0).getId(), "xxyy");
+    	 *//*
+    	for(TaskModel task:tasks){
+    		//完成任务
+    		WorkFlowModel workFlowModel = new WorkFlowModel();
+        	workFlowModel.setNodeServiceName("completeUserTaskService");
+        	workFlowModel.setTaskId(task.getTaskId());
+        	workFlowModel.setAssignee(assignee);
+        	workFlowModel.setCondition("1");
+        	workFlowModel.setNextOperator("liuyun");
+        	CompleteUserTaskService workFlowService = WorkflowUtils.getCurrentTaskService(workFlowModel.getNodeServiceName());
+        	workFlowService.completeUserTask(workFlowModel);
+    	}*/
+    }
+    
+}