Skip to content

getProcessDefinition

Flowable 7.1.0 摘要:根据流程定义ID获取流程定义对象。

方法签名与说明

ProcessDefinition getProcessDefinition(String processDefinitionId)

根据唯一的流程定义ID获取流程定义对象。流程定义ID是在部署时由Flowable自动生成的,格式通常为 {processDefinitionKey}:{version}:{deploymentId}

Parameters:

  • processDefinitionId - 流程定义的唯一标识符,不能为null

Returns:

  • ProcessDefinition - 流程定义对象,包含流程的元数据信息

Throws:

  • FlowableObjectNotFoundException - 当指定ID的流程定义不存在时

常见使用场景

1. 流程详情展示

在企业流程管理后台,管理员需要查看已部署流程的详细信息,包括流程名称、版本、部署时间等。

2. 流程版本对比

在流程版本升级时,需要获取旧版本和新版本的流程定义,进行对比分析,确保升级不影响现有业务。

3. 流程图渲染

在流程监控页面,需要根据流程实例获取对应的流程定义,然后渲染流程图,展示当前执行位置。

4. 权限验证

在启动流程前,验证当前用户是否有权限启动该流程,需要先获取流程定义信息。

Kotlin + Spring Boot 调用示例

示例1:获取并展示流程定义基本信息

kotlin
import org.flowable.engine.RepositoryService
import org.flowable.engine.repository.ProcessDefinition
import org.springframework.stereotype.Service

@Service
class ProcessDefinitionService(
    private val repositoryService: RepositoryService
) {
    
    /**
     * 获取流程定义详细信息
     * 企业场景:流程管理后台展示流程基本信息
     */
    fun getProcessDefinitionDetails(processDefinitionId: String): Map<String, Any> {
        val processDefinition = repositoryService.getProcessDefinition(processDefinitionId)
        
        return mapOf(
            "id" to processDefinition.id,
            "key" to processDefinition.key,
            "name" to processDefinition.name,
            "version" to processDefinition.version,
            "category" to processDefinition.category,
            "description" to processDefinition.description,
            "deploymentId" to processDefinition.deploymentId,
            "resourceName" to processDefinition.resourceName,
            "diagramResourceName" to processDefinition.diagramResourceName,
            "hasStartFormKey" to processDefinition.hasStartFormKey(),
            "hasGraphicalNotation" to processDefinition.hasGraphicalNotation(),
            "isSuspended" to processDefinition.isSuspended,
            "tenantId" to processDefinition.tenantId
        )
    }
}

示例2:获取流程定义用于启动流程

kotlin
import org.flowable.engine.RepositoryService
import org.flowable.engine.RuntimeService
import org.springframework.stereotype.Service

@Service
class LeaveApplicationService(
    private val repositoryService: RepositoryService,
    private val runtimeService: RuntimeService
) {
    
    /**
     * 根据流程定义ID启动请假流程
     * 企业场景:员工提交请假申请时,验证流程是否可用
     */
    fun startLeaveProcess(
        processDefinitionId: String,
        employeeId: String,
        leaveDays: Int
    ): String {
        // 获取流程定义,验证是否存在且未挂起
        val processDefinition = repositoryService.getProcessDefinition(processDefinitionId)
        
        if (processDefinition.isSuspended) {
            throw IllegalStateException("流程已被挂起,暂时无法提交申请")
        }
        
        println("=== 启动请假流程 ===")
        println("流程名称: ${processDefinition.name}")
        println("流程版本: V${processDefinition.version}")
        
        // 启动流程实例
        val variables = mapOf(
            "employeeId" to employeeId,
            "leaveDays" to leaveDays,
            "applyTime" to System.currentTimeMillis()
        )
        
        val processInstance = runtimeService.startProcessInstanceById(
            processDefinitionId,
            employeeId, // 使用员工ID作为业务Key
            variables
        )
        
        return processInstance.id
    }
}

示例3:流程版本对比

kotlin
import org.flowable.engine.RepositoryService
import org.springframework.stereotype.Service

data class ProcessVersionComparison(
    val oldVersion: ProcessVersionInfo,
    val newVersion: ProcessVersionInfo
)

data class ProcessVersionInfo(
    val id: String,
    val version: Int,
    val deploymentTime: String,
    val resourceName: String
)

@Service
class ProcessVersionComparisonService(
    private val repositoryService: RepositoryService
) {
    
    /**
     * 对比两个版本的流程定义
     * 企业场景:流程升级时,对比新旧版本的差异
     */
    fun compareProcessVersions(
        oldProcessDefinitionId: String,
        newProcessDefinitionId: String
    ): ProcessVersionComparison {
        
        val oldDef = repositoryService.getProcessDefinition(oldProcessDefinitionId)
        val newDef = repositoryService.getProcessDefinition(newProcessDefinitionId)
        
        // 验证是否为同一个流程的不同版本
        if (oldDef.key != newDef.key) {
            throw IllegalArgumentException("两个流程定义的Key不同,无法对比")
        }
        
        val oldVersionInfo = ProcessVersionInfo(
            id = oldDef.id,
            version = oldDef.version,
            deploymentTime = oldDef.deploymentId,
            resourceName = oldDef.resourceName
        )
        
        val newVersionInfo = ProcessVersionInfo(
            id = newDef.id,
            version = newDef.version,
            deploymentTime = newDef.deploymentId,
            resourceName = newDef.resourceName
        )
        
        println("=== 流程版本对比 ===")
        println("流程Key: ${oldDef.key}")
        println("旧版本: V${oldDef.version}")
        println("新版本: V${newDef.version}")
        
        return ProcessVersionComparison(oldVersionInfo, newVersionInfo)
    }
}

示例4:检查流程是否有启动表单

kotlin
import org.flowable.engine.RepositoryService
import org.flowable.engine.form.StartFormData
import org.flowable.form.api.FormRepositoryService
import org.springframework.stereotype.Service

@Service
class ProcessStartFormService(
    private val repositoryService: RepositoryService
) {
    
    /**
     * 检查流程是否配置了启动表单
     * 企业场景:在展示流程启动页面前,判断是否需要渲染表单
     */
    fun checkAndGetStartForm(processDefinitionId: String): Map<String, Any?> {
        val processDefinition = repositoryService.getProcessDefinition(processDefinitionId)
        
        val hasStartForm = processDefinition.hasStartFormKey()
        
        return mapOf(
            "processName" to processDefinition.name,
            "hasStartForm" to hasStartForm,
            "startFormKey" to if (hasStartForm) {
                // 获取启动表单Key(如果配置了)
                processDefinition.description // 简化示例,实际需要从BPMN中解析
            } else null,
            "message" to if (hasStartForm) {
                "该流程需要填写启动表单"
            } else {
                "该流程可直接启动,无需填写表单"
            }
        )
    }
}

示例5:多租户场景获取流程定义

kotlin
import org.flowable.engine.RepositoryService
import org.springframework.stereotype.Service

@Service
class TenantProcessService(
    private val repositoryService: RepositoryService
) {
    
    /**
     * 在多租户环境中获取流程定义
     * 企业场景:SaaS平台中,为不同企业客户提供流程管理
     */
    fun getProcessDefinitionForTenant(
        processDefinitionId: String,
        currentTenantId: String
    ): Map<String, Any> {
        
        val processDefinition = repositoryService.getProcessDefinition(processDefinitionId)
        
        // 验证租户权限
        if (processDefinition.tenantId != currentTenantId) {
            throw SecurityException("无权访问其他租户的流程定义")
        }
        
        return mapOf(
            "processName" to processDefinition.name,
            "tenantId" to processDefinition.tenantId,
            "version" to processDefinition.version,
            "isActive" to !processDefinition.isSuspended
        )
    }
}

示例6:获取流程定义并渲染流程图

kotlin
import org.flowable.bpmn.model.BpmnModel
import org.flowable.engine.RepositoryService
import org.flowable.image.ProcessDiagramGenerator
import org.springframework.stereotype.Service
import java.io.InputStream

@Service
class ProcessDiagramService(
    private val repositoryService: RepositoryService,
    private val processDiagramGenerator: ProcessDiagramGenerator
) {
    
    /**
     * 获取流程定义并生成流程图
     * 企业场景:在流程监控页面展示流程图
     */
    fun generateProcessDiagram(processDefinitionId: String): InputStream {
        // 获取流程定义
        val processDefinition = repositoryService.getProcessDefinition(processDefinitionId)
        
        println("生成流程图: ${processDefinition.name} V${processDefinition.version}")
        
        // 获取BPMN模型
        val bpmnModel = repositoryService.getBpmnModel(processDefinitionId)
        
        // 生成流程图(PNG格式)
        return processDiagramGenerator.generateDiagram(
            bpmnModel,
            "png",
            emptyList(), // 高亮节点
            emptyList(), // 高亮流程线
            "宋体", "宋体", "宋体", // 中文字体
            null,
            1.0,
            true
        )
    }
}

示例7:流程定义管理控制器

kotlin
import org.flowable.engine.RepositoryService
import org.springframework.web.bind.annotation.*

data class ProcessDefinitionDTO(
    val id: String,
    val key: String,
    val name: String,
    val version: Int,
    val category: String?,
    val deploymentId: String,
    val isSuspended: Boolean,
    val tenantId: String
)

@RestController
@RequestMapping("/api/process-definitions")
class ProcessDefinitionController(
    private val repositoryService: RepositoryService
) {
    
    /**
     * 获取流程定义详情API
     * 企业场景:前端流程管理页面调用此接口获取流程信息
     */
    @GetMapping("/{processDefinitionId}")
    fun getProcessDefinition(
        @PathVariable processDefinitionId: String
    ): ProcessDefinitionDTO {
        
        val pd = repositoryService.getProcessDefinition(processDefinitionId)
        
        return ProcessDefinitionDTO(
            id = pd.id,
            key = pd.key,
            name = pd.name,
            version = pd.version,
            category = pd.category,
            deploymentId = pd.deploymentId,
            isSuspended = pd.isSuspended,
            tenantId = pd.tenantId
        )
    }
    
    /**
     * 检查流程状态
     */
    @GetMapping("/{processDefinitionId}/status")
    fun checkProcessStatus(
        @PathVariable processDefinitionId: String
    ): Map<String, Any> {
        
        val pd = repositoryService.getProcessDefinition(processDefinitionId)
        
        return mapOf(
            "processName" to pd.name,
            "status" to if (pd.isSuspended) "已挂起" else "运行中",
            "canStartNewInstance" to !pd.isSuspended
        )
    }
}

注意事项

1. ID格式理解

  • 流程定义ID由系统自动生成,格式:{key}:{version}:{deploymentId}
  • 例如:leaveProcess:3:12345 表示key为leaveProcess,版本3,部署ID为12345
  • 不要手动构造流程定义ID,应从查询结果或流程实例中获取

2. 异常处理

  • 当流程定义不存在时会抛出 FlowableObjectNotFoundException
  • 建议使用try-catch捕获异常,向用户返回友好提示

3. 挂起状态检查

  • 获取流程定义后,应检查 isSuspended 属性
  • 挂起的流程定义无法启动新的流程实例

4. 多租户隔离

  • 在多租户环境中,需要验证流程定义的 tenantId 是否匹配
  • 防止租户A访问租户B的流程定义

5. 缓存机制

  • Flowable内部会缓存流程定义,重复获取不会频繁访问数据库
  • 无需在应用层额外缓存流程定义对象

6. 权限控制

  • 生产环境应限制流程定义访问权限
  • 建议结合Spring Security进行权限验证

7. 性能考虑

  • 获取流程定义是轻量级操作,可放心调用
  • 如需批量获取,建议使用 createProcessDefinitionQuery() 进行查询

相关 API

  • RepositoryService.createProcessDefinitionQuery() - 查询流程定义
  • RepositoryService.getBpmnModel() - 获取BPMN模型
  • RepositoryService.getProcessDiagram() - 获取流程图
  • RepositoryService.getProcessModel() - 获取流程模型
  • RepositoryService.isProcessDefinitionSuspended() - 检查是否挂起
  • RepositoryService.suspendProcessDefinitionById() - 挂起流程定义
  • RepositoryService.activateProcessDefinitionById() - 激活流程定义

最佳实践

1. 结合流程实例获取流程定义

kotlin
fun getProcessDefinitionFromInstance(processInstanceId: String) {
    val processInstance = runtimeService.createProcessInstanceQuery()
        .processInstanceId(processInstanceId)
        .singleResult()
    
    val processDefinition = repositoryService
        .getProcessDefinition(processInstance.processDefinitionId)
    
    println("当前流程: ${processDefinition.name} V${processDefinition.version}")
}

2. 获取最新版本的流程定义

kotlin
fun getLatestProcessDefinition(processDefinitionKey: String) {
    val processDefinition = repositoryService.createProcessDefinitionQuery()
        .processDefinitionKey(processDefinitionKey)
        .latestVersion()
        .singleResult()
    
    // 然后使用 getProcessDefinition() 获取完整信息
    return repositoryService.getProcessDefinition(processDefinition.id)
}

本文档说明

  • 基于 Flowable 7.1.0 版本编写
  • 所有示例均可直接在 Spring Boot + Kotlin 项目中使用
  • 示例场景来自真实企业应用,具有实际参考价值