本文详细介绍了Java工作流项目的学习过程,涵盖了工作流的基本概念、Java中工作流框架的选择与搭建,以及具体的流程模型设计与执行。文章还提供了搭建简易请假审批系统的实践案例,帮助读者更好地理解和应用Java工作流项目学习。
Java工作流简介什么是工作流
工作流是一种自动化业务流程的方法,它通过定义任务的序列、条件和参与者来实现业务流程的自动化。工作流的核心在于将流程中的各个步骤和任务进行结构化定义,以确保流程的一致性和高效执行。工作流模型通常包括流程定义、流程实例、活动、连接和参与者等元素。流程定义定义了整个流程的结构和逻辑,而流程实例则是具体执行过程中的实例化表示。
工作流在Java中的应用
在Java应用程序中,工作流通常用于自动化复杂的业务流程,如订单处理、审批流程、资源调度等。通过使用Java工作流框架,可以动态地定义和修改流程逻辑,从而提高系统的灵活性和可维护性。Java工作流框架提供了API支持,允许开发者通过编程方式定义和控制流程的执行,包括启动流程实例、完成任务、处理分支和并行路径等。
选择合适的Java工作流框架流行的工作流框架介绍
Java工作流框架有许多流行的选择,每个框架都有其特点和适用场景。
-
Activiti
- Activiti是一个基于BPMN 2.0规范的工作流引擎,提供了强大的流程定义和执行功能。Activiti的API丰富,易于集成到各种Java应用程序中。它支持流程定义的可视化设计,并提供了丰富的工具和插件,如Activiti Explorer、Activiti Tasklist和Activiti REST API。
-
示例代码:
import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; public class ActivitiInitializer { public static ProcessEngine initializeEngine() { ProcessEngineConfiguration processEngineConfiguration = new StandaloneProcessEngineConfiguration(); processEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activiti"); processEngineConfiguration.setJdbcUsername("root"); processEngineConfiguration.setJdbcPassword("password"); processEngineConfiguration.setJdbcDriver("com.mysql.cj.jdbc.Driver"); processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); return processEngineConfiguration.buildProcessEngine(); } }
-
JBPM
- JBPM(Java Business Process)是一个开源的业务流程管理框架,它支持BPMN 2.0流程模型,并提供了强大的流程执行和管理功能。JBPM内置了流程引擎、规则引擎和任务列表等功能,支持流程的动态修改和扩展。JBPM还提供了可插拔的持久层和调度器,以满足不同的应用场景。
-
示例代码:
import org.jbpm.services.cdi.impl.JBPMAbstractBean; import org.jbpm.services.cdi.impl.KieServerRuntimeServiceBean; @Startup @Singleton public class KieJarDeploymentBean extends JBPMAbstractBean { @Inject KieServerRuntimeService kieServerRuntimeService; @PostConstruct public void deployJars() { kieServerRuntimeService.createContainer("processes"); KieContainer kieContainer = kieServerRuntimeService.getKieContainer("processes"); kieContainer.start(); } }
-
Camunda
- Camunda是一个开源的工作流引擎,支持BPMN 2.0流程模型。它提供了强大的流程定义和执行能力,支持流程的可视化设计和调试。Camunda还提供了与Spring Boot、Docker等现代技术栈的集成,使其易于在现代应用中使用。Camunda还提供了丰富的插件和扩展点,以满足各种业务场景的需求。
-
示例代码:
import org.camunda.bpm.engine.ProcessEngine; import org.camunda.bpm.engine.ProcessEngines; public class CamundaInitializer { public static ProcessEngine initializeEngine() { return ProcessEngines.getDefaultProcessEngine(); } }
-
Flowable
- Flowable是一个基于BPMN 2.0的工作流引擎,提供了强大的流程定义和执行功能。Flowable支持流程实例的动态创建和修改,能够根据业务需求灵活调整流程逻辑。它还支持流程的可视化设计和调试,并提供了丰富的API和插件,以支持各种应用场景。
-
示例代码:
import org.flowable.engine.ProcessEngine; import org.flowable.spring.ProcessEngineFactoryBean; @Configuration public class FlowableConfig { @Bean public ProcessEngineFactoryBean processEngineFactoryBean(DataSource dataSource) { ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean(); processEngineFactoryBean.setDataSource(dataSource); processEngineFactoryBean.setJdbcUrl("jdbc:mysql://localhost:3306/flowable"); processEngineFactoryBean.setJdbcUsername("root"); processEngineFactoryBean.setJdbcPassword("password"); processEngineFactoryBean.setDatabaseSchemaUpdate(ProcessEngineFactoryBean.DATABASE_SCHEMA_UPDATE_TRUE); return processEngineFactoryBean; } }
框架对比与选择建议
选择合适的Java工作流框架时,需要考虑以下几个因素:
- 流程模型支持:选择支持BPMN 2.0的框架,如Activiti、JBPM和Camunda。
- 易用性与集成:选择API简单、易于集成的框架,如Activiti和Camunda。
- 扩展性和灵活性:选择支持动态修改和扩展的框架,如JBPM和Flowable。
- 社区支持和文档:选择有活跃社区和详细文档的框架,如Activiti和Camunda。
- 性能和稳定性:选择经过广泛测试和应用验证的框架,如JBPM和Flowable。
根据上述因素,建议选择Activiti或Camunda,它们支持BPMN 2.0,API易于使用,且有丰富的社区支持和文档。
Java工作流项目搭建开发环境准备
开发Java工作流项目需要准备Java开发环境和相应的工作流框架环境。以下是开发环境的准备步骤:
- 安装JDK:下载并安装最新版本的JDK。
- 配置环境变量:
- 设置JAVA_HOME为JDK安装目录。
- 将JAVA_HOME/bin路径添加到系统PATH变量中。
- 验证JDK安装是否成功,运行
java -version
命令。
- 选择IDE:选择合适的IDE,如IntelliJ IDEA或Eclipse。
- 安装Maven或Gradle:选择依赖管理工具,下载并安装Maven或Gradle。
- 安装工作流框架:下载并安装所选工作流框架的服务器版本,如Activiti或Camunda。
- 配置工作流框架环境:
- 启动工作流框架的服务器。
- 配置工作流框架的数据源和持久化存储。
- 配置工作流框架的HTTP接口和服务端口。
通过以上步骤,可以准备好开发Java工作流项目的环境。
创建新的Java项目
创建一个新的Java项目,选择合适的框架进行集成。以下是创建新的Java项目并集成工作流框架的步骤:
-
创建Maven或Gradle项目:
- 使用IDE创建一个新的Maven或Gradle项目。
- 配置pom.xml或build.gradle文件,添加相应的依赖。
- 示例代码:
<dependencies> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-engine</artifactId> <version>5.22.0</version> </dependency> </dependencies>
-
初始化工作流框架:
- 初始化工具类,创建
ProcessEngineConfiguration
对象。 - 配置
ProcessEngineConfiguration
对象,设置数据库连接、任务执行器等。 -
示例代码:
import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration; public class ActivitiInitializer { public static ProcessEngine initializeEngine() { ProcessEngineConfiguration processEngineConfiguration = new StandaloneProcessEngineConfiguration(); processEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activiti"); processEngineConfiguration.setJdbcUsername("root"); processEngineConfiguration.setJdbcPassword("password"); processEngineConfiguration.setJdbcDriver("com.mysql.cj.jdbc.Driver"); processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); return processEngineConfiguration.buildProcessEngine(); } }
- 初始化工具类,创建
集成所选工作流框架
集成所选的工作流框架,初始化流程引擎并开始使用流程定义。以下是集成工作流框架的步骤:
-
启动流程引擎:
- 初始化流程引擎,获取
ProcessEngine
对象。 -
示例代码:
import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; public class ActivitiService { private static final ProcessEngine processEngine = ActivitiInitializer.initializeEngine(); public static ProcessEngine getProcessEngine() { return processEngine; } }
- 初始化流程引擎,获取
-
部署流程定义:
- 部署流程定义文件(如BPMN文件)到流程引擎。
-
示例代码:
import org.activiti.engine.RepositoryService; import org.activiti.engine.repository.Deployment; public class ActivitiDeploymentService { public static void deployProcessDefinition() { RepositoryService repositoryService = ActivitiService.getProcessEngine().getRepositoryService(); Deployment deployment = repositoryService.createDeployment() .addClasspathResource("processes/leaveApproval.bpmn20.xml") .deploy(); } }
-
启动流程实例:
- 启动流程实例,开始执行流程定义。
-
示例代码:
import org.activiti.engine.ProcessEngine; import org.activiti.engine.RuntimeService; import org.activiti.engine.runtime.ProcessInstance; public class ActivitiRuntimeService { public static ProcessInstance startProcessInstance() { ProcessEngine processEngine = ActivitiService.getProcessEngine(); RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leaveApproval"); return processInstance; } }
工作流模型设计
工作流模型设计是定义流程逻辑的重要步骤。流程模型通常使用BPMN 2.0规范进行定义,并包含流程定义、节点、任务和连接等元素。
-
流程定义:
- 流程定义文件通常以XML格式存储,如BPMN文件。
- 定义流程的开始、结束、任务和连接等元素。
- 示例代码:
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100801/BPMN20.xsd" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn"> <process id="leaveApproval" isExecutable="true"> <startEvent id="StartEvent_1"/> <sequenceFlow id="Flow_1" sourceRef="StartEvent_1" targetRef="UserTask_1"/> <userTask id="UserTask_1" name="请假申请"> <extensionElements> <activiti:taskListener event="create" class="com.example.tasklisteners.LeaveApplicationListener"/> </extensionElements> </userTask> <sequenceFlow id="Flow_2" sourceRef="UserTask_1" targetRef="ExclusiveGateway_1"/> <exclusiveGateway id="ExclusiveGateway_1"/> <sequenceFlow id="Flow_3" sourceRef="ExclusiveGateway_1" targetRef="UserTask_2"/> <sequenceFlow id="Flow_4" sourceRef="ExclusiveGateway_1" targetRef="EndEvent_1"/> <userTask id="UserTask_2" name="主管审批"> <extensionElements> <activiti:taskListener event="create" class="com.example.tasklisteners.ManagerApprovalListener"/> </extensionElements> </userTask> <sequenceFlow id="Flow_5" sourceRef="UserTask_2" targetRef="EndEvent_1"/> <endEvent id="EndEvent_1"/> </process> </definitions>
-
节点:
- 节点表示流程中的任务或步骤,如开始、结束、用户任务、服务任务等。
- 示例代码:
<startEvent id="StartEvent_1"/> <userTask id="UserTask_1" name="请假申请"/> <exclusiveGateway id="ExclusiveGateway_1"/> <endEvent id="EndEvent_1"/>
-
任务:
- 任务表示具体的执行逻辑,如用户任务、服务任务、脚本任务等。
- 示例代码:
<userTask id="UserTask_1" name="请假申请"> <extensionElements> <activiti:taskListener event="create" class="com.example.tasklisteners.LeaveApplicationListener"/> </extensionElements> </userTask>
- 连接:
- 连接表示节点之间的路径和条件,如顺序流、并行流、条件流等。
- 示例代码:
<sequenceFlow id="Flow_1" sourceRef="StartEvent_1" targetRef="UserTask_1"/> <exclusiveGateway id="ExclusiveGateway_1"/> <sequenceFlow id="Flow_3" sourceRef="ExclusiveGateway_1" targetRef="UserTask_2"/> <sequenceFlow id="Flow_4" sourceRef="ExclusiveGateway_1" targetRef="EndEvent_1"/>
定义流程任务与节点
定义流程任务与节点是实现具体业务逻辑的关键步骤。流程任务可以是用户任务、服务任务、脚本任务等。
-
用户任务:
- 用户任务表示需要人工介入的任务,通常由用户或管理员执行。
- 示例代码:
<userTask id="UserTask_1" name="请假申请"> <extensionElements> <activiti:taskListener event="create" class="com.example.tasklisteners.LeaveApplicationListener"/> </extensionElements> </userTask>
- 用户任务还可以配置任务监听器,用于处理任务的生命周期事件。
- 示例代码:
public class LeaveApplicationListener implements TaskListener { @Override public void notify(DelegateTask delegateTask) { // 任务开始时执行的逻辑 } }
-
服务任务:
- 服务任务表示需要调用服务或执行其他逻辑的任务,通常由系统自动执行。
- 示例代码:
<serviceTask id="ServiceTask_1" name="服务任务" activiti:class="com.example.service.MyService"/>
- 服务任务可以指定服务实现类,用于执行具体的业务逻辑。
- 示例代码:
public class MyService implements TaskDelegate { @Override public void execute(DelegateExecution execution) { // 服务任务执行的逻辑 } }
- 脚本任务:
- 脚本任务表示需要执行脚本的任务,通常用于简单的逻辑处理。
- 示例代码:
<scriptTask id="ScriptTask_1" name="脚本任务" activiti:script="result = 'Hello, World!'; result"> </scriptTask>
- 脚本任务可以包含脚本逻辑,用于实现特定的处理。
- 示例代码:
<scriptTask id="ScriptTask_1" name="脚本任务" activiti:script="result = 100 * 200; result"> </scriptTask>
执行与监控工作流
执行与监控工作流是确保流程正确执行的重要步骤。可以通过API或管理界面执行和监控流程实例。
-
执行流程实例:
- 通过API启动流程实例并执行流程定义。
-
示例代码:
import org.activiti.engine.ProcessEngine; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.runtime.ProcessInstance; public class ActivitiRuntimeService { public static ProcessInstance startProcessInstance() { ProcessEngine processEngine = ActivitiService.getProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("leaveApproval"); return processInstance; } }
-
监控流程实例:
- 通过API监控流程实例的状态和执行情况。
-
示例代码:
import org.activiti.engine.ProcessEngine; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; public class ActivitiMonitoringService { public static void monitorProcessInstance(String processInstanceId) { ProcessEngine processEngine = ActivitiService.getProcessEngine(); RuntimeService runtimeService = processEngine.getRuntimeService(); TaskService taskService = processEngine.getTaskService(); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); if (processInstance != null) { System.out.println("流程实例ID: " + processInstance.getId()); System.out.println("流程实例名称: " + processInstance.getName()); System.out.println("流程实例状态: " + processInstance.getState()); List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list(); for (Task task : tasks) { System.out.println("任务ID: " + task.getId()); System.out.println("任务名称: " + task.getName()); System.out.println("任务创建时间: " + task.getCreateTime()); } } else { System.out.println("流程实例已结束"); } } }
搭建简易请假审批系统
搭建一个简易的请假审批系统,演示如何使用Java工作流框架实现流程自动化。
需求描述
- 用户提交请假申请:用户提交请假申请,系统自动生成请假申请单。
- 主管审批:主管审批请假申请,根据不同的审批结果(批准或拒绝)执行后续流程。
- 通知用户审批结果:系统通知用户审批结果,并记录审批日志。
代码实现
-
创建BPMN文件:
- 定义请假审批流程:
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100801/BPMN20.xsd" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn"> <process id="leaveApproval" isExecutable="true"> <startEvent id="StartEvent_1"/> <sequenceFlow id="Flow_1" sourceRef="StartEvent_1" targetRef="UserTask_1"/> <userTask id="UserTask_1" name="请假申请"> <extensionElements> <activiti:taskListener event="create" class="com.example.tasklisteners.LeaveApplicationListener"/> </extensionElements> </userTask> <sequenceFlow id="Flow_2" sourceRef="UserTask_1" targetRef="ExclusiveGateway_1"/> <exclusiveGateway id="ExclusiveGateway_1"/> <sequenceFlow id="Flow_3" sourceRef="ExclusiveGateway_1" targetRef="UserTask_2"/> <sequenceFlow id="Flow_4" sourceRef="ExclusiveGateway_1" targetRef="EndEvent_1"/> <userTask id="UserTask_2" name="主管审批"> <extensionElements> <activiti:taskListener event="create" class="com.example.tasklisteners.ManagerApprovalListener"/> </extensionElements> </userTask> <sequenceFlow id="Flow_5" sourceRef="UserTask_2" targetRef="EndEvent_1"/> <endEvent id="EndEvent_1"/> </process> </definitions>
- 定义请假审批流程:
-
创建任务监听器:
- 实现请假申请任务监听器:
public class LeaveApplicationListener implements TaskListener { @Override public void notify(DelegateTask delegateTask) { // 请假申请任务处理逻辑 } }
- 实现主管审批任务监听器:
public class ManagerApprovalListener implements TaskListener { @Override public void notify(DelegateTask delegateTask) { // 主管审批任务处理逻辑 } }
- 实现请假申请任务监听器:
-
启动请假审批流程:
-
通过API启动请假审批流程实例:
import org.activiti.engine.ProcessEngine; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.runtime.ProcessInstance; public class ActivitiRuntimeService { public static ProcessInstance startProcessInstance() { ProcessEngine processEngine = ActivitiService.getProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); ProcessInstance processInstance = processEngine.getRuntimeService().startProcessInstanceByKey("leaveApproval"); return processInstance; } }
-
解释代码与实现思路
-
BPMN文件:
- 搭建了从用户提交请假申请到主管审批的流程。
- 包含开始事件、用户任务、排它网关、结束事件等元素。
- 流程定义文件使用BPMN 2.0规范定义。
-
任务监听器:
- 实现了请假申请任务和主管审批任务的监听器。
- 监听器处理任务的生命周期事件,如创建和完成任务时的逻辑。
- 启动流程实例:
- 使用API启动请假审批流程实例。
- 通过
startProcessInstanceByKey
方法启动指定流程定义的实例。
运行与调试
运行和调试请假审批系统,确保流程能够正确执行并达到预期结果。
-
运行流程实例:
- 运行
startProcessInstance
方法启动流程实例。 - 输出流程实例ID和流程实例的状态。
- 示例代码:
public static void main(String[] args) { ProcessInstance processInstance = ActivitiRuntimeService.startProcessInstance(); System.out.println("流程实例ID: " + processInstance.getId()); System.out.println("流程实例状态: " + processInstance.getState()); }
- 运行
-
调试流程实例:
- 通过监控接口获取流程实例的状态。
- 调试流程实例的执行情况,确保流程逻辑正确执行。
-
示例代码:
public static void main(String[] args) { ProcessInstance processInstance = ActivitiRuntimeService.startProcessInstance(); System.out.println("流程实例ID: " + processInstance.getId()); System.out.println("流程实例状态: " + processInstance.getState()); ActivitiMonitoringService.monitorProcessInstance(processInstance.getId()); }
常见问题汇总
- 流程定义文件错误:流程定义文件格式错误或包含无效元素。
- 数据库连接失败:数据库连接配置错误或数据库服务未启动。
- 流程执行异常:流程执行时出现异常或任务执行失败。
- 流程监控难:流程实例状态监控困难或监控接口不完善。
解决方案与调试技巧
-
流程定义文件错误:
- 检查流程定义文件格式是否正确,确保符合BPMN 2.0规范。
- 使用流程建模工具进行验证和调试。
- 示例代码:
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100801/BPMN20.xsd" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn"> <process id="leaveApproval" isExecutable="true"> <startEvent id="StartEvent_1"/> <sequenceFlow id="Flow_1" sourceRef="StartEvent_1" targetRef="UserTask_1"/> <userTask id="UserTask_1" name="请假申请"> <extensionElements> <activiti:taskListener event="create" class="com.example.tasklisteners.LeaveApplicationListener"/> </extensionElements> </userTask> <sequenceFlow id="Flow_2" sourceRef="UserTask_1" targetRef="ExclusiveGateway_1"/> <exclusiveGateway id="ExclusiveGateway_1"/> <sequenceFlow id="Flow_3" sourceRef="ExclusiveGateway_1" targetRef="UserTask_2"/> <sequenceFlow id="Flow_4" sourceRef="ExclusiveGateway_1" targetRef="EndEvent_1"/> <userTask id="UserTask_2" name="主管审批"> <extensionElements> <activiti:taskListener event="create" class="com.example.tasklisteners.ManagerApprovalListener"/> </extensionElements> </userTask> <sequenceFlow id="Flow_5" sourceRef="UserTask_2" targetRef="EndEvent_1"/> <endEvent id="EndEvent_1"/> </process> </definitions>
-
数据库连接失败:
- 检查数据库连接配置是否正确,确保数据库服务已启动。
- 使用数据库管理工具验证数据库连接。
-
示例代码:
import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.ProcessEngine; public class ActivitiInitializer { public static ProcessEngine initializeEngine() { ProcessEngineConfiguration processEngineConfiguration = new StandaloneProcessEngineConfiguration(); processEngineConfiguration.setJdbcUrl("jdbc:mysql://localhost:3306/activiti"); processEngineConfiguration.setJdbcUsername("root"); processEngineConfiguration.setJdbcPassword("password"); processEngineConfiguration.setJdbcDriver("com.mysql.cj.jdbc.Driver"); processEngineConfiguration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); return processEngineConfiguration.buildProcessEngine(); } }
-
流程执行异常:
- 检查流程定义文件和任务监听器实现是否正确。
- 调试任务执行逻辑,确保任务执行成功。
- 示例代码:
public class LeaveApplicationListener implements TaskListener { @Override public void notify(DelegateTask delegateTask) { // 请假申请任务处理逻辑 } }
-
流程监控难:
- 使用流程监控工具或API获取流程实例的状态。
- 调试流程实例的执行情况,确保流程逻辑正确执行。
-
示例代码:
import org.activiti.engine.ProcessEngine; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.history.HistoricTaskInstance; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; public class ActivitiMonitoringService { public static void monitorProcessInstance(String processInstanceId) { ProcessEngine processEngine = ActivitiService.getProcessEngine(); RuntimeService runtimeService = processEngine.getRuntimeService(); TaskService taskService = processEngine.getTaskService(); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); if (processInstance != null) { System.out.println("流程实例ID: " + processInstance.getId()); System.out.println("流程实例名称: " + processInstance.getName()); System.out.println("流程实例状态: " + processInstance.getState()); List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list(); for (Task task : tasks) { System.out.println("任务ID: " + task.getId()); System.out.println("任务名称: " + task.getName()); System.out.println("任务创建时间: " + task.getCreateTime()); } } else { System.out.println("流程实例已结束"); } } }
共同學習,寫下你的評論
評論加載中...
作者其他優質文章