Java进阶学习第三十五天(Activiti工作流)

一、工作流概念

1、生活中的工作流:请假流程

2、理解工作流概念
① 定义工作流 : 包括定义具体的活动、规则等
② 执行工作流 : 按照流程定义的规则去执行,并且由多个参与者进行控制

二、Activiti工作流

1、Activiti工作流介绍
① 常见开源工作流引擎框架:OSWorkFlow、JBPM(java business process management)、Activiti工作流(是对JBPM升级)
② 工作流引擎:ProcessEngine ,它是Activiti的核心类,由该类可以获取其他的服务实例(历史服务、仓库服务、任务服务、用户参与者服务)
③ BPMN
业务流程建模与标注(Business Process Model and Notation,BPMN) 描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)
④ 数据库
Activiti的工作流数据库有23张表,Activiti的后台是有数据库的支持,所有的表都以ACT_开头。第二部分是表示表的用途的两个字母标识,用途也和服务的API对应

act_ge_*:通用表
act_hi_*:历史流程相关表 
act_re_*:仓库表:保存流程定义
act_ru_*:保存流程运行相关的表  
act_id_*:用户参与相关的表  

⑤ activiti.cfg.xml
Activiti核心配置文件,配置流程引擎创建工具的基本参数和数据库连接参数
⑥ logging.properties

2、搭建Activiti开发环境
① Acitiviti软件环境
◇ JDK 1.6版本及以上
◇ 数据库支持的有:h2、mysql、oracle、mssql、db2等 ,这里选择mysql
◇ 支持Activiti 5 运行的jar包,在activiti-5.13\wars\activiti-rest \WEB-INF\lib添加,可以在官网下载www.activiti.org
◇ 集成开发环境:Myeclipse 8.6及以上,最好myeclipse 2014
② 安装流程设计器BPMN
◇ 有网络安装
◇ 无网情况:直接添加插件 ,把压缩包中的内容放入eclipse根目录的dropins文件夹下
◇ 注意:打开菜单Windows > Preferences > Activit > Save actions(*.bpmn*.png同步保存)

3、Activiti 架构及核心API

activiti.cfg.xml
ProcessEngineConfigration
ProcessEngine
RepositoryService:流程定义 ,存放资源
TaskService :任务服务
IdentityService :用户与组服务
FormService  :表单服务
RuntimeService :运行时服务
ManagementService :管理服务
HistoryService :历史服务

Activiti-Api关系

三、模拟Activiti流程引擎框架执行

1、设置流程定义图bpmn
assignee:指定谁来处理这个任务

2、创建流程引擎及工作流数据表
① 数据库及表可以自动创建,可以在配置数据库连接时,实现自动创建数据库和表
② 取得ProcessEngine对象(先取得ProcessEngineConfiguration 对象,再由该对象来构建ProcessEngine)

/*
 * 模拟Activiti 工作流框架执行
 */
public class TestActiviti {
	private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
	//取得流程引擎,且自动创建Activiti涉及的数据库和表
	@Test
	public void createProcessEngine(){
		/**   第一种方式:通过代码形式创建ProcessEngine
		 *  - 取得ProcessEngineConfiguration对象
		 *  - 设置数据库连接属性
		 *  - 设置创建表的策略 (当没有表时,自动创建表)
		 *  - 通过ProcessEngineConfiguration对象创建 ProcessEngine 对象
		//取得ProcessEngineConfiguration对象
		ProcessEngineConfiguration engineConfiguration=ProcessEngineConfiguration.
				createStandaloneProcessEngineConfiguration();
		//设置数据库连接属性
		engineConfiguration.setJdbcDriver("com.mysql.jdbc.Driver");
		engineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activitiDB?createDatabaseIfNotExist=true"
				+ "&useUnicode=true&characterEncoding=utf8");
		engineConfiguration.setJdbcUsername("root");
		engineConfiguration.setJdbcPassword("1234");
		// 设置创建表的策略 (当没有表时,自动创建表)
//		  public static final java.lang.String DB_SCHEMA_UPDATE_FALSE = "false";//不会自动创建表,没有表,则抛异常
//		  public static final java.lang.String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";//先删除,再创建表
//		  public static final java.lang.String DB_SCHEMA_UPDATE_TRUE = "true";//假如没有表,则自动创建
		engineConfiguration.setDatabaseSchemaUpdate("true");
		//通过ProcessEngineConfiguration对象创建 ProcessEngine 对象
		ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
		System.out.println("流程引擎创建成功!");
		*/
		
		/**   第二种方式:通过加载 activiti.cfg.xml 获取流程引擎和自动创建数据库及表
		 * 
		ProcessEngineConfiguration engineConfiguration=
				ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
		//从类加载路径中查找资源  activiti.cfg.xm文件名可以自定义
		ProcessEngine processEngine = engineConfiguration.buildProcessEngine();
		System.out.println("使用配置文件Activiti.cfg.xml获取流程引擎");
		*/
		
		/**   第三种方式:通过ProcessEngines来获取默认的流程引擎
		 * 
		 */
		//默认会加载类路径下的 activiti.cfg.xml 
//		ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
//		System.out.println("通过ProcessEngines来获取流程引擎");
	}
	
	//部署流程定义
	@Test
	public void deploy(){
		//取得流程引擎对象
//		ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
		//获取仓库服务 :管理流程定义
		RepositoryService repositoryService = processEngine.getRepositoryService();
		Deployment deploy = repositoryService.createDeployment()//创建一个部署的构建器
		.addClasspathResource("diagrams/LeaveBill.bpmn")//从类路径中添加资源,一次只能添加一个资源
		.addClasspathResource("diagrams/LeaveBill.png")//从类路径中添加资源,一次只能添加一个资源
		.name("请求单流程")//设置部署的名称
		.category("办公类别")//设置部署的类别
		.deploy();
		System.out.println("部署的id"+deploy.getId());
		System.out.println("部署的名称"+deploy.getName());
	}
	
	//执行流程
	@Test
	public void startProcess(){
		String processDefiKey="leaveBill";
		//取运行时服务
		RuntimeService runtimeService = processEngine.getRuntimeService();
		//取得流程实例
		ProcessInstance pi = runtimeService.startProcessInstanceByKey(processDefiKey);//通过流程定义的key来执行流程
		System.out.println("流程实例id:"+pi.getId());//流程实例id
		System.out.println("流程定义id:"+pi.getProcessDefinitionId());//输出流程定义的id
	}
	
	//查询任务 
	@Test
	public void queryTask(){
		//任务的办理人
		String assignee="王五";
		//取得任务服务
		TaskService taskService = processEngine.getTaskService();
		//创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		//办理人的任务列表
		List<Task> list = taskQuery.taskAssignee(assignee)//指定办理人
		.list();
		//遍历任务列表
		if(list!=null&&list.size()>0){
			for(Task task:list){
				System.out.println("任务的办理人:"+task.getAssignee());
				System.out.println("任务的id:"+task.getId());
				System.out.println("任务的名称:"+task.getName());
				
			}
		}
	}
	
	//完成任务
	@Test
	public void compileTask(){
		String taskId="402";
		//taskId:任务id
		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}
}

activiti.cfg.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

 <!-- 配置 ProcessEngineConfiguration  -->
 <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
  <!-- 配置数据库连接 -->
  <property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>
  <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activitiDB?createDatabaseIfNotExist=true&amp;useUnicode=true&amp;characterEncoding=utf8"></property>
  <property name="jdbcUsername" value="root"></property>
  <property name="jdbcPassword" value="1234"></property>
  <!-- 配置创建表策略 :没有表时,自动创建 -->
  <property name="databaseSchemaUpdate" value="true"></property>
 </bean>
</beans>

3、部署流程
影响的表:
act_re_procdef (流程定义表):该表的key属性是由bpmn的id决定, 该表的name属性是由bpmn的name属性决定
act_re_deployment(部署表):id是由act_ge_property的 next_dbid决定
act_ge_property( 通用属性表)
4、执行流程
5、查询任务
6、完成任务

四、管理流程定义

1、涉及的对象及表
① 对象: ProcessEngine 、RepositoryService、Deployment 、ProcessDefinition
② 表:

act_re_deployment:部署对象表
act_re_procdef:流程定义表
act_ge_bytearray: 字节资源表
act_ge_property:主键生成策略表,next_dbId会作为部署表的id

2、设置流程定义图
① 流程图设计
② bpmn与png文件

3、部署流程定义
① 通过bpmn和png格式加载及部署
② 通过Zip格式加载及部署
③ 查看流程定义
④ 删除流程定义
⑤ 获取流程定义文档的资源(查看流程图附加)
⑥ 查看最新版本的流程定义

//流程定义管理
public class ProcessDefinitionManager {
	private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
	//部署流程定义1:资源来在bpmn格式
	@Test
	public void deployProcessDefi(){
		Deployment deploy = processEngine.getRepositoryService()
		.createDeployment()
		.name("采购流程")
		.addClasspathResource("diagrams/BuyBill.bpmn")
		.addClasspathResource("diagrams/BuyBill.png")
		.deploy();
		System.out.println("部署名称:"+deploy.getName());
		System.out.println("部署id:"+deploy.getId());
	}
	
	//部署流程定义2:资源来自zip格式
	@Test
	public void deployProcessDefiByZip(){
		InputStream in=getClass().getClassLoader().getResourceAsStream("BuyBill.zip");
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment()
				.name("采购流程")
				.addZipInputStream(new ZipInputStream(in))
				.deploy();
		System.out.println("部署名称:"+deploy.getName());
		System.out.println("部署id:"+deploy.getId());
	}
	
	//查看流程定义
	@Test
	public void queryProcessDefination(){
		String processDefiKey="buyBill";//流程定义key
		//获取流程定义列表
		List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery()
		//查询 ,好比where
//		.processDefinitionId(proDefiId) //流程定义id
		 // 流程定义id  : buyBill:2:704   组成 : proDefikey(流程定义key)+version(版本)+自动生成id
		.processDefinitionKey(processDefiKey)//流程定义key 由bpmn 的 process 的  id属性决定
//		.processDefinitionName(name)//流程定义名称  由bpmn 的 process 的  name属性决定
//		.processDefinitionVersion(version)//流程定义的版本
		.latestVersion()//最新版本
		//排序
		.orderByProcessDefinitionVersion().desc()//按版本的降序排序
		//结果
//		.count()//统计结果
//		.listPage(arg0, arg1)//分页查询
		.list();
		//遍历结果
		if(list!=null&&list.size()>0){
			for(ProcessDefinition temp:list){
				System.out.print("流程定义的id: "+temp.getId());
				System.out.print("流程定义的key: "+temp.getKey());
				System.out.print("流程定义的版本: "+temp.getVersion());
				System.out.print("流程定义部署的id: "+temp.getDeploymentId());
				System.out.println("流程定义的名称: "+temp.getName());
			}
		}
	}
	
	//查看bpmn 资源图片
	@Test
	public void viewImage() throws Exception{
		String deploymentId="601";
		String imageName=null;
		//取得某个部署的资源的名称  deploymentId
		List<String> resourceNames = processEngine.getRepositoryService().getDeploymentResourceNames(deploymentId);
		// buybill.bpmn  buybill.png 
		if(resourceNames!=null&&resourceNames.size()>0){
			for(String temp :resourceNames){
				if(temp.indexOf(".png")>0){
					imageName=temp;
				}
			}
		}
		
		/**
		 * 读取资源
		 * deploymentId:部署的id
		 * resourceName:资源的文件名
		 */
		InputStream resourceAsStream = processEngine.getRepositoryService()
				.getResourceAsStream(deploymentId, imageName);
		//把文件输入流写入到文件中
		File file=new File("d:/"+imageName);
		FileUtils.copyInputStreamToFile(resourceAsStream, file);
	}
	
	//删除流程定义
	@Test
	public void deleteProcessDefi(){
		//通过部署id来删除流程定义
		String deploymentId="101";
		processEngine.getRepositoryService().deleteDeployment(deploymentId);
	}
}

五、流程实例和流程任务

1、涉及的对象及表
① Execution:执行对象,按流程定义的规则执行一次的过程
对应的表:

act_ru_execution: 正在执行的信息
act_hi_procinst:已经执行完的历史流程实例信息
act_hi_actinst:存放历史所有完成的活动

② ProcessInstance:流程实例,特指流程从开始到结束的那个最大的执行分支,一个执行的流程中流程实例只有1个。
注意
◇ 如果是单例流程,执行对象ID就是流程实例ID
◇ 如果一个流程有分支和聚合,那么执行对象ID和流程实例ID就不相同
◇ 一个流程中,流程实例只有1个,执行对象可以存在多个。
③ Task:任务
执行到某任务环节时生成的任务信息。
对应的表:

act_ru_task:正在执行的任务信息
act_hi_taskinst:已经执行完的历史任务信息

2、启动流程实例
3、查看我的个人任务
4、办理任务(完成任务)
5、查询流程实例状态(判断流程是正在执行还是结束)
6、查询历史任务
7、查看历史流程实例

public class ProcessInstanceAndTask {
	private ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
	//部署流程定义  ,采用buyBill
	//执行流程,开始跑流程
	@Test
	public void startProcess(){
		String processDefiKey="buyBill";//bpmn 的 process id属性
		ProcessInstance pi = processEngine.getRuntimeService()
		.startProcessInstanceByKey(processDefiKey);
		System.out.println("流程执行对象的id:"+pi.getId());//Execution 对象
		System.out.println("流程实例的id:"+pi.getProcessInstanceId());//ProcessInstance 对象
		System.out.println("流程定义的id:"+pi.getProcessDefinitionId());//默认执行的是最新版本的流程定义	
	}
	
	//查询正在运行任务 
	@Test
	public void queryTask(){
		//取得任务服务
		TaskService taskService = processEngine.getTaskService();
		//创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		//办理人的任务列表
		List<Task> list = taskQuery.list();
		//遍历任务列表
		if(list!=null&&list.size()>0){
			for(Task task:list){
				System.out.println("任务的办理人:"+task.getAssignee());
				System.out.println("任务的id:"+task.getId());
				System.out.println("任务的名称:"+task.getName());
			}
		}
	}
	
	//完成任务
	@Test
	public void compileTask(){
		String taskId="1002";
		//taskId:任务id
		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}
	
	//获取流程实例的状态
	@Test
	public void getProcessInstanceState(){
		String processInstanceId="801";
		 ProcessInstance pi = processEngine.getRuntimeService()
		 .createProcessInstanceQuery()
		 .processInstanceId(processInstanceId)
		 .singleResult();//返回的数据要么是单行,要么是空 ,其他情况报错
		 //判断流程实例的状态
		 if(pi!=null){
			 System.out.println("该流程实例"+processInstanceId+"正在运行...  "+"当前活动的任务:"+pi.getActivityId());
		 }else{
			 System.out.println("当前的流程实例"+processInstanceId+" 已经结束!");
		 } 
	}
	
	//查看历史执行流程实例信息
	@Test
	public void queryHistoryProcInst(){
		List<HistoricProcessInstance> list = processEngine.getHistoryService()
		.createHistoricProcessInstanceQuery()
		.list();
		if(list!=null&&list.size()>0){
			for(HistoricProcessInstance temp:list){
				System.out.println("历史流程实例id:"+temp.getId());
				System.out.println("历史流程定义的id:"+temp.getProcessDefinitionId());
				System.out.println("历史流程实例开始时间--结束时间:"+temp.getStartTime()+"-->"+temp.getEndTime());
			}
		}
	}
	
	//查看历史执行流程任务信息
	@Test
	public void queryHistoryTask(){
		String processInstanceId="801";
		List<HistoricTaskInstance> list = processEngine.getHistoryService()
				.createHistoricTaskInstanceQuery()
				.processInstanceId(processInstanceId)
				.list();
		if(list!=null&&list.size()>0){
			for(HistoricTaskInstance temp:list){
				System.out.print("历史流程实例任务id:"+temp.getId());
				System.out.print("历史流程定义的id:"+temp.getProcessDefinitionId());
				System.out.print("历史流程任务名称:"+temp.getName());
				System.out.println("历史流程任务处理人:"+temp.getAssignee());
			}
		}
	}
}

六、流程变量

1、涉及到的表:

act_ru_variable:正在执行的流程变量表
act_hi_varinst:流程变量历史表

2、流程变量作用
① 传递业务参数(申请人、天数、事件、原因)
② 动态指定办理人
③ 指定连接,完成任务(同意或者拒绝)

3、设置简易的bpmn流程图
4、部署流程定义及启动流程实例
5、设置流程变量:通过 TaskService 和 RuntimeService 服务设置变量
6、获取流程变量
7、查询历史的流程变量
8、流程变量支持的类型(包括了大部分封装类型和Date、String和实现了Serializable接口的类的类型)

public class AppayBillBean  implements Serializable{
	private Integer id;
	private Integer cost;//金额
	private String appayPerson;//申请人
	private Date date;//申请日期
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Integer getCost() {
		return cost;
	}
	public void setCost(Integer cost) {
		this.cost = cost;
	}
	public String getAppayPerson() {
		return appayPerson;
	}
	public void setAppayPerson(String appayPerson) {
		this.appayPerson = appayPerson;
	}
	public Date getDate() {
		return date;
	}
	public void setDate(Date date) {
		this.date = date;
	}
}
public class ProcessVariable {
	private ProcessEngine processEngine = ProcessEngines
			.getDefaultProcessEngine();

	// 部署流程定义,资源来在bpmn格式
	@Test
	public void deployProcessDefi() {
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment().name("支付流程")
				.addClasspathResource("diagrams/AppayBill.bpmn")
				.addClasspathResource("diagrams/AppayBill.png")
				.deploy();
		System.out.println("部署名称:" + deploy.getName());
		System.out.println("部署id:" + deploy.getId());
	}

	// 执行流程,开始跑流程
	@Test
	public void startProcess() {
		String processDefiKey = "appayBill";// bpmn 的 process id属性
		ProcessInstance pi = processEngine.getRuntimeService()
				.startProcessInstanceByKey(processDefiKey);
		System.out.println("流程执行对象的id:" + pi.getId());// Execution 对象
		System.out.println("流程实例的id:" + pi.getProcessInstanceId());// ProcessInstance														
		System.out.println("流程定义的id:" + pi.getProcessDefinitionId());// 默认执行的是最新版本的流程定义
	}

	// 查询正在运行任务
	@Test
	public void queryTask() {
		// 取得任务服务
		TaskService taskService = processEngine.getTaskService();
		// 创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		// 办理人的任务列表
		List<Task> list = taskQuery.list();
		// 遍历任务列表
		if (list != null && list.size() > 0) {
			for (Task task : list) {
				System.out.println("任务的办理人:" + task.getAssignee());
				System.out.println("任务的id:" + task.getId());
				System.out.println("任务的名称:" + task.getName());
			}
		}
	}

	// 完成任务
	@Test
	public void compileTask() {
		String taskId = "1502";
		// taskId:任务id
		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}
	
	//设置流程变量值
	@Test
	public void setVariable(){
		String taskId="1804";//任务id
		//采用TaskService来设置流程变量
		
		//1. 第一次设置流程变量
//		TaskService taskService = processEngine.getTaskService();
//		taskService.setVariable(taskId, "cost", 1000);//设置单一的变量,作用域在整个流程实例
//		taskService.setVariable(taskId, "申请时间", new Date());
//		taskService.setVariableLocal(taskId, "申请人", "何某某");//该变量只有在本任务中是有效的
		
		//2. 在不同的任务中设置变量
//		TaskService taskService = processEngine.getTaskService();
//		taskService.setVariable(taskId, "cost", 5000);//设置单一的变量,作用域在整个流程实例
//		taskService.setVariable(taskId, "申请时间", new Date());
//		taskService.setVariableLocal(taskId, "申请人", "李某某");//该变量只有在本任务中是有效的
		
		/**
		 * 3. 变量支持的类型
		 * - 简单的类型 :String 、boolean、Integer、double、date 
		 * - 自定义对象bean  
		 */
		TaskService taskService = processEngine.getTaskService();
		//传递的一个自定义bean对象
		AppayBillBean appayBillBean=new AppayBillBean();
		appayBillBean.setId(1);
		appayBillBean.setCost(300);
		appayBillBean.setDate(new Date());
		appayBillBean.setAppayPerson("何某某");
		taskService.setVariable(taskId, "appayBillBean", appayBillBean);
		System.out.println("设置成功!");
	}
	
	//查询流程变量
	@Test
	public void getVariable(){
		String taskId="1804";//任务id
//		TaskService taskService = processEngine.getTaskService();
//		Integer cost=(Integer) taskService.getVariable(taskId, "cost");//取变量
//		Date date=(Date) taskService.getVariable(taskId, "申请时间");//取本任务中的变量
		Date date=(Date) taskService.getVariableLocal(taskId, "申请时间");//取本任务中的变量
//		String appayPerson=(String) taskService.getVariableLocal(taskId, "申请人");//取本任务中的变量
		String appayPerson=(String) taskService.getVariable(taskId, "申请人");//取本任务中的变量
//		
//		System.out.println("金额:"+cost);
//		System.out.println("申请时间:"+date);
//		System.out.println("申请人:"+appayPerson);

		//读取实现序列化的对象变量数据
		TaskService taskService = processEngine.getTaskService();
		AppayBillBean appayBillBean=(AppayBillBean) taskService.getVariable(taskId, "appayBillBean");
		System.out.println(appayBillBean.getCost());
		System.out.println(appayBillBean.getAppayPerson());
	}
	
	//模拟流程变量设置
	@Test
	public void  getAndSetProcessVariable(){
		//有两种服务可以设置流程变量
//		TaskService taskService = processEngine.getTaskService();
//		RuntimeService runtimeService = processEngine.getRuntimeService();
		
		/**1.通过 runtimeService 来设置流程变量
		 * exxcutionId: 执行对象
		 * variableName:变量名
		 * values:变量值
		 */
//		runtimeService.setVariable(exxcutionId, variableName, values);
//		runtimeService.setVariableLocal(executionId, variableName, values);
		//设置本执行对象的变量 ,该变量的作用域只在当前的execution对象
//		runtimeService.setVariables(exxcutionId, variables); 
		  //可以设置多个变量  放在 Map<key,value>  Map<String,Object>
		
		/**2. 通过TaskService来设置流程变量
		 * taskId:任务id
		 */
//		taskService.setVariable(taskId, variableName, values);
//		taskService.setVariableLocal(taskId, variableName, values);
		设置本执行对象的变量 ,该变量的作用域只在当前的execution对象
//		taskService.setVariables(taskId, variables); //设置的是Map<key,values>
		
		/**3. 当流程开始执行的时候,设置变量参数
		 * processDefiKey: 流程定义的key
		 * variables: 设置多个变量  Map<key,values>
		 */
//		processEngine.getRuntimeService()
//		.startProcessInstanceByKey(processDefiKey, variables)
		
		/**4. 当执行任务时候,可以设置流程变量
		 * taskId:任务id
		 * variables: 设置多个变量  Map<key,values>
		 */
//		processEngine.getTaskService().complete(taskId, variables);
		
		
		/** 5. 通过RuntimeService取变量值
		 * exxcutionId: 执行对象
		 * 
		 */
//		runtimeService.getVariable(exxcutionId, variableName);//取变量
//		runtimeService.getVariableLocal(exxcutionId, variableName);//取本执行对象的某个变量
//		runtimeService.getVariables(variablesName);//取当前执行对象的所有变量
		/** 6. 通过TaskService取变量值
		 * TaskId: 执行对象
		 * 
		 */
//		taskService.getVariable(taskId, variableName);//取变量
//		taskService.getVariableLocal(taskId, variableName);//取本执行对象的某个变量
//		taskService.getVariables(taskId);//取当前执行对象的所有变量
	}	
}

9、Execution 与 ProcessInstance 区别
① Execution:只一个流程实例具体要执行的过程对象
② ProcessInstance:流程实例 ProcessInstance(1)–>Execution(N) ,且N>=1
③ 值等情况: act_ru_execution 的id和 proc_inst_id 相同 ,该流程没有子流程
④ 值不等情况: 只会出现在子流程中(嵌套、引入),act_ru_execution 的id和 proc_inst_id 不相同,但parent_id 等于当前流程实例的 id 和proc_inst_id
⑤ 比如一个购物流程中除了下单、出库节点,可能还有一个付款子流程,一般付款流程都是作为公用的流程,当任务达到子流程时,引擎会自动创建一个付款子流程

10、setValiable 与 setLocalValiable区别:作用域

七、连线

1、设置bpmn流程图
2、部署和执行流程
3、查询和完成任务
4、如何设置条件变量
连线 > main config > condition
表达式的结果必须是布尔型: #{variable=='value'} 或者 ${variable==value}
5、总结
① 一个活动中可以指定一个或多个SequenceFlow(Start中有一个,End中没有)。
◇ 开始活动中有一个SequenceFlow
◇ 结束活动中没有SequenceFlow
◇ 其他活动中有1条或多条SequenceFlow
② 如果只有一个,则可以不使用流程变量设置codition的名称

public class SequenceFlow {
	private ProcessEngine processEngine = ProcessEngines
			.getDefaultProcessEngine();
	// 部署流程定义,资源来在bpmn格式
	@Test
	public void deployProcessDefi() {
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment().name("连线流程")
				.addClasspathResource("diagrams/SequenceFlow.bpmn")
				.deploy();
		System.out.println("部署名称:" + deploy.getName());
		System.out.println("部署id:" + deploy.getId());
	}

	// 执行流程,开始跑流程
	@Test
	public void startProcess() {
		String processDefiKey = "sequenceBill";// bpmn 的 process id属性
		ProcessInstance pi = processEngine.getRuntimeService()
				.startProcessInstanceByKey(processDefiKey);
		System.out.println("流程执行对象的id:" + pi.getId());// Execution 对象
		System.out.println("流程实例的id:" + pi.getProcessInstanceId());// ProcessInstance
		System.out.println("流程定义的id:" + pi.getProcessDefinitionId());// 默认执行的是最新版本的流程定义
	}

	// 查询正在运行任务
	@Test
	public void queryTask() {
		// 取得任务服务
		TaskService taskService = processEngine.getTaskService();
		// 创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		// 办理人的任务列表
		List<Task> list = taskQuery.list();
		// 遍历任务列表
		if (list != null && list.size() > 0) {
			for (Task task : list) {
				System.out.println("任务的办理人:" + task.getAssignee());
				System.out.println("任务的id:" + task.getId());
				System.out.println("任务的名称:" + task.getName());
			}
		}
	}

	// 完成任务
	@Test
	public void compileTask() {
		String taskId = "2704";
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("message", "不知道重不重要");
		// taskId:任务id
		processEngine.getTaskService().complete(taskId, params);
//		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}
}

八、排他网关(ExclusiveGateWay)

1、设置bpmn流程图
2、部署与执行流程
3、查询和完成任务
4、总结
① 一个排他网关对应一个以上的顺序流
② 由排他网关流出的顺序流都有个conditionExpression元素,在内部维护返回boolean类型的决策结果。
③ 决策网关只会返回一条结果。当流程执行到排他网关时,流程引擎会自动检索网关出口,从上到下检索如果发现 第一条决策结果为true或者没有设置条件的(默认为成立),则流出。
④ 如果没有任何一个出口符合条件,则抛出异常
⑤ 使用流程变量,设置连线的条件,并按照连线的条件执行工作流,如果没有条件符合的条件,则以默认的连线离开,但是默认的连线不能设置条件

public class ExclusiveGetWay {
	private ProcessEngine processEngine = ProcessEngines
			.getDefaultProcessEngine();

	// 部署流程定义,资源来在bpmn格式
	@Test
	public void deployProcessDefi() {
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment().name("排他网关流程")
				.addClasspathResource("diagrams/ExclusiveGateway.bpmn")
				.deploy();

		System.out.println("部署名称:" + deploy.getName());
		System.out.println("部署id:" + deploy.getId());
	}

	// 执行流程,开始跑流程
	@Test
	public void startProcess() {
		String processDefiKey = "bankBill";// bpmn 的 process id属性
		ProcessInstance pi = processEngine.getRuntimeService()
				.startProcessInstanceByKey(processDefiKey);

		System.out.println("流程执行对象的id:" + pi.getId());// Execution 对象
		System.out.println("流程实例的id:" + pi.getProcessInstanceId());// ProcessInstance
																	// 对象
		System.out.println("流程定义的id:" + pi.getProcessDefinitionId());// 默认执行的是最新版本的流程定义
	}

	// 查询正在运行任务
	@Test
	public void queryTask() {
		// 取得任务服务
		TaskService taskService = processEngine.getTaskService();
		// 创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		// 办理人的任务列表
		List<Task> list = taskQuery.list();
		// 遍历任务列表
		if (list != null && list.size() > 0) {
			for (Task task : list) {
				System.out.println("任务的办理人:" + task.getAssignee());
				System.out.println("任务的id:" + task.getId());
				System.out.println("任务的名称:" + task.getName());
			}
		}
	}

	// 完成任务
	@Test
	public void compileTask() {
		String taskId = "3704";
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("visitor", 6);
		// taskId:任务id
		processEngine.getTaskService().complete(taskId, params);
//		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}
}

九、指定任务处理者

个人分配任务方式1:直接指定
个人分配任务方式2:采用流程变量(在bpmn的assignee设置 ${userID}

public class UserTask {
	private ProcessEngine processEngine = ProcessEngines
			.getDefaultProcessEngine();

	// 部署流程定义,资源来在bpmn格式
	@Test
	public void deployProcessDefi() {
		Deployment deploy = processEngine.getRepositoryService()
				.createDeployment().name("用户任务指定流程")
				.addClasspathResource("diagrams/AppayBill.bpmn")
				.deploy();

		System.out.println("部署名称:" + deploy.getName());
		System.out.println("部署id:" + deploy.getId());
	}

	// 执行流程,开始跑流程
	@Test
	public void startProcess() {
		String processDefiKey = "appayBill";// bpmn 的 process id属性
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("userID", "王某某");
		ProcessInstance pi = processEngine.getRuntimeService()
				.startProcessInstanceByKey(processDefiKey, params);
		System.out.println("流程执行对象的id:" + pi.getId());// Execution 对象
		System.out.println("流程实例的id:" + pi.getProcessInstanceId());// ProcessInstance
		System.out.println("流程定义的id:" + pi.getProcessDefinitionId());// 默认执行的是最新版本的流程定义
	}

	// 查询正在运行任务
	@Test
	public void queryTask() {
		String assignee="王某某";//指定任务处理人
		// 取得任务服务
		TaskService taskService = processEngine.getTaskService();
		// 创建一个任务查询对象
		TaskQuery taskQuery = taskService.createTaskQuery();
		// 办理人的任务列表
		List<Task> list = taskQuery
				.taskAssignee(assignee)
				.list();
		// 遍历任务列表
		if (list != null && list.size() > 0) {
			for (Task task : list) {
				System.out.println("任务的办理人:" + task.getAssignee());
				System.out.println("任务的id:" + task.getId());
				System.out.println("任务的名称:" + task.getName());
			}
		}
	}

	// 完成任务
	@Test
	public void compileTask() {
		String taskId = "3704";
		Map<String,Object> params=new HashMap<String, Object>();
		params.put("visitor", 6);
		// taskId:任务id
		processEngine.getTaskService().complete(taskId, params);
//		processEngine.getTaskService().complete(taskId);
		System.out.println("当前任务执行完毕");
	}
}

十、数据库相关表

 -- 流程部署相关的表
SELECT * FROM act_ge_bytearray # 通用字节资源表
SELECT * FROM act_ge_property # 通用属性表,可以生成部署id
SELECT * FROM act_re_deployment  #部署表
SELECT * FROM act_re_procdef    # 流程定义表

-- 流程实例与任务相关的表
SELECT * FROM act_ru_execution  # 流程执行对象信息
SELECT * FROM act_ru_task   # 正在运行的任务表
SELECT * FROM act_hi_procinst # 历史流程实例表
SELECT * FROM act_hi_taskinst  # 历史流程任务表

-- 流程变量相关表
SELECT * FROM act_ru_variable # 正在执行的流程变量表
SELECT * FROM act_hi_varinst # 流程变量历史表
前 言 1 1 概 述 2 1.1 选题背景 2 1.2 组织结构 2 2 所用相关技术和方法 3 2.1 工作流 3 2.1.1 什么叫工作流 3 2.1.2 工作流发展 3 2.1.3 工作流的优点 3 2.2 MVC工作模式 4 2.2.1 MVC设计思想 4 2.2.2 MVC的具体实现 5 2.2.3 MVC的不足 6 2.3 JSP技术介绍 6 2.3.1 JSP的运行原理 7 2.3.2 JSP的生命周期 8 2.3.3 Servlet和JavaBean技术介绍 8 2.3.4 Java 虚拟机 9 2.3.5 JSP访问SQL Server 2000数据库 9 2.4 数据库后台环境配置 10 2.5 系统开发工具简介 10 2.5.1 Dreamweaver 10 2.5.2 MyEclipse 10 2.5.3 Tomcat 11 2.5.4 SQL Server2000 11 2.5.5 chs_sql2ksp3 12 3 系统需求分析 13 3.1 系统功能分析 13 3.2 系统性能分析 13 3.3 系统方案的确定和评价 13 4 系统总体设计 15 4.1 系统层次模块图 15 4.1.1 营业厅模块 15 4.1.2 收费管理模块 16 4.2 系统数据流程图 16 4.3 数据表设计 18 5 详细设计及编码 21 5.1 编写JAVABEAN 21 5.2 营业厅实现函数 21 5.3 收费厅主要的实现函数 22 5.4 JAVABEAN主要实现模块 22 5.4.1 中文字符格式的转换模块(Stringto.java) 22 5.4.2 自动生成验证码(Ran.java) 22 5.4.3 数据库的连接(ConnectionFactory.java) 23 5.4.4 数据库连接的关闭(DatabaseUtils.java)--只提供接口 23 5.4.5 密码修改模块(Common_fuction.java) 24 5.4.6 时间格式转换(timeBean.java) 24 5.4.7 数据统计(counthander.java) 25 5.4.8 营业厅的接口(luruaction.java) 27 5.4.9 营业厅的主要函数实现(luruhander.java) 28 5.4.10 收费厅的主要函数接口 32 5.5 管理员登陆模块 33 5.5.1 管理员登录 33 5.6 营业厅管理模块 36 5.6.1 Left.jsp页面 36 5.6.2 Work.jsp 40 5.6.3 customerlistinfo.jsp 41 5.6.4 allinfo.jsp 41 5.7 收费厅管理模块 42 5.7.1 Left.jsp 42 5.7.2 Work.jsp 43 5.7.3 Customerlistinfo.jsp 43 5.7.4 gongdan.jsp 43 6 系统测试与维护 45 6.1 测试目的 45 6.2 测试环境 45 6.3 系统测试 45 6.4 系统维护 45 7 开发难点与技术 46 7.1 主要程序实现的代码描述 46 7.1.1 验证码的自动生成 46 7.1.2 生成WORD工单 46 7.1.3 以一定的时间刷新页面 47 7.1.4 JSP中文问题的解决 47 7.2 在程序编码过程遇到的主要问题: 48 7.3 代码编写风格 49 7.4 我的不足: 49 结束语 50 致 谢 50
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值