一、知识点分类
JBPM4_DEPLOYMENT 流程定义表@b@JBPM4_DEPLOYPROP 流程定义属性表@b@JBPM4_EXECUTION 流程实例表@b@JBPM4_HIST_ACTINST 流程活动( 节点) 实例表@b@JBPM4_HIST_DETAIL 流程历史详细表@b@JBPM4_HIST_PROCINST 流程实例历史表@b@JBPM4_HIST_TASK 流程任务实例历史表@b@JBPM4_HIST_VAR 流程变量( 上下文) 历史表@b@JBPM4_ID_GROUP 组表@b@JBPM4_ID_MEMBERSHIP 用户角色表@b@JBPM4_ID_USER 用户表@b@JBPM4_JOB 定时表@b@JBPM4_LOB 存储表 存放流程定义的xml和png图片文件@b@JBPM4_PARTICIPATION 参与者表@b@JBPM4_SWIMLANE 泳道表@b@JBPM4_TASK 任务表@b@JBPM4_VARIABLE 上下文表
2)工作流的基本思路
2.1 、描述工作流@b@2.2 、发布和存储工作流@b@2.3 、装载和解析工作流@b@2.4 、顶层对象:流程、活动、转移@b@2.5 、流程定义和流程实例@b@2.6 、活动定义和活动实例@b@2.7 、令牌驱动,petri网@b@2.8 、转移:隐式、显示、fork(分支)、join、按条件等等@b@2.9 、活动:人工活动、自动活动等@b@2.10、人工活动会涉及:活动的处理页面、活动的数据@b@2.11、workList:活动的列表、接收、拒收、重分配、活动的响应等
3)jBPM有什么,简介jBPM的Service API
1:ProcessEngine:流程引擎。并不负责具体的业务,而是用于获取各种Service。@b@2:RepositoryService:流程资源服务的接口,如流程定义发布、查询、删除等。@b@{@b@ 在流程仓库里包含部署管理、@b@}@b@3:ExecutioService:用于操作流程实例的服务,可以进行流程实例发布、查询、流程推进、设置流程变量等操作。@b@4:TaskService:用于操作人工任务的服务,可以进行任务创建、查询、获取、提交完成、保存、删除等操作。@b@5:HistoryService:用于操作流程历史的服务,提供对流程历史库(就是已经完成的流程实例)的操作。比如:历史流程实例,历史活动实例等。@b@6:IdentityService:用于操作用户、用户组以及成员关系的服务@b@7:ManagementService:流程管理控制服务的接口,只提供异步工作(Job)相关的执行和查询操作。
4)jPDL基础--1
jPDL(JBoss jBPM Process Definition Language)是构建于jBPM框架上的流程语言之一。在jPDL中提供了任务(tasks)、待@b@处理状态(wait states)、计时器(timers)、自动处理(automated@b@actions)…等术语,并通过图型化的流程定义,很直观地描述业务流程。@b@n 流程定义(ProcessDefinition)@b@就是对一个流程抽象的对象化定义。一套系统中,用户可以定义并保存多@b@个流程定义实体,如:报销流程定义、请假流程定义、人事录用流程定义等。@b@n 流程节点@b@是对流程中的过程环节/行为的抽象对象化定义。结点有两个主要职责:@b@一,实现某个指定行为,这在jBPM中就是执行一段制定的Java代码;二,传递、@b@维持流程的延续,直至达到最终结点。@b@流程实例(ProcessInstance)@b@流程实例是流程定义的运行时状态,它记录了一个流程运行的起始时间、@b@结束时间等状态信息。@b@n 任务实例(Task)@b@用来描述一个任务实例对象,可以分配给指定的操作者处理,当任务完成@b@后,将触发流程继续向下流转。任务实例的生命周期很简单,生成实例-->处理-->任务结束。
二、流程代码说明
1)流程发布
//如果是读取默认的jbpm.cfg.xml文件 2 ProcessEngine engine = Configuration.getProcessEngine(); @b@ //如果不是读取默认的jbpm.cfg.xml文件 4 ProcessEngine engine = new Configuration() @b@ .setResource("ccjbpm.cfg.xml") @b@ .buildProcessEngine(); @b@ RepositoryService repositoryService = processEngine.getRepositoryService(); @b@ repositoryService.createDeployment() @b@ .addResourceFromClasspath("cn/javass/jbpm4/hello/hello.jpdl.xml") @b@ .deploy();
2)流程定义
ProcessEngine processEngine = Configuration.getProcessEngine(); @b@ RepositoryService repositoryService = processEngine.getRepositoryService(); @b@ List<ProcessDefinition> pdList = repositoryService.createProcessDefinitionQuery().list(); @b@ for (ProcessDefinition pd:pdList){ @b@ System.out.println("id:"+pd.getId()); @b@ System.out.println("name:"+pd.getName()); @b@ System.out.println("version:"+pd.getVersion()); @b@ System.out.println("deploymentId:"+pd.getDeploymentId()); @b@ System.out.println("---------------"); @b@}
3)启动实例
ProcessEngine processEngine = Configuration.getProcessEngine(); @b@ExecutionService executionService = processEngine.getExecutionService(); @b@Map map = new HashMap(); @b@map.put("pm","ProjectManager"); @b@map.put("dm", "DepartmentManager "); @b@map.put("ceo", "Manager"); @b@executionService.startProcessInstanceByKey("MyProcess",map);
4)检索流程实例
ProcessEngine processEngine = Configuration.getProcessEngine(); @b@ExecutionService executionService = processEngine.getExecutionService(); @b@List<ProcessInstance> piList = executionService.createProcessInstanceQuery().list(); @b@for (ProcessInstance pi : piList) { @b@System.out.println("id:"+pi.getId()); @b@System.out.println("activeActivityNames:“+pi.findActiveActivityNames()); @b@System.out.println("state:"+pi.getState()); @b@System.out.println("-----------------");
5)检索出Task
ProcessEngine processEngine = Configuration.getProcessEngine(); @b@TaskService taskService = processEngine.getTaskService(); @b@List<Task> list = taskService.createTaskQuery().list(); @b@for(Task t : list){ @b@ System.out.println("activityName="+t.getActivityName()+",user=" @b@ +t.getAssignee()+",id="+t.getId()); @b@}
6) 完成task
ProcessEngine processEngine = Configuration.getProcessEngine(); @b@TaskService taskService = processEngine.getTaskService(); @b@String taskId = “70003”;//这个是流程运行中生成的任务id @b@Map map = new HashMap(); @b@map.put("dmResult", 1); @b@map.put("days", 15); @b@taskService.completeTask(taskId,map);
7) 历史的流程实例
ProcessEngine engine = Configuration.getProcessEngine(); @b@HistoryService hs = engine.getHistoryService(); @b@List<HistoryProcessInstance> list = hs.createHistoryProcessInstanceQuery().list(); @b@for(HistoryProcessInstance hpi : list){ @b@ System.out.println("state="+hpi.getState()+" ,pdid=“+hpi.getProcessDefinitionId()+ @b@ ",piid="+hpi.getProcessInstanceId()+",startTime="+hpi.getStartTime()); @b@ }
三、流程描述
1)start(流程开始) 用于描述流程的开始节点,即流程从哪里开始,包含子节点transition,用来描述流程开始后的去向
2) end(流程结束) 用于描述该流程已经结束,包含子节点end-cancel和end-error表示流程结束原因
3)state(流程状态) 描述流程正处于等待外界的调用,与task不同的是他不会将任务分配给某个人 如果是同时只有单个state的情况,可以简单的使用: executionService.signalExecutionById(“这里默认使用流程实例的id"); 如果是同时有多个state的话,应该要先查找到Execution的id,如下使用:
ExecutionService exe = engine.getExecutionService(); @b@Execution e = exe.createProcessInstanceQuery() @b@ .processInstanceId(piid).uniqueResult() @b@ .findActiveExecutionIn(“state活动名称"); @b@exe.signalExecutionById(e.getId());
4) decision(决策) 用于判断其中每一个transition元素的转移条件,当遇到一个transition的condition值为true的时候,就流向这个transition,decision活动的expr属性是一个三目运算符用来判断是否流向这个transition,decision活动的handler子元素,通过实现decisionHandler接口来在代码中决定要走向那个流程
方法一
<decision name="evaluate document"> @b@ <handler class="org.jbpm.examples.decision.handler.ContentEvaluation" /> @b@ <transition name="good" to="submit document" /> @b@ <transition name="bad" to="try again" /> @b@ <transition name="ugly" to="give up" /> @b@ </decision>
public class ContentEvaluation implements DecisionHand @b@ public String decide(OpenExecution execution) { @b@ String content = (String) execution.getVariable("content"); @b@ if (content.equals("you're great")) { @b@ return "good"; @b@ } @b@ if (content.equals("you gotta improve")) { @b@ return "bad"; @b@ } @b@ return "ugly"; @b@ } @b@ }
方法二
<decision> @b@ <transition name="good" to="submit document" /> @b@ <transition name="bad" to="try again" /> @b@ <transition name="ugly" to="give up" /> @b@ </decision> @b@ @b@ Map<String, Object> variables = new HashMap<String, Object>(); @b@ variables.put("content", "good"); @b@ ProcessInstance processInstance = executionService.startProcessInstanceByKey("DecisionExpression", variables);
方法三
<decision name="evaluate document"> @b@ <transition to="submit document"> @b@ <condition expr="#{content=="good"}" /> @b@ </transition> @b@ <transition to="try again"> @b@ <condition expr="#{content=="not so good"}" /> @b@ </transition> @b@ <transition to="give up" /> @b@ </decision> @b@ @b@ Map<String, Object> variables = new HashMap<String, Object>(); @b@ variables.put("content", "good"); @b@ ProcessInstance processInstance = @b@executionService.startProcessInstanceByKey("DecisionConditions", variables);
5) task(任务)一般用来处理涉及人机交互的活动,流程引擎会停在这里等待人工的操作。assignee属性:用来指定任务分配给谁(可以用变量定义){
<task name="review" assignee="#{order.owner}" > 《或者assignee="johndoe"》 @b@ <transition to="wait" /> @b@ </task>
public class Order implements Serializable { @b@ @b@ String owner; @b@ @b@ public Order(String owner) { @b@ @b@ this.owner = owner; @b@ @b@ } @b@ @b@ public String getOwner() { @b@ @b@ return owner; @b@ @b@ } @b@ @b@ public void setOwner(String owner) { @b@ @b@ this.owner = owner; @b@ @b@ } @b@ @b@ } @b@ @b@ Map<String, Object> variables = new HashMap<String, Object>(); @b@ variables.put("order", new Order("johndoe")); @b@ @b@ ProcessInstance processInstance = executionService @b@ .startProcessInstanceByKey("TaskAssignee", variables); @b@ @b@ List<Task> taskList = taskService.findPersonalTasks("johndoe"); @b@ };
candidate-users属性:(可以用逗号分隔用户id列表)用来定义任务的候选人,用户想要接收这个任务需要人工的接受任务takeTask{
TaskService taskService = processEngine.getTaskService();@b@taskService.takeTask(“task的id”, “领取task的人员");
任务候选组candidate-groups:(类似于candidate-users){
<task name="review" candidate-groups="sales" > @b@ @b@ <transition to="wait" /> @b@ @b@ </task> @b@ @b@ IdentityService identityService = processEngine.getIdentityService(); @b@ identityService.createGroup("sales"); @b@ identityService.createUser(“zhang", “zhang", “san"); @b@ identityService.createUser(“li", “li", “si"); @b@ identityService.createMembership(“zhang", "sales"); @b@ identityService.createMembership(“li", "sales"); @b@ taskService.findGroupTasks("zhang"); @b@ taskService.findGroupTasks("li");
注意:为了防止同一个任务被一个分组中的多个人领取,需要将这个任务分配给指定的个人后才能开始执行任务,例如下面
taskService.takeTask(task.getDbid(), "zhang");
并且任务呗某一个用户领取之后,应该将该任务标识为已领取状态,以避免造成重复。
任务分配器AssignmentHandler:支持使用java代码来进行任务分配{
<task name="review" g="96,16,127,52"> @b@ <assignment-handler class="org.jbpm.examples.task.assignmenthandler.AssignTask"> @b@ @b@ <field name="assignee"> @b@ <string value="johndoe" /> @b@ </field> @b@ @b@ </assignment-handler> @b@ <transition to="wait" /> @b@ @b@ </task>
public class AssignTask implements AssignmentHandler{ @b@ @b@ private String name; @b@ @b@ public String getName() { @b@ @b@ return name; @b@ @b@ } @b@ @b@ public void setName(String name) { this.name = name; } @b@ @b@ public void assign(Assignable assignable, OpenExecution execution) @b@ @b@ throws Exception { @b@ @b@ assignable.setAssignee(name); @b@ @b@ } @b@ @b@ }
6) 并发(concurrency)包含join(合并分支)和fork(拆分分支)
7) java活动可以指定一个Java类的方法,当流程执行到此活动时,马上自动执行此Java方法。class属性用来指定此Java类的全类名,要注意这个类要有public无参的默认构造方法。method属性用来指定调用的方法。
var属性存储方法执行结果的流程变量名称。
<java g="246,135,92,52" name="java1" class="cn.javass.test.java.MyJava" @b@ method="sayHello" var="manager"> @b@ @b@ <field name="user1"><object expr="#{user1}"/></field> @b@ @b@ <field name="user2"><string value="user2"/></field> @b@ @b@ <arg><string value="xyz"/></arg> @b@ @b@ <arg><object expr="#{abc}"/></arg> @b@ @b@ <transition to="task1"/> @b@ @b@ </java>
public class MyJava{ @b@ @b@ private String user1; @b@ @b@ private String user2; @b@ @b@ …user1和user2的setter @b@ @b@ public String sayHello(String arg1,String arg2){ @b@ @b@ System.out.println("user1=="+user1); @b@ @b@ System.out.println("user2=="+user2); @b@ @b@ System.out.println("arg1=="+arg1); @b@ @b@ System.out.println("arg2=="+arg2); @b@ @b@ return “Hello"; @b@ @b@ } @b@ @b@ }
8)script活动可以指定一个表达式,当流程执行到此活动时,马上自动执行此表达式,默认用的是juEL
9)sql活动能够支持使用sql直接从数据库中查询数据,并将结果返回到流程变量中。Xml代码
<sql g="192,438,92,52" name="sql1" unique="true" var="sqlV"> @b@ <query> @b@ select * from tbl_user where uuid=:uuid @b@ </query> @b@ @b@ <parameters> @b@ <object name="uuid" expr="#{uuid}"></object> @b@ </parameters> @b@ @b@ <transition to="hql1"/> @b@ </sql>
10)hql活动能够支持使用hql直接从数据库中查询数据,并将结果返回到流程变量中。Xml代码
<hql name="hql1" g="404,457,92,52" unique="true" var="hqlV"> @b@ <query> @b@ select o from Parent o where o.id=:id @b@ </query> @b@ @b@ <parameters> @b@ <string name="id" value="22"/> @b@ </parameters> @b@ @b@ <transition to="task2"/> @b@ </hql>
<foreach name="foreach1" in="D1,D2,D3" var="nowDep"> @b@ <transition to="task5"/> @b@ </foreach> @b@ @b@ <task name="task5"> @b@ <transition to="join1"/> @b@ </task> @b@ @b@ <join name="join1" multiplicity="3"> @b@ <transition to="task6"/> @b@ </join>
11)foreach活动使得通过一条单独的流程路径来执行多条流程分支的功能in:将被迭代的集合。集合中的每个元素会生成一个新的同步分支。in执行任意类型的集合,数组和以逗号分隔的字符串。。var:用来保存集合中当前元素的变量。这个变量会设置到同步流程分支中,并且只对这个流程分支可见。
12)jBPM的事件机制使得我们可以很方便的在流程、活动、任务生命周期的各个阶段插入定制的代码逻辑,以便实现特定的业务逻辑操作。正是这种机制赋予了jBPM无限的可扩展性on活动:监听器在jpdl中可以被定为on活动。on活动的event属性{start|end}指明了监听器是在进入还是结束时触发<event-listener>、<java>、<sql>、<hql>等自动活动还可以作为<transition>元素的子元素,在流经这个<transition>的时候被执行。
<on event="start"> @b@ @b@ <event-listener class="org.jbpm.examples.eventlistener.LogListener"> @b@ <field name="msg"><string value="start on process definition"/></field> @b@ </event-listener> @b@ </on> @b@ @b@ <start> @b@ <transition to="wait"/> @b@ </start> @b@ @b@ <state name="wait"> @b@ <on event="start"> @b@ <event-listener class="org.jbpm.examples.eventlistener.LogListener"> @b@ <field name="msg"><string value="start on activity wait"/></field> @b@ </event-listener> @b@ </on> @b@ @b@ <on event="end"> @b@ <event-listener class="org.jbpm.examples.eventlistener.LogListener"> @b@ <field name="msg"><string value="end on activity wait"/></field> @b@ </event-listener> @b@ </on> @b@ @b@ <transition to="park"> @b@ <event-listener class="org.jbpm.examples.eventlistener.LogListener"> @b@ <field name="msg"><string value="take transition"/></field> @b@ </event-listener> @b@ </transition> @b@ @b@ </state>
public class MyEventListener implements EventListener{ @b@ @b@ public void notify(EventListenerExecution exection) throws Exception { @b@ @b@ System.out.println("走出Decistion"); @b@ @b@ } @b@ }
13)会签的概念1、概念:会签,又称会审,也就是流程中某个业务需要经过多人表决,并且根据表决意见的汇总结果,匹配设定的规则,决定流程的走向
另外:tomcat的配置:在将jBPM与web项目结合的时候,需要把jBPM资源包中的juel-engine.jar和juel-impl.jar添加到tomcat/lib下,同时在Web应用的lib下面,把juel-api.jar、juel-engine.jar和juel-impl.jar 删除掉