jBPM一(概念及管理控制流程)

    技术2022-05-20  46

    工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。

    通俗的说,流程就是多个人在一起合作完成某件事情的必要步骤,把步骤变成计算机能理解的形式就是工作流。

    工作流管理系统(WfMS,Workflow Management System)的主要功能是通过计算机技术的支持去定义、执行和管理工作流,协调工作流执行过程中,工作之间以及群体成员之间的信息交互。工作流需要依靠工作流管理系统来实现。工作流管理系统是定义、创建、执行工作流的系统,应能提供以下三个方面的功能支持:

    定义工作流:包括具体的活动、规则等 运行控制功能:在运行环境中管理工作流过程,对工作流过程中的活动进行调度 运行交互功能:指在工作流运行中,WfMS与用户(活动的参与者)及外部应用程序工具交互的功能。

    那么使用工作流管理系统有什么好处呢?

    提高系统的柔性,适应业务流程的变化. 实现更好的业务过程控制,提高顾客服务质量 降低系统开发和维护成本

    目前市面上主要的工作流框架有:Jbpm、OSWorkflow、ActiveBPEL、YAWL等.

    一个工作流管理系统往往分为两部分组成,定义工作流的时候,需要给用户提供一种简单清晰的方案,一般提供给一个"流程设计器"来帮助用户有效的制定流程.我们无法让计算机依客户的方案去执行这套流程,我们必须要使用计算机能够读得懂的语言.xml能够很好的描述数据之间的关系,jBPM就对xml提供了约束文档,称为JPDL(jBPM Process Definition Language).在客户制定流程的时候,要生成一张图片给客户看,还要生成一个xml文件给计算机看.因为我们不知道客户需要什么样的流程,而且流程要给客户自由管理,比如添加一个流程,或是删除一个流程,所以这是客户需要做的,这被称为表达业务流程.我们需要做的就是让工作流系统正确的工作,管理控制流程,大致上可以分为这个两部分:

    jBPM也是使用Hibernate对流程的数据进行存储,它将在数据库中创建18张表来管理不同的信息.如果数据库是Mysql,则方言一定要是MySQL5InnoDBDialect!

    在Eclipse中安装完插件(GPD)后,就能使用流程设计器了.

    在保存的时候将同步生成一个对应的xml文件.这个xml文件是最主要的文件.

    相关概念:

    Process definition---流程定义

    流程定义就是整个流程的一个描述.

    Process instance---流程实例

    一个流程实例包括了所有运行阶段, 其中最典型的属性就是跟踪当前节点的指针。它就是一个主线.

    Execution---执行

    一般情况下,一个流程实例是一个执行树的根节点, 当一个新的流程实例启动时,实际上流程实例就处于根节点的位置, 这时只有它的"子节点"才可以被激活。使用树状结构的原因在于, 这一概念只有一条执行路径, 使用起来更简单。 业务API不需要了解流程实例和执行之间功能的区别。 因此, API里只有一个执行类型来引用流程实例和执行。它相当于一个支线.

    ProcessEngine最核心的对象,就像Hibernate中的SessionFactory一样,做任何事情都要通过它.ProcessEngine提供了获取Service的方法,以下是获取Service的方式:

    RepositoryService repositoryService = processEngine.getRepositoryService();

    ExecutionService executionService = processEngine.getExecutionService();

    TaskService taskService = processEngine.getTaskService();

    HistoryService historyService = processEngine.getHistoryService();

    ManagementService managementService = processEngine.getManagementService();

    IdentityService identityService = processEngine.getIdentityService();

    各个Service的作用:

    RepositoryService

    管理流程定义

    ExecutionService

    执行管理,包括启动、推进、删除流程实例等操作

    TaskService

    任务管理

    HistoryService

    历史管理(执行完的数据管理)

    IdentityService

    jBPM的用户、组管理

    ManagementService

     

    有关查询的API:

    功能说明

    相应的查询API

    查询“流程定义”

    ProcessDefinitionQuery processDefinitionQuery =

    processEngine.getRepositoryService()

    .createProcessDefinitionQuery();

    查询“执行对象”

    (流程实例)

    ProcessInstanceQuery processInstanceQuery =

    processEngine.getExecutionService() //

    .createProcessInstanceQuery();

    查询“任务”

    TaskQuery taskQuery = //

    processEngine.getTaskService()//

    .createTaskQuery();

    查询“执行历史”

    (流程实例历史)

    HistoryProcessInstanceQuery historyProcessInstanceQuery =

    processEngine.getHistoryService()

    .createHistoryProcessInstanceQuery();

    查询“任务历史”

    HistoryTaskQuery historyTaskQuery =

    processEngine.getHistoryService()

    .createHistoryTaskQuery();

    jBPM的API风格都是方法调用链的形式.

    创建一个流程定义

    被添加的文件可以是一个文件:

    private ProcessEngine processEngine = Configuration.getProcessEngine();   // 部署(添加) // jbpm4_deployment, jbpm4_deployprop, jbpm4_lob @Test public void deploy() { String deploymentId = processEngine.getRepositoryService()// .createDeployment()// .addResourceFromClasspath("aa/aa.jpdl.xml")// 必须要有一个 .jpdl.xml 文件 .addResourceFromClasspath("aa/aa.png")// .deploy(); System.out.println("部署成功,deploymentId = " + deploymentId); }

    也可以是一组文件(Zip):

    /** * 创建一个流程定义 */ @Test public void createProcessDefinition() { //获取当前类路径下的文件 ZipInputStream in = new ZipInputStream(CRD.class.getClassLoader() .getResourceAsStream("JBPM.zip"));   processEngine.getRepositoryService()// .createDeployment()// .addResourcesFromZipInputStream(in)// .deploy(); }

    推荐使用Zip文件的形式.

    查询所有的流程定义

    // Deployment:一次部署的信息(包含多个文件)。 // ProcessDefinition(流程定义):是指解析xx.jpdl.xml后得到的流程信息。 @Test public void findAll() { // 查询 List list = processEngine.getRepositoryService()// .createProcessDefinitionQuery()// .list();   // 显示 for (ProcessDefinition pd : list) { System.out.println("id=" + pd.getId()// 格式为:{key}-{version} + ", name=" + pd.getName()// .jpdl.xml中根元素的name属性的值 + ", key=" + pd.getKey()// .jpdl.xml中根元素的key属性的值,如果没有指定,默认为name属性的值 。 + ", version=" + pd.getVersion()// 版本,默认是1,或自动累加。 + ", deploymentId=" + pd.getDeploymentId()); // 所属的Deployment记录的id } }

    jBPM不支持已经部署的流程定义,这也是不能提供的操作,试想几种情况之后就不能发现这是很明智的选择:如果当前有流程实例,原流程有5个步骤要去,走到一半,流程被修改成了7个步骤,中间的活动可能已经被改变了,那么就可能出现问题;或者走到了第4步的时候,流程被修改成了只有3步,那怎么办?所以不支持修改流程定义不仅没有对工作造成影响,还很大程度地保障了原先流程实例的正确执行,以及不对历史中的流程实例造成影响.

    只能重新部署一个流程,如果和已有的流程的名字有冲突,将自动把版本号加1,以视区别.在这种情况下,就要保证以后开始的流程实例都是最新的流程实例.

    查询所有最新版本的流程定义

    // OrderBy的属性名在ProcessDefinitionQuery中有常量的定义。 @Test public void findAllLatestVersions() { // 1,查询所有的流程定义 // 按version排序,以便让所有最大的版本都排在最后面 List allList = processEngine.getRepositoryService()// .createProcessDefinitionQuery()// .orderAsc(ProcessDefinitionQuery.PROPERTY_VERSION)// .list(); // 2,过滤出所需的最新版本流程定义的集合 Map map = new HashMap(); for (ProcessDefinition pd : allList) { // ProcessDefinition pdInMap = map.get(pd.getKey()); // if(pdInMap == null || pdInMap.getVersion() < pd.getVersion()){ // map.put(pd.getKey(), pd); // } map.put(pd.getKey(), pd); }   // 显示 for (ProcessDefinition pd : map.values()) { System.out.println("id=" + pd.getId()// 格式为:{key}-{version} + ", name=" + pd.getName()// .jpdl.xml中根元素的name属性的值 + ", key=" + pd.getKey()// .jpdl.xml中根元素的key属性的值,如果没有指定,默认为name属性的值 。 + ", version=" + pd.getVersion()// 版本,默认是1,或自动累加。 + ", deploymentId=" + pd.getDeploymentId()); // 所属的Deployment记录的id } }

    由于没有直接查询最新流程定义的语法,所以只能先全部查出,再进行筛选.上面的代码使用了两种方法,第一种(被注释的)每次都判断一下,以保证新的流程定义不被旧的覆盖;第二种在查询时增加了排序条件,保证新的流程定义都在后面,所以不用判断.

    删除一个Deployment

    @Test public void deleteById() { String deploymentId = "40001";   // // 删除一次部署的信息(删除相关的文件),如果有相关的运行信息,则报错 // processEngine.getRepositoryService().deleteDeployment(deploymentId);   // 删除一次部署的信息(删除相关的文件),会级联删除所有相关的运行信息 processEngine.getRepositoryService().deleteDeploymentCascade(deploymentId); }

    删除指定key的所有版本的流程定义(所属的Deployment)

    @Test public void deleteByKey() { // 1,查询出指定key的所有版本的流程定义 String key = "test"; List list = processEngine.getRepositoryService()// .createProcessDefinitionQuery()// .processDefinitionKey(key)// .list();   // 2,循环删除 for (ProcessDefinition pd : list) { processEngine.getRepositoryService().deleteDeploymentCascade(pd.getDeploymentId()); } }

    查看流程图

    @Test public void getProcessImage() throws Exception { String deploymentId = "60001"; String resourceName = "a/helloworld.png";   // 获取某Deployment中所有的文件资源的名称 Set set = processEngine.getRepositoryService().getResourceNames(deploymentId); for (String s : set) { System.out.println(s); }   // 获取某Deployment中某资源的InputStream(内容) InputStream in = processEngine.getRepositoryService().getResourceAsStream(deploymentId, resourceName); // 保存到 c盘 FileOutputStream out = new FileOutputStream("c:/processImage.png"); for (int b = -1; (b = in.read()) != -1;) { out.write(b); } in.close(); out.close(); }

    流程变量

    上面的流程在执行的时候,没有带任何有关受理人的信息以及意见,通常在流程执行的过程中,应该记录当前活动(Activity)的数据,比如同意的理由或者不同意的理由等,这些信息通过流程变量存进数据库.流程变量也是有作用域的,与流程实例的生命周期相同,流程变量可以在流程实例的各个活动中获取和设置,假设我现在有个请假的流程定义:

    它就是一个大大的Map,存入的流程变量都会被存入数据库中.流程变量的设置大致可以分为两种:

    顺便设置

    ExecutionService.startProcessInstanceByKey(processDefinitionId, variables);

    TaskService.completeTask(taskId, variables);

    专门设置

    // 通过Execution设置一个流程变量ExecutionService.setVariable(executionId, name, value);// 通过Execution设置多个流程变量ExecutionService.setVariables(executionId, variables)// 通过Task设置多个流程变量processEngine.getTaskService().setVariables(taskId, variables);

    不管是以何种方式设置,如果是以给定taskId,它将会根据taskId找到当前的execution,然后才设置.对应的获取也有两种方式:

    // 通过Execution获取流程变量的信息ExecutionService.getVariable(executionId, variableName);ExecutionService.getVariableNames(executionId);ExecutionService.getVariables(executionId, variableNames);// 通过Task获取流程变量的信息TaskService.getVariable(taskId, variableName);TaskService.getVariableNames(taskId);TaskService.getVariables(taskId, variableNames);

    最后找到execution对应的流程变量.

    总结一下一个工作流系统的工作流程:

    申请模板可以自由定制。申请模板对应的流程(步骤)可以自由定制。让文件或表单等按预定的步骤进行流转。

    第二步又可分为以下几步:

    要有流程设计器(画图):需要把所有规则整理清楚,并实现,最终是想能覆盖尽可能多的情况。设计完流程后,结果是:图片,给用户看的;xml,给计算机看的。

    最新回复(0)