Activiti工作流Day03-Activiti API

2021-04-08  本文已影响0人  攻城狮Chova

流程引擎的API和服务

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
FormService formService = processEngine.getFormService();
ProcessEngines.getDefaultProcessEngine():
            - 会在第一次调用时,初始化并创建一个流程引擎,以后再调用就会返回相同的流程引擎
            - 使用对应的方法可以创建和关闭所有流程引擎:ProcessEngines.init()和ProcessEngines.destroy()
            - ProcessEngines会扫描所有activiti.cfg.xml 和 activiti-context.xml 文件
            - 对于activiti.cfg.xml文件,流程引擎会使用Activiti的经典方式构建: 
                    - ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream).buildProcessEngine()
            - 对于activiti-context.xml文件,流程引擎会使用Spring方法构建:先创建一个Spring的环境,然后通过环境获得流程引擎
            - 所有服务都是无状态的.这意味着可以在多节点集群环境下运行Activiti,每个节点都指向同一个数据库,不用担心哪个机器实际执行前端的调用.无论在哪里执行服务都没有问题       
RepositoryService
            - 负责静态信息
            - 是使用Activiti引擎时最先接触的服务,提供了管理和控制发布包和流程定义的操作
            - 流程定义是BPMN 2.0流程的java实现.它包含了一个流程每个环节的结构和行为
            - 发布包是Activiti引擎的打包单位.一个发布包可以包含多个BPMN 2.0 xml文件和其他资源
                    - 开发者可以自由选择把任意资源包含到发布包中
                    - 既可以把一个单独的BPMN 2.0 xml文件放到发布包里,也可以把整个流程和相关资源都放在一起
                    - 可以通过RepositoryService来部署这种发布包.发布一个发布包,意味着把它上传到引擎中,所有流程都会在保存进数据库之前分析解析好
                    - 从这点来说,系统知道这个发布包的存在,发布包中包含的流程就已经可以启动了
            - RepositoryService可以查询引擎中的发布包和流程定义
            - RepositoryService暂停或激活发布包,对应全部和特定流程定义.暂停意味着它们不能再执行任何操作了,激活是对应的反向操作
            - RepositoryService获得多种资源,例如包含在发布包里的文件,引擎自动生成的流程图
            - RepositoryService获得流程定义的pojo版本,可以用来通过java解析流程,而不必通过xml
RuntimeService
            - 负责启动一个流程定义的新实例
                    - 流程定义定义了流程各个节点的结构和行为
                    - 流程实例就是这样一个流程定义的实例
                    - 对每个流程定义来说,同一时间会有很多实例在执行
            - RuntimeService可以用来获取和保存流程变量,这些数据是特定于某个流程实例的,并会被很多流程中的节点使用
            - Runtimeservice可以查询流程实例和执行,执行对应BPMN 2.0中的'token',基本上执行指向流程实例当前在哪里
            - RuntimeService可以在流程实例等待外部触发时使用,可以用来继续流程实例.流程实例可以有很多暂停状态,而服务提供了多种方法来'触发'实例, 接受外部触发后,流程实例就会继续向下执行
TaskService
            - 任务是由系统中真实人员执行的,它是Activiti这类BPMN引擎的核心功能之一, 所有与任务有关的功能都包含在TaskService中
            - 在TaskService中,查询分配给用户或组的任务
            - 在TaskService中,创建独立运行任务,这些任务与流程实例无关
            - 在TaskService中,手工设置任务的执行者,或者这些用户通过何种方式与任务关联
            - 在TaskService中,认领并完成一个任务:
                    - 认领意味着一个人期望成为任务的执行者,即这个用户会完成这个任务
                    - 完成意味着“做这个任务要求的事情”,通常来说会有很多种处理形式
IdentityService
            - 可以管理,创建,更新,删除,查询..群组和用户
            -  Activiti执行时并没有对用户进行检查.任务可以分配给任何人,但是引擎不会校验系统中是否存在这个用户.这是Activiti引擎也可以使用外部服务:ldap,活动目录...
HistoryService
            - HistoryService提供了Activiti引擎的所有历史数据
            - 在执行流程时,引擎会根据配置保存很多数据:流程实例启动时间,任务的参与者,完成任务的时间,每个流程实例的执行路径..., 这个服务主要通过查询功能来获得这些数据
FormService
            - FormService是一个可选服务,即使不使用它,Activiti也可以完美运行,不会损失任何功能
            - FormService提供了启动表单和任务表单两个概念
                    - 启动表单会在流程实例启动之前展示给用户
                    - 任务表单会在用户完成任务时展示
            - Activiti支持在BPMN 2.0流程定义中设置这些表单.这个服务以一种简单的方式将数据暴露出来,是可选的,表单也不一定要嵌入到流程定义中
ManagementService
            - 在使用Activiti的定制环境中基本上不会用到
            - ManagementService可以查询数据库的表和表的元数据
            - ManagementService提供了查询和管理异步操作的功能
            - Activiti的异步操作用途很多:定时器,异步操作,延迟暂停,激活..

异常策略

/**
 * Called when the task is successfully executed.
 * @param taskId the id of the task to complete, cannot be null.
 * @throws ActivitiObjectNotFoundException when no task exists with the given id.
 */
 void complete(String taskId);

当传入一个不存在的任务的id时,就会抛出异常.taskId不能为null,如果传入null,就会抛出ActivitiIllegalArgumentException

ActivitiWrongDbException:               当Activiti引擎发现数据库版本号和引擎版本号不一致时抛出
ActivitiOptimisticLockingException:     对同一数据进行并发方法并出现乐观锁时抛出
ActivitiClassLoadingException:          当无法找到需要加载的类或在加载类时出现了错误-JavaDelegate,TaskListener
ActivitiObjectNotFoundException:        当请求或操作的对应不存在时抛出
ActivitiIllegalArgumentException:       这个异常表示调用Activiti API时传入了一个非法的参数,可能是引擎配置中的非法值,或提供了一个非法值,或流程定义中使用的非法值
ActivitiTaskAlreadyClaimedException:    当任务已经被认领了,再调用taskService.claim(...)就会抛出

查询 API

     List<Task> tasks = taskService.createTaskQuery()
         .taskAssignee("kermit")
         .processVariableValueEquals("orderId", "0815")
         .orderByDueDate().asc()
         .list();
    List<Task> tasks = taskService.createNativeTaskQuery()
        .sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T WHERE T.NAME_ = #{taskName}")
        .parameter("taskName", "gonzoTask")
        .list();

      long count = taskService.createNativeTaskQuery()
        .sql("SELECT count(*) FROM " + managementService.getTableName(Task.class) + " T1, "
               + managementService.getTableName(VariableInstanceEntity.class) + " V1 WHERE V1.TASK_ID_ = T1.ID_")
        .count();

表达式

${myVar}
${myBean.myProperty}

所有流程变量都可以使用,所有spring bean(spring环境中)也可以使用在表达式中

${printer.print()}
${myBean.addNewOrder('orderName')}
${myBean.doSomething(myVar, execution)}

当调用一个无参数的方法时,记得在方法名后添加空的括号,以区分值表达式
传递的参数可以是字符串也可以是表达式,它们会被自动解析

单元测试

public class MyBusinessProcessTest extends ActivitiTestCase {

  @Deployment
  public void testSimpleProcess() {
    runtimeService.startProcessInstanceByKey("simpleProcess");

    Task task = taskService.createTaskQuery().singleResult();
    assertEquals("My Task", task.getName());

    taskService.complete(task.getId());
    assertEquals(0, runtimeService.createProcessInstanceQuery().count());
  }
}
public class MyBusinessProcessTest {

  @Rule
  public ActivitiRule activitiRule = new ActivitiRule();

  @Test
  @Deployment
  public void ruleUsageExample() {
    RuntimeService runtimeService = activitiRule.getRuntimeService();
    runtimeService.startProcessInstanceByKey("ruleUsage");

    TaskService taskService = activitiRule.getTaskService();
    Task task = taskService.createTaskQuery().singleResult();
    assertEquals("My Task", task.getName());

    taskService.complete(task.getId());
    assertEquals(0, runtimeService.createProcessInstanceQuery().count());
  }
}

调试单元测试

Web中的流程引擎

public class ProcessEnginesServletContextListener implements ServletContextListener {

  public void contextInitialized(ServletContextEvent servletContextEvent) {
    ProcessEngines.init();
  }

  public void contextDestroyed(ServletContextEvent servletContextEvent) {
    ProcessEngines.destroy();
  }

}

contextInitialized方法会执行ProcessEngines.init() 这会查找classpath下的activiti.cfg.xml文件,根据配置文件创建一个ProcessEngine(比如,多个jar中都包含配置文件)如果classpath中包含多个配置文件,确认它们有不同的名字

ProcessEngines.getDefaultProcessEngine()

ProcessEngines.getProcessEngine("myName");
上一篇 下一篇

猜你喜欢

热点阅读