• 1. 成都传智播客 cd.itcast.cnJBPM 讲师:蓝声强
  • 2. 成都传智播客 cd.itcast.cn工作流的概念 工作流(Work Flow):全部或者部分由计算机支持或自动处理的业务过程。工作流要解决的主要问题是:为实现某个业务目标,在多个参与者之间,利用计算机,按某种预定规则自动传递文档、信息或者任务。 简单地说,工作流就是一系列相互衔接、自动进行的业务活动或任务。一个工作流包括一组任务(或活动)及它们的相互顺序关系,还包括流程及任务(或活动)的启动和终止条件,以及对每个任务(或活动)的描述。
  • 3. 成都传智播客 cd.itcast.cn工作流管理系统工作流管理系统(Workflow Management System, WfMS)是一个软件系统,它完成工作量的定义和管理,并按照在系统中预先定义好的工作流逻辑进行工作流实例的执行。工作流管理系统不是企业的业务系统,而是为企业的业务系统的运行提供了一个软件的支撑环境。
  • 4. 成都传智播客 cd.itcast.cn工作流管理系统工作流管理联盟(WfMC,Workflow Management Coalition)给出的关于工作流管理系统的定义是:工作流管理系统是一个软件系统,它通过执行经过计算的流程定义去支持一批专门设定的业务流程。工作流管理系统被用来定义、管理、和执行工作流程。 工作流管理系统的目标:管理工作的流程以确保工作在正确的时间被期望的人员所执行——在自动化进行的业务过程中插入人工的执行和干预。
  • 5. 成都传智播客 cd.itcast.cn工作流技术在企业中的应用应用方面: 协助涉及多人/部门相关任务的工作执行 作为企业应用集成平台 嵌入式工作流引擎 优势: 提高效率 较好的流程控制 改进客户服务 促进业务改进 方便企业业务流程重组
  • 6. 工作流系统核心模型工作流引擎工作列表流程定义解释定义产生业务数据库持久化组件成都传智播客 cd.itcast.cn
  • 7. 成都传智播客 cd.itcast.cn工作流中的一些术语工作流 就是工作从开始到完成的过程。工作流由流程逻辑和路线规则组成。流程逻辑定义了任务的顺序和必须遵循的路线规则,还有截止期限以及由工作流引擎实现的其他业务规则 ; 流程定义(process definition) 一个图形流程定义或流程图,代表工作流的流程逻辑元素以及各元素之间的关系 流程实例(process instance): 一个流程实例,通常称为工作,是一个流程定义的运行实例 状态(state,或者说等待状态): 代表一种对外部参与者的依赖;这意味着在流程运行时流程引擎必须等待,直到外部参与者通知工作流系统指定的状态完成了 动作(action): 在流程运行过程中,工作流系统为响应指定事件运行的一段程序逻辑;当流程运行过程中指定的事件发生时,工作流系统启动并执行这些动作
  • 8. 成都传智播客 cd.itcast.cn工作流中的一些术语流程上下文变量(process context variable): 保存每一个流程运行的上下文信息;通常在流程定义中声明这些变量,然后在流程实例生成时被实例化 参与者 以下类型之一:资源集、特定资源、组织单元、角色(一个人在组织内部的作用)、人或系统(自动代理)。 活动 组成流程定义中的一个逻辑步骤的任务。可以是自动的或人工的。自动指在流程操作过程中定义脚本和触发器的能力。流程定义中的特定活动可以作为无人参与的任务来运行,自动化可以在手工或人力驱动的任务中执行业务规则。常见的一种自动活动就是截止期限管理,如果某个工作项在预定的截止期限之前未能完成,该管理可以自动发送一条提醒消息或触发一个延期程序。 活动所有者 活动所有者是有权宣布一个活动结束,然后推进工作到流程中的下一个活动的参与者 工作所有者 工作所有者是有权整体控制流程实例执行过程的参与者 工作项 代表流程实例中活动的参与者将要执行的工作
  • 9. 成都传智播客 cd.itcast.cnJBPM简介JBPM,全称是Java Business Process Management(业务流程管理),它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。jBPM是JBOSS厂商下的一个开源项目,它使用的是LGPL协议。 JBOSS是一个开源厂商,被Red Hat收购,其下知名项目有Jboss服务器、Hiberante、JBPM,JbossCache,Drools(规则引擎)...等等,函盖多个领域。 JBPM是一个工作流平台,是一个工作流应用基础框架及工作流引擎; JBPM是一个基于Hibernate的应用系统; JBPM使用自己定义的JBoss jBPM Process definition language (jPdl)来描述业务流程,业务流程图相当于状态图,jPdl就是详细定义了这个状态图的每个部分,如起始、结束状态,状态之间的转换,过图型化的流程定义,直观地描述业务流程。
  • 10. 成都传智播客 cd.itcast.cnJBPM特点嵌入式的工作流引擎 : 完全嵌入式应用的业务流程开发框架,可在事务,持久化等各个方面和应用程序灵活集成。不依赖任何中间件或服务器。发布只需要依赖jar包。 可插拔的体系架构: 采用了Ioc的设计理念,各个模块之间可以方便的替换不同实现,如事务,持久化,身份认证,日志等。 易扩展的流程语言 在Jbpm中内置的流程定义活动,都提供了将业务逻辑java代码和业务流程绑定的机制。并允许通过定制新的活动类型或者完全重新设计一种新的流程定义语言来描述特定领域的业务流程。
  • 11. 成都传智播客 cd.itcast.cnJBPM4安装使用1、准备tomcat6.0.26+,放置到jbpm3的install\download目录下 2、运行ant demo.setup.tomcat 可以起动tomcat示例 访问:http://localhost:8080/jbpm-console访问控制台,可以看到与jbpm4相关的一些概念。 访问:http://localhost:8080/jbpmeditor/p/explorer基于web的流程设计器(Signavio web建模器),结果生成在signavio-repository目录中。 3、 流程设计器GPD,Eclipse插件; 4、添加jBPM Libraries,把jbpm相关的lib添加到该库中 5、在XML CataLog中添加jPDL4模式
  • 12. 成都传智播客 cd.itcast.cnjbpm-jpdl设计器GPD插件安装及使用流程设计器插件安装 GPD使用 一个流程定义文件是一个扩展名为.jpdl.xml的文件; 节点介绍
  • 13. JBPM之HelloWorld1.eclipse3.4以上 2.jbpm4.4 3.安装jbpm插件 4. a.eclipse->help install new software..., b.add...选择Archive...在选择%JBPM_HOME%\install\src\gpd\jbpm-gpd-site.zip c.取消Contact all update...的勾,不是联网更新插件很慢的 5.创建java project 6.创建Other->JBoss jBPM->jBPM 4 Process Definition->输入helloworld 7.helloworld.jpdl.xml右键Open With->jBPM jPDL4 Editor 8.创建流程图,查看helloworld.jpdl.xml
  • 14. JBPM表结构JBPM4_DEPLOYMENT 流程定义表 JBPM4_DEPLOYPROP 流程定义属性表 JBPM4_EXECUTION 流程实例表 JBPM4_HIST_ACTINST 流程活动(节点)实例表 JBPM4_HIST_DETAIL 流程历史详细表 JBPM4_HIST_PROCINST 流程实例历史表 JBPM4_HIST_TASK 流程任务实例历史表 JBPM4_HIST_VAR 流程变量(上下文)历史表 JBPM4_ID_GROUP 组表 JBPM4_ID_MEMBERSHIP 用户角色表 JBPM4_ID_USER 用户表 JBPM4_JOB 定时表 JBPM4_LOB 存储流程定义文件表 JBPM4_PARTICIPATION 参与者表 JBPM4_SWIMLANE 泳道表 JBPM4_TASK 任务表 JBPM4_VARIABLE 上下文表
  • 15. JBPM4注意事项若数据库选择为mysql,应注意修改jbpm.hibernate.cfg.xml中mysql的方言为org.hibernate.dialect.MySQL5InnoDBDialect 常见错误loading for a different type with name "javax/servlet/http/HttpServletRequest" 包冲突,只有tomcat6.X有这个问题,jpml自带的juel.jar, juel-engine.jar, juel-impl.jar会与tomcat目录中的el-api.jar发生冲突 换掉tomcat,使用tomcat5.5是没有问题的。 将juel.jar, juel-engine.jar, juel-impl.jar这三个包复制到tomcat6下lib中(改原来的el-api.jar为el-api.jar.txt,或者干脆删掉),并且把WEB-INF\lib中的juel.jar, juel-engine.jar, juel-impl.jar删除。
  • 16. 相关概念JBPM: Java Business Process Managerment(Java商业流程管理系统) JPDL: Jbpm Process Definition Language(Jbpm流程定义语言) PVM: Process Virtual Machine (流程虚拟机制) GPD: Graphical Process Designer(图形化流程设计)
  • 17. 成都传智播客 cd.itcast.cn借款流程
  • 18. 成都传智播客 cd.itcast.cnjpdl文件介绍根元素process节点 name流程名称,必填,在与用户交互时,作为流程名字显示的一个名字或是标签。 key键,字母或数字,下划线,用来辨别不同的流程定义。 version版本,整型,流程的版本号。默认会从1开始,如果系统中已有相同key的流程,则版本会自加1。 process下面包一个或多个流程活动(activities活动) 比如:
  • 19. 成都传智播客 cd.itcast.cnStart节点 说明一个流程的实例从哪里开始。 在一个流程里有且仅有一个开始节点(子流程可以有多个开始节点)。 开始节点必须有一个向外的流向,这个流向会在流程启动的时候执行。 start元素中可以根据情况设置一个name名称; 的子元素 节点中至少包括一个转移节点,用于指定流程开始后向什么地方转移。 示例: ...
  • 20. 成都传智播客 cd.itcast.cnState节点 一个等待状态节点。 流程处理的流向会在外部触发器调用提供的API之前一直等待。 state元素需要通过name属性设置一个名称,以便可以从其它流程转移到这个节点。 的子元素 节点中至少包括一个转移节点,用于指定流程到达这个节点后可以转移的目标节点。示例:
  • 21. 成都传智播客 cd.itcast.cntransition节点 transition元素位于各个活动节点中,用来表示活动的转移;一般来描述一个活动中的转移路径; transition元素可以包含两个属性: to:表示转移的目标,这是必须的。 name:用来指定这个转移节点的名称;当一个活动中有多个转移路径时,可以使用name来区分不同的转移,可以在程序中通过指定name来选择使用哪一个转移。 示例:
  • 22. 成都传智播客 cd.itcast.cntask节点 task元素用来表示一个任务活动,也就是将会等待任务完成后,才会继续向下执行; task元素可以包含下面的属性: name:指定任务的名称; assignee:指定任务承办人; candidate-users:指定一批任务候选人; candidate-groups:指定一批任务候选组; duedate:指定任务超期时间; form:指定任务表单; 示例:
  • 23. 成都传智播客 cd.itcast.cnend节点 end元素用来表示结束流程; 结束活动会终结已完成流程处理实例,同时活动中的多个并发(concurrent)流向(concurrent) 也会结束。 end元素可以包含下面的属性: name:用来指定节点的名称; state:指定结束的状态码; 表示取消并结束流程; 表示遇到错误并结束流程; 示例:
  • 24. 成都传智播客 cd.itcast.cn使用GPD设计一个请假流程开始结点start 状态结点state 流程流向transition 任务节点task 结束节点end 其它节点
  • 25. 成都传智播客 cd.itcast.cnJBPM核心Jar包jbpm.jar hibernate相关包 规则引擎相关包 其它相关包
  • 26. 成都传智播客 cd.itcast.cnJBPM4 Service API使用管理流程部署 管理流程实例 管理流程任务 管理流程历史 等等。。。
  • 27. 成都传智播客 cd.itcast.cn流程引擎org.jbpm.api.ProcessEngine 流程引擎对象通过配置对象获得 ProcessEngine processEngine = new Configuration().buildProcessEngine(); JBPM中所有重要的服务对象都由流程引擎获得 RepositoryService repositoryService = processEngine.getRepositoryService(); ExecutionService executionService = processEngine.getExecutionService(); TaskService taskService = processEngine.getTaskService(); HistoryService historyService = processEngine.getHistoryService(); ManagementService managementService = processEngine.getManagementService(); IdentityService identityService=processEngine.getIdentityService();
  • 28. 成都传智播客 cd.itcast.cnJBPM中重要的服务对象RepositoryService 流程资源服务,提供对流程定义的部署,查询,删除等维护。 ExecutionService 流程执行服务,提供启动流程实例,执行流程,设置流程变量等维护。 TaskService 任务服务,提供任务的创建,提交,查询等维护。 HistoryService 流程历史服务,提供对历史流程的查询,和简单统计等维护。 ManagementService 流程管理服务,提供对工作(Job)的查询和执行操作。 IdentityService 身份认证服务,提供对用户,用户组和其组成关系的维护。
  • 29. 成都传智播客 cd.itcast.cn部署流程从CLASSPATH部署一个流程 String deploymentid = repositoryService.createDeployment() .addResourceFromClasspath("org/jbpm/examples/services/Order.jpdl.xml") .deploy(); 从Zip文件部署一个流程 ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream( new File("D:/stef/workspace/jbpm4/src/helloworld.zip"))); repositoryService.createDeployment() .addResourcesFromZipInputStream(zipInputStream).deploy(); 从Zip文件部署一个流程 ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(getClass().getResourceAsStream("helloworld.zip"))); repositoryService.createDeployment() .addResourcesFromZipInputStream(zipInputStream).deploy();
  • 30. 成都传智播客 cd.itcast.cn流程定义的关键属性name:流程定义的名称,来源于流程定义文件 key:流程定义的键,可以在流程文件中定义,或者根据流程名称生成 version:流程定义的版本,用来标示同一名称的流程定义的不同版本,系统自动处理。 id:流程定义的id。生成格式为{key}-{version}
  • 31. 成都传智播客 cd.itcast.cn删除流程定义删除一个已经部署的流程定义: repositoryService.deleteDeployment(deploymentId); 如果该流程定义中存在为完成的流程实例,删除时抛错。 级联删除一个已经部署的流程定义: repositoryService.deleteDeploymentCascade(deploymentId); 删除绑定该流程定义的所有对象,包括流程实例,历史信息等。 (注意:如果是使用Mysql数据库,需要修改Hibernate配置的dialect属性为:org.hibernate.dialect.MySQL5InnoDBDialect)
  • 32. 成都传智播客 cd.itcast.cn流程定义,流程实例和执行流程定义
  • 33. 成都传智播客 cd.itcast.cn流程定义,流程实例和执行流程实例
  • 34. 成都传智播客 cd.itcast.cn流程定义,流程实例和执行流程执行
  • 35. 成都传智播客 cd.itcast.cn创建流程实例使用ExecutionService创建一个流程实例: ProcessInstance processInstance = executionService.startProcessInstanceByKey("helloworld"); 该方法使用对应Key的流程最新版本创建一个流程实例 使用指定版本创建流程实例: ProcessInstance processInstance = executionService.startProcessInstanceById(helloworld-1"); 该方法使用name为helloworld的第一个版本流程创建一个流程实例 使用指定业务键创建流程实例: ProcessInstance processInstance = executionService.startProcessInstanceByKey("helloworld",document.getId()); (使用业务键创建流程实例是一个最佳实践)
  • 36. 成都传智播客 cd.itcast.cn执行等待的流向对于State活动,执行(或流程实例) 会在到达state的时候进行等待,直到一个signal(也叫外部触发器)出现,流程实例才会继续向下执行。 executionService.signalExecutionById(executionId); 注意:有时候,到达state的执行会是流程实例本身。 但是在定时器和同步的情况, 流程是执行树形的根节点。所以必须确认signal方法作用在正确的流程路径上。
  • 37. 成都传智播客 cd.itcast.cn任务服务TaskService主要针对task活动 使用TaskService查询某一个用户的任务列表: List taskList=taskService.findPersonalTasks("user"); 使用TaskService完成一个任务: taskService.complateTask(taskId); 使用指定业务键创建流程实例(持久化业务对象) ProcessInstance processInstance = executionService.startProcessInstanceByKey("helloworld",document.getId()); (使用业务键创建流程实例是一个最佳实践)
  • 38. 成都传智播客 cd.itcast.cn历史服务所有运行完成的活动将被存入历史信息中,通过HistoryService,可以查询这些历史信息。 历史信息的分类: HistoryProcessInstance:流程实例历史信息 HistoryTask:任务历史信息 HistoryActivityInstance:所有活动历史信息 使用HistoryService对流程历史做统计分析: avgDurationerAcitivity:获取指定流程定义中每个活动的平均执行时间 choiceDistribution:获取指定活动定义每个转移的经过次数
  • 39. 成都传智播客 cd.itcast.cn常用历史服务查询示例查询某一特定流程定义的所有历史流程实例: List historyProcessInstances = historyService .createHistoryProcessInstanceQuery() .processDefinitionId(processDefinition.getId()) .orderAsc(HistoryProcessInstanceQuery.PROPERTY_STARTTIME) .list(); 获得指定流程实例已经过的节点的完整列表 List histActInsts = historyService .createHistoryActivityInstanceQuery() .processInstanceId(processInstance.getId()) .list();
  • 40. 查询APIListresults = executionService.createProcessInstanceQuery() .processDefinitionId("my_process_definition") .notSuspended().page(0,50).list(); 这个例子返回指定流程定义的所有流程实例,流程定义不是暂停的。结果支持分页,第一页的前50条数据会被我们获得。 成都传智播客 cd.itcast.cn
  • 41. 查询API查询任务也可以使用相同的方式完成: ListmyTasks = taskService.createTaskQuery() .processInstanceId(piId) .assignee("John") .page(100,120) .orderDesc(TaskQuery.PROPERTY_DUEDATE) .list(); 这个查询会获得指定流程实例,分配给John的所有任务,也使用分页,对duedate进行逆序查询。 成都传智播客 cd.itcast.cn
  • 42. 成都传智播客 cd.itcast.cnJBPM中主要(概念及实体)模型流程部署信息Deployment 流程定义ProcessDefinition 流程实例ProcessInstance及Execution 任务模型(Task) 活动(Activity) 转移(Transition)
  • 43. 成都传智播客 cd.itcast.cn流程部署信息模型Deployment(Entity)Deployment代表一个流程部署,当往系统中部署一个流程定义文件的时候,就会生成一个Deployment对象。 Deployment的属性: name:代表部署的名称; id:表示部署的id; state:状态,包括 STATE_ACTIVE(活动) 及 STATE_SUSPENDED(暂停)两种状态; timestamp:部署时间; 在实例应用JBPM开发工作流引擎应用的过程中,程序员一般是与ProcessDefinition打交道,ProcessDefinition代表流程的定义信息。
  • 44. 成都传智播客 cd.itcast.cn流程定义模型ProcessDefinition(VO)ProcessDefinition代表流程规则定义,当流程规则定义存储到数据库中后,我们取出来的每一个流程规则定义文件就被转化成一个ProcessDefinition实例。 每个流程定义包含下面四个重要的属性: name:代表定义的名称,可以包含空格等特殊字符; key:表示流程定义的标识,用于与其它流程进行区别开来; version:在部署流程的时候,可以指定一个版本号,如果不指定则系统会自动增加(从1开始);使用版本号来区分部署到系统中同一流程; id:这是流程的唯一标识,由key-version组成; ProcessDefinition的其它属性 deploymentId:流程部署信息Id description:备注 imageResourceName:流程图片资源名称 suspended:暂停
  • 45. 成都传智播客 cd.itcast.cn流程实例ProcessInstance(VO)流程实例的概念 流程实例是指一个根据指定流程定义来产生的一条流程具体信息;比如在请假流程中,当张三去填请假单,并在根据请假流程预设好的规则进行流转,就是一个流程实例; 在JBPM4中,流程实例下面单流程包含一个Execution,并发流程包含多个Execution。 在JBPM4中,ProcessInstance继承自Execution;
  • 46. 成都传智播客 cd.itcast.cnExecution(Entity)流程实例的基类,代表正在执行的一个流程或子流程; Execution的状态 STATE_ACTIVE_CONCURREN、STATE_ACTIVE_ROOT 、STATE_ASYNC 、STATE_CREATED 、STATE_ENDED 、STATE_SUSPENDED 等等 流程实例Execution接口的主要方法 getId():唯一id号,每一个Execution都有一个id; getKey():Execution的key,根据ProcessDefinition来决定; getName():Execution的名称 getState():状态信息 getProcessDefinitionId():与当前Execution对应的 ProcessDefinitionID isEnded() :是否已经结束; isSuspended() :是否暂停; isActive(String activityName):指定的name的Activity是否处理活动状态
  • 47. 成都传智播客 cd.itcast.cn任务Task(Entity)Task任务的概念 当一个流程实例产生以后,流程中的一些步骤需要用户进行处理,在jbpm中通过任务来表示这种由用户处理的活动; 任务Task接口的主要属性: id:任务id,每一个任务都有唯一的id; name:任务名称; activityName:任务对应的活动名称,如果没有活动,则为null; assignee:任务接收人; createTime:任务创建时间; description:任务描述; duedate:任务超期时间; executionId:任务关联Execution或ProcessInstance的id值; formResourceName:任务对应的表单地址,可以通过该地址让用户操作相关界面; priority :优先级 progress:任务进度;
  • 48. 成都传智播客 cd.itcast.cn转移Transition(VO)转移描述了两个点之间的顺序及流向关系; 一个节点可以有多个转移,转移到不同的节点。 JBPM中使用Transition接口代表转移; 每个Transition包括一个转移的目标,可以通过getDestination()方法得到; 每个 Transition包括一个来源,通过 getSource() 方法获得; 每个 Transition可以指定一个名称,没有名称的Transition为默认Transition,如果一个节点或 Activity中只包含一个Transition,则可以不用指定名称;可以通过Transition的getName()方法获得 Transition的名称。 通过调用Activity的方法可以得到Transition实例;
  • 49. 成都传智播客 cd.itcast.cn活动Activity(VO)活动Activity用来代表流程中的一个步骤; 每个活动Activity中都可以包含多个入口及出口transitions; 活动Activity接口的主要方法: getDefaultOutgoingTransition():获得活动的默认出口连接,就是没有名称的Transition; getIncomingTransitions():活动的入口连接; getType():获得活动的类型; getName():获得活动名称; getOutgoingTransition(java.lang.String transitionName) ,获得活动出口连接; getOutgoingTransitions() ,获得所有出口连接; 如何获得一个Activity对象? 通过Task的getExecution()得到OpenExecution对象 OpenExecution的 getActivity() 方法可以返回当前流程实例当前的活动的Activity;
  • 50. 成都传智播客 cd.itcast.cn第一个工作流Web项目工作: 综合之前介绍的Jbpm4核心Service API的使用和测试案例,完成一个简单的基于Jbpm4的工作流Web项目。 项目结构: 可直接使用Servlet+JSP+Jbpm4完成。 目标: 通过该项目,加深对Jbpm4核心Service API的使用,更深入的体会Jbpm4的作用和执行流程。
  • 51. 成都传智播客 cd.itcast.cn第一个工作流Web项目项目功能: 流程定义管理 发布简单的流程定义 所有已经发布的流程定义列表 删除已经发布的流程定义 查看流程定义的流程图 启动一个流程实例 流程实例管理 所有活动的流程实例列表 查看流程实例的流程图 可直接推进处于等待的流程实例
  • 52. 成都传智播客 cd.itcast.cn第一个工作流Web项目项目功能: 任务管理 一个模拟的登录界面和登录过程 登录用户可查看自己的任务列表 登录用户可完成某一个任务 登录用户可查看任务对应的流程图 历史管理 可查看某一个流程定义对应的所有流程实例列表 可查看某一个流程实例下的所有活动列表
  • 53. 成都传智播客 cd.itcast.cnjBPM4流程定义语言在本节中,会对jPDL的每一个元素进行详细的介绍和测试。在介绍和测试中,加深对jPDL已经Service API的理解,加深对Jbpm核心对象理解。并在完成本节学习后,能独立的进行更为复杂的基于jBPM4的项目应用。
  • 54. 成都传智播客 cd.itcast.cn一个典型的jPDL文件
  • 55. 成都传智播客 cd.itcast.cn是流程定义的根节点,用来定义一个流程 的属性 属性类型默认值是否必须描述name文本必须定义流程的名称key可选用来辨别流程定义,对同一流程定义的不同版本,key-name必须一致version整形可选流程的版本号的子元素元素个数描述description0..1流程的描述activities1..*流程的活动,至少有一个start活动
  • 56. 成都传智播客 cd.itcast.cn流转控制活动(Activities)一个流程在启动后,需要利用各种活动的组成,来控制流程中的并行,串行,分支-聚合,条件判断等。 在jBPM中定义的活动有: start:开始活动 state:状态活动 decision:判断活动 fork-join:分支-聚合活动 end:结束活动 task:人工任务活动 sub-process:子流程活动 custom:自定义活动
  • 57. 成都传智播客 cd.itcast.cn标识了一个流程实例从哪里开始。一个流程至少有一个start节点。开始节点必须有一个流出节点,该流向在流程实例启动后执行。 除了节点,一个流程只能有一个节点。 的属性 属性类型默认值是否必须描述name文本可选定义开始活动的名称的子元素元素个数描述transition1流出转向
  • 58. 成都传智播客 cd.itcast.cn,状态活动节点标识了一种等待状态。当流程到达等待状态后,流程会进入挂起状态,直到外部的干预让流程继续执行下去。 的属性 属性类型默认值是否必须描述name文本可选定义状态活动的名称的子元素元素个数描述transition1..*流出转向
  • 59. 成都传智播客 cd.itcast.cn序列化的state链: 测试过程: //启动流程实例,流程停留在state1上 ExecutionService es=JbpmUtil.getProcessEngine().getExecutionService(); ProcessInstance pi=es.startProcessInstanceByKey("state"); Execution state1=pi.findActiveExecutionIn("state1"); //外部"干预",流程向下执行到state2 pi=es.signalExecutionById(state1.getId()); Execution state2=pi.findActiveExecutionIn("state2"); //外部"干预",流程向下执行到state3 pi=es.signalExecutionById(state2.getId()); Execution state3=pi.findActiveExecutionIn("state3");
  • 60. 成都传智播客 cd.itcast.cn使用state选择路径: 测试代码: //创建流程实例,流程decide处等待 ExecutionService es=JbpmUtil.getProcessEngine().getExecutionService(); ProcessInstance pi=es.startProcessInstanceByKey("state2"); //外部"干预",让流程通过goout2转移到out2处等待 pi=es.signalExecutionById(decide.getId(), "goout2");
  • 61. 成都传智播客 cd.itcast.cn,判断活动节点标识了一种判断。该活动可以根据一种选择条件从多个流转路径中选择一条。 可以拥有多个流出转移,当流程实例到达decision后,会根据最先匹配成功的一个条件自动选择流出转移。 如果没有任何一个匹配项,并且没有配置任何默认流出转移,则抛出错误。 设置判断条件: 使用节点判断 使用节点的expression属性判断 使用Decision handler判断 思考:使用都可以完成根据某个条件判断流程流向。区别?
  • 62. 成都传智播客 cd.itcast.cn使用判断 属性类型默认值是否必须描述expr表达式文本必须定义条件转移的表达式lang表达式语言juEL可选定义条件转移的表达式的语言类型注意:只有当transition的表达式值为true,或者没有的transition,流程立刻流转到该transition。
  • 63. 成都传智播客 cd.itcast.cn使用节点的expression属性判断 属性类型默认值是否必须描述expr表达式文本必须定义条件转移的表达式lang表达式语言juEL可选定义条件转移的表达式的语言类型思考:如果没有指定的流转,会怎样?能设置一个默认的流转么?
  • 64. 成都传智播客 cd.itcast.cn使用Decision handler判断:如果应用在做判断的时候需要做复杂的逻辑运算或者需要借助于其他系统的决策,可以通过decision handler的方式使用java代码自行处理。 实现DecisionHandler接口: public interface DecisionHandler{ //该方法要求返回一个判定成功的流转名称 String decide(OpenExecution execution); } 配置在下的中:
  • 65. 成都传智播客 cd.itcast.cn使用Decision handler判断 public class Decision3Handler implements DecisionHandler { private static final long serialVersionUID = 1L; public String decide(OpenExecution execution) { Integer value = (Integer) execution.getVariable("value"); if (value < 10)return "lt"; if (value == 10)return "eq"; if (value > 10)return "gt"; return "default"; } }
  • 66. 成都传智播客 cd.itcast.cn-用来处理流程的并发执行。 活动使流程在一条主干上出现并行的分支。 活动可以使流程的并行分支聚合成一条主干。 共有的属性:属性类型默认值是否必须描述name文本可选定义开始活动的名称元素个数描述transition1流出转向共有的元素
  • 67. 成都传智播客 cd.itcast.cn特有的属性属性类型默认值是否必须描述multiplicity整数或表达式传入转移的数目可选流程执行中,当指定的流入转移数量到达join活动后,流程即会聚合,沿着join活动的唯一流出转移继续执行流转。其他未到达的流入转移则被忽略。从而实现按流入转移数量聚合的场景。lockmode{none, read, upgrade, upgrade_nowait, write}upgrade可选hibernate的锁定模式,应用在上级执行, 来防止两个还没到达join的同步事务互相锁定对方资源, 导致死锁。
  • 68. 成都传智播客 cd.itcast.cn-
  • 69. 成都传智播客 cd.itcast.cn-测试代码: //启动流程实例,流程直接进入两个分支流程中 ExecutionService es=JbpmUtil.getProcessEngine().getExecutionService(); ProcessInstance pi=es.startProcessInstanceByKey("forkjoin1"); //推动state2活动到join活动等待,目前pi中还有state1所处流程还在等待中 Execution state2=pi.findActiveExecutionIn("state2"); pi=es.signalExecutionById(state2.getId()); //推动state1活动到state3活动等待,目前pi中还有state2所处流程还在等待中 Execution state1=pi.findActiveExecutionIn("state1"); pi=es.signalExecutionById(state1.getId()); //推动state3活动,join活动得到两个分支流程都执行完后,流程到state4等待 Execution state3=pi.findActiveExecutionIn("state3"); pi=es.signalExecutionById(state3.getId()); //推动state4活动,流程执行完毕 Execution state4=pi.findActiveExecutionIn("state4"); pi=es.signalExecutionById(state4.getId());
  • 70. 成都传智播客 cd.itcast.cn,默认情况下,end活动会终结流程。并且到达end活动的流程实例中所有并发活动的流程都会终止。可以通过设置ends="execution",来终结这种情况 属性类型默认值是否必须描述ends{processinstance,execution}processinstance可选执行到达end活动时,整个流程实例会被完全结束stateString可选用来自定义流程实例的状态name文本必填定义结束活动的名称
  • 71. 成都传智播客 cd.itcast.cnjBPM允许同时存在多个活动 //指定流程通过500流转到internal server error结束节点 ProcessInstance pi=es.startProcessInstanceByKey("end2"); pi=es.signalExecutionById(pi.getId(),"500");
  • 72. 成都传智播客 cd.itcast.cnjBPM允许同时存在多个活动 //指定流程通过500流转到internal server error结束节点ProcessInstance pi=es.startProcessInstanceByKey("end3"); pi=es.signalExecutionById(pi.getId(),"500"); //可以通过processInstance.getState()方法得到指定的state值。 //end-cancel指定的state为cancel,end-error指定的state为error Assert.assertEquals("error", pi.getState());
  • 73. 成都传智播客 cd.itcast.cn:任务活动主要用来处理需要人工参与的活动,比如填写表单,录入,审核单据等。 在Task活动中,主要会关心以下一些内容: 任务的分配者 任务候选者 任务分配处理器 任务泳道 任务变量 在任务中使用邮件提醒 任务表单
  • 74. 成都传智播客 cd.itcast.cn任务的分配者:使用assignee将一个任务分配给指定用户属性类型默认值是否必须描述assignee表达式或文本可选任务被分配到用户的id Map vars=new HashMap(); vars.put("taker","user"); //启动流程实例,并为流程注入变量。在变量中指定将任务分配给user这个用户 JbpmUtil.getProcessEngine().getExecutionService().startProcessInstanceByKey("task1", vars); //找到user用户所有分配到的任务 List userTasks=JbpmUtil.getProcessEngine().getTaskService().findPersonalTasks("user"); Assert.assertEquals("task",userTasks.get(0).getActivityName());
  • 75. 成都传智播客 cd.itcast.cn中的任务候选者将任务分配给一组候选用户,组中的每一个用户都有权利接受并完成任务。通过candidate-groups或candidate-users来指派一个任务的候选者。属性类型默认值是否必须描述candidate-groups表达式或文本可选使用逗号分隔的用户组ID列表。所有指定用户组中的用户都成为任务的候选者candidate-users表达式或文本可选使用逗号分隔的用户ID列表。所有指定ID的用户都成为任务的候选者jpdl:
  • 76. 成都传智播客 cd.itcast.cn中的任务候选者关键代码: //启动流程实例,流程到达任务活动 JbpmUtil.getProcessEngine().getExecutionService().startProcessInstanceByKey("task2"); //使用IdentityService(身份认证服务)创建用户,用户组以及用户和用户组之间的关系 IdentityService is=JbpmUtil.getProcessEngine().getIdentityService(); //创建用户user1 is.createUser("user1", "cd","itcast"); //创建用户组userGroup is.createGroup("userGroup"); //将user1用户添加到userGroup中 is.createMembership("user1","userGroup"); TaskService ts=JbpmUtil.getProcessEngine().getTaskService(); //使用TaskService的findGroupTasks方法可以得到用户所有的可选任务 List userTasks1=ts.findGroupTasks("user1"); //用户接受任务 ts.takeTask(userTasks1.get(0).getId(), "user1"); //用户可以通过TaskService的findPersonalTasks方法找到已经指派给自己的任务 List userTask1=ts.findPersonalTasks("user1"); ts.completeTask(userTask1.get(0).getId());
  • 77. 成都传智播客 cd.itcast.cnIdentityService简介jBPM通过IdentityService实现了一个最基本的身份认证和组织模型管理。在jBPM系统中,默认只提供了两个相关模型: User:jBPM中的用户模型 Group:jBPM中的用户组模型 IdentityService的关键方法: void createUser(String userId,String givenName,String familyName):创建一个用户,分别指定用户ID,用户名,和familyName void createGroup(String groupId):创建一个用户组,只需要一个组ID void createMemberShip(String userId,String groupId):绑定用户和组的关系 void deleteUser(String userId):删除一个用户 void deleteGroup(String groupId):删除一个用户组 void deleteMembership(String userId,String groupId,String role):取消一个用户和用户组之间的绑定关系。role参数可以为null。
  • 78. 成都传智播客 cd.itcast.cnIdentityService简介使用jBPM4默认身份服务产生的数据表ER:
  • 79. 成都传智播客 cd.itcast.cn中的任务分配处理器如果需要在任务分配或者用户接受任务过程中加入自定义业务或者需要借助外部业务系统的数据或者逻辑,需要使用任务分配处理器。实现AssignmentHandler接口并配置给task活动。 AssignmentHandler接口: public interface AssignmentHandler extends Serializable { //其中,assignable是一个可被指派的对象接口,execution是执行活动上下文 void assign(Assignable assignable, OpenExecution execution) throws Exception; } 配置设置: ... ...
  • 80. 成都传智播客 cd.itcast.cn中的任务分配处理器 public class MyAssignmentHandler implements AssignmentHandler { public void assign(Assignable assignable, OpenExecution execution)throws Exception { //通过execution对象得到流程变量 Integer order=(Integer)execution.getVariable("order"); //根据流程变量的值直接设置任务接受人 if(order>1000) assignable.setAssignee("admin"); else assignable.setAssignee("manager"); } } //使用一个流程变量启动流程实例,为自定义任务分配器设置判断值 JbpmUtil.getProcessEngine().getExecutionService().startProcessInstanceByKey("task3",vars); //断定任务分配给了特定的用户 List tasks=JbpmUtil.getProcessEngine().getTaskService().findPersonalTasks(assignee);
  • 81. 成都传智播客 cd.itcast.cn中的任务泳道什么是泳道:在流程中,往往存在多个任务同时属于某一类用户执行,泳道用来规划这些不同类型的用户群。
  • 82. 成都传智播客 cd.itcast.cn中的任务泳道在jBPM4中,可以使用来定义一些泳道,并通过活动的swimlane属性为task配置不同的泳道。属性类型默认值是否必须描述swimlane定义的泳道名称可选将任务归纳到某一个泳道上的swimlan属性属性类型默认值是否必须描述name字符串必需定义泳道的名称assignee表达式可选引用的单个用户的IDcandidate-groups 表达式或文本可选 使用逗号分隔的用户组ID列表。所有指定用户组中的用户都成为任务的候选者candidate-users 表达式或文本 可选使用逗号分隔的用户ID列表。所有指定ID的用户都成为任务的候选者标签的属性
  • 83. 成都传智播客 cd.itcast.cn中的任务泳道
  • 84. 成都传智播客 cd.itcast.cn中的任务泳道//开始流程实例,进入到第一个任务项 ProcessInstance pi = jbpmUtil.getProcessEngine().getExecutionService().startProcessInstanceByKey("task4"); TaskService ts = JbpmUtil.getProcessEngine().getTaskService(); //userGroup的用户都可以接受第一个任务 List tasks = ts.findGroupTasks("user1"); //使用user1接受任务 ts.takeTask(tasks.get(0).getId(), "user1"); ts.completeTask(tasks.get(0).getId()); //manager完成第二个任务 List mtasks = ts.findPersonalTasks("manager"); ts.completeTask(mtasks.get(0).getId()); //第三个任务,由于和第一个任务是同时存在一个泳道里面的,所以默认将任务3指派给了user1 List utasks = ts.findPersonalTasks("user1"); Assert.assertEquals("领款", utasks.get(0).getActivityName());注意:在一个流程实例中,一旦用户接受任务,那么在同一个泳道中定义的任务自动固化指派给该用户。
  • 85. 成都传智播客 cd.itcast.cn中的任务变量任务变量主要是用来记录或者保存和任务相关的任务表单数据,也是任务之间传递数据最好的方式。 获得任务变量: List taskList = taskService.findPersonalTasks("johndoe"); Task task = taskList.get(0); Set variableNames = taskService.getVariableNames(task.getDbid()); Map variables = taskService.getVariables(taskDbid, variableNames); 设置任务变量: variables = new HashMap(); variables.put("category", "small"); variables.put("lires", 923874893); taskService.setVariables(taskDbid, variables);
  • 86. 成都传智播客 cd.itcast.cn中的邮件提醒可以通过配置邮件提醒,在任务分配的时候提醒被分配者,或者在任务分配期间,定时发送邮件提醒。 标签中的notification和reminder元素元素个数描述reminder0..1根据指定的时间间隔发送提醒信息。 如果没有引用模板,也没有提供内部模板, mail会使用task-reminder名字的模板。notification0..1让一个任务被分配的时候发送一个提醒消息。 如果没有引用模板,也没有提供内部的模板, mail会使用task-notification名字的模板。
  • 87. 成都传智播客 cd.itcast.cn中的邮件提醒notification标签的属性属性类型默认值是否必须描述continue{sync | async | exclusive}sync可选指定以同步,异步或者独占模式发送邮件reminder标签的属性属性类型默认值是否必须描述duedate纯字符串或包含表达式必填提醒电子邮件在任务产生后延迟多少时间开始发送repeat纯字符串或包含表达式可选提醒电子邮件在每次发送提醒之间间隔的时间continue{sync | async | exclusive}sync可选指定以同步,异步或者独占模式发送邮件
  • 88. 成都传智播客 cd.itcast.cn中的邮件提醒一个简单的邮件提醒配置实例:
  • 89. 成都传智播客 cd.itcast.cn中的任务表单task活动是需要人工参与的,一般来说,在task任务中会提供用户录入,查看,分析的表单或者报表数据。可以通过使用form属性将表单绑定到task活动或者start活动上。 jBPM4并不执行表单,只是通过持久化表单,来达到活动和表单关联的目的。 通过task.getFormResourceName()得到活动对应的表单信息。 List tasks=ts.findPersonalTasks("user5"); String formPath=tasks.get(0).getFormResourceName();
  • 90. 成都传智播客 cd.itcast.cn代表子流程。当业务复杂到一定程度后,需要根据规则拆分成多个子流程。当主流程运行到子流程活动时,会创建一个子流程实例,等待其完成后,流程再流向主流程下一步。 活动的属性属性类型默认值是否必须描述sub-process-id字符串或表达式sub-process-key和sub-process-id选一流程定义的ID标识。sub-process-key字符串或表达式sub-process-key和sub-process-id选一流程的key标识。outcome表达式当sub-process活动的ransition元素有outcome-value时必填当子流程活动执行结束时执行的表达式。表达式中的值用来匹配流出转移中的outcome-value值。
  • 91. 成都传智播客 cd.itcast.cn活动的元素元素个数描述parameter-in0..*子流程输入参数。即在创建子流程实例时该传入该参数。parameter-out0..*子流程的输出参数。在子流程实例结束后,该参数返回到父流程实例中。
  • 92. 成都传智播客 cd.itcast.cn-元素的属性属性类型默认值是否必须描述subvar字符串必须被赋值的子流程变量名称var字符串var和expr选一该变量在父流程中的变量名称expr表达式var和expr选一在父流程环境中执行,得到的值作为值传入到子流程中lang字符串可选expr使用的脚本语言类型
  • 93. 成都传智播客 cd.itcast.cn-元素的属性属性类型默认值是否必须描述subvar字符串必须输出到父流程的变量名称var字符串var和expr选一该输出变量在子流程中的变量名称expr表达式var和expr选一在子流程环境中执行,得到的值作为值传入到父流程中lang字符串可选expr使用的脚本语言类型
  • 94. 成都传智播客 cd.itcast.cn-元素的元素元素个数描述outcome-value0..1outcome-value是一个值表达式。子流程活动结束时,如果某转移的outcome-value值与子流程的outcome值匹配,则父流程的下一步从此转移流出。 ...
  • 95. 成都传智播客 cd.itcast.cn主流程定义: 子流程定义:
  • 96. 成都传智播客 cd.itcast.cn可以通过cusom活动完全自定义一套活动行为,实现定制的活动逻辑。 自定义的活动需要实现ExternalActivityBehaviour接口,该接口定义了两个方法: //该方法定义了当流程实例执行到该活动时完成的逻辑。 //ActivityExecution是执行流程上下文。 void execute(ActivityExecution execution) throws Exception; //在流程实例得到执行信号离开此活动时执行该方法 void signal(ActivityExecution execution, String signalName, Map parameters) throws Exception; 配置:
  • 97. 成都传智播客 cd.itcast.cn自定义活动中两个关键的方法: execution.waitForSignal(): 等待一个执行信号使流程引擎进入signal方法的处理 execution.take(signalName): 使流程继续执行,进入下一个活动。
  • 98. 成都传智播客 cd.itcast.cn自由活动自由活动:在执行过程中完全无需人工干预编排好的程序。JBPM4支持的自由活动类型有: java:JAVA程序活动 script:脚本活动 hql:Hibernate查询活动 sql:SQL查询活动 mail:邮件活动
  • 99. 成都传智播客 cd.itcast.cnJAVA活动java活动可以指定一个JAVA类的方法,当流程执行到此活动时,便会自动执行此方法。 属性类型默认值是否必须描述class字符串class和expr选一该有包路径的完整java类。该类需要提供无参构造方法expr表达式class和expr选一表达式返回一个java类对象,该对象含有指定方法method字符串必须调用的方法名称var流程变量名字可选方法执行的结果保存到该流程变量名称元素个数描述field0..*在方法调用前给指定的类成员注入制定的值arg0..*给被调用的方法提供参数
  • 100. 成都传智播客 cd.itcast.cnJAVA活动 public class JavaActive { public Integer createValue(Integer seed){ Random r=new Random(); return r.nextInt(seed); } }
  • 101. 成都传智播客 cd.itcast.cnScript活动script活动可以定义一段EL表达式脚本,JBPM执行此活动时会解析这段脚本
  • 102. 成都传智播客 cd.itcast.cnScript活动
  • 103. 成都传智播客 cd.itcast.cnhql活动属性类型默认值是否必须描述unique{true|false}false可选如果该值为true,在查询结果上调用uniqueResult(),否则使用list()var流程变量名字可选HQL执行的结果保存到该流程变量名称hql活动可以直接使用HQL查询,并将返回的结果保存到流程变量中 元素个数描述query1HQL查询语句parameter0..*HQL查询语句的参数
  • 104. 成都传智播客 cd.itcast.cnhql活动 SELECT COUNT(t) FROM org.jbpm.pvm.internal.task.TaskImpl t WHERE t.assignee = :assignee
  • 105. 成都传智播客 cd.itcast.cnsql活动属性类型默认值是否必须描述unique{true|false}false可选如果该值为true,在查询结果上调用uniqueResult(),否则使用list()var流程变量名字可选SQL执行的结果保存到该流程变量名称sql活动可以直接使用SQL查询,并将返回的结果保存到流程变量中 元素个数描述query1SQL查询语句parameter0..*SQL查询语句的参数
  • 106. 成都传智播客 cd.itcast.cnsql活动 SELECT t.DBID_ FROM JBPM4_TASKl t WHERE t.assignee = :assignee
  • 107. 成都传智播客 cd.itcast.cnjBPM中的事件监听jBPM中的事件用来定位流程执行过程中特定的时间点。可以在事件点上定义一系列的监听器,当流程执行通过这些点的时候,会自动执行监听器中的逻辑。 事件监听器需要实现EventListener接口: public interface EventListener extends Serializable{ void notify(EventListenerExecution execution) throws Exception; } 所有的自由活动都可以作为事件的监听器 使用on元素为事件监听器分组并指定事件。on元素可以作为process元素或process元素下的任何流程活动的子元素。属性类型默认值是否必须描述event{start|end}必须事件的名称
  • 108. 成都传智播客 cd.itcast.cnjBPM中的事件监听event-listener元素可直接作为transition元素子元素,监听转移的执行事件。 on元素的子元素元素个数描述event-listener0..*自定义事件监听器自动活动0..*使用自动活动作为事件的监听器属性类型默认值是否必须描述propagationenabled|disableddisabled可选指定该事件监听器是否支持被传播的事件调用(即是否监听子元素对应事件)continuesync|async|exclusivesync可选指定事件监听器是否异步执行事件监听器的属性
  • 109. 成都传智播客 cd.itcast.cnjBPM中的事件监听
  • 110. 成都传智播客 cd.itcast.cnjBPM中的事件监听
  • 111. 成都传智播客 cd.itcast.cnjBPM中的事件监听public class LogListener implements org.jbpm.api.listener.EventListener { private static final long serialVersionUID = 1L; private String msg; @Override public void notify(EventListenerExecution execution) throws Exception { List logs = (List) execution.getVariable("logs"); if(logs==null){ logs=new ArrayList(); execution.setVariable("logs",logs); } logs.add(msg); } }
  • 112. 成都传智播客 cd.itcast.cn事件的传播 public class LogListener2 implements EventListener { private static final long serialVersionUID = 1L; public void notify(EventListenerExecution execution) throws Exception { List logs = (List) execution.getVariable("logs"); if(logs==null){ logs=new ArrayList(); execution.setVariable("logs",logs); } logs.add(((ExecutionImpl)execution).getActivityName()+" start"); } }
  • 113. 成都传智播客 cd.itcast.cn异步执行默认情况下,jBPM的流程执行都是同步的,直到流程实例到达一个等待的状态。 如果在两个等待流程之间执行的自动活动组群时间过长,或者不需要等待自动活动而直接执行下一个活动,可以使用异步执行流程。 所有的活动都支持异步属性:属性类型默认值是否必须描述continuesync|async|exclusivesync可选指定活动是否异步执行
  • 114. 成都传智播客 cd.itcast.cn异步执行默认情况下,jBPM的流程执行都是同步的,直到流程实例到达一个等待的状态。 如果在两个等待流程之间执行的自动活动组群时间过长,或者不需要等待自动活动而直接执行下一个活动,可以使用异步执行流程。 所有的活动都支持异步属性:属性类型默认值是否必须描述continuesync|async|exclusivesync可选指定活动是否异步执行
  • 115. 成都传智播客 cd.itcast.cn异步执行sync:同步执行,使用当前事务。 async:启动异步执行。当前事务自动提交,活动在一个新事物中执行。jBPM使用异步消息机制通知流程异步执行的完成(Job)。 exclusive:启动独占模式的异步执行。当前事务提交,活动在一个新事务中执行。jBPM使用异步消息机制通知流程异步执行的完成。特别的,jBPM会为每个异步消息启动一个新的事务,确保异步消息的独占性。
  • 116. 成都传智播客 cd.itcast.cn异步执行
  • 117. 成都传智播客 cd.itcast.cn异步执行 public class LongWork{ public void work1() throws Exception{ System.out.println("long work1 start"); Thread.sleep(3000); System.out.println("long work1 end"); } public void work2() throws Exception{ System.out.println("long work2 start"); Thread.sleep(3000); System.out.println("long work2 end"); } }