日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Springboot整合Camunda工作流引擎實現(xiàn)審批流程實例

環(huán)境:Spingboot2.6.14 +
camunda-spring-boot-starter7.18.0

我們提供的服務(wù)有:成都網(wǎng)站制作、做網(wǎng)站、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、金城江ssl等。為超過千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的金城江網(wǎng)站制作公司

環(huán)境配置

依賴配置

7.18.0

  org.camunda.bpm.springboot
  camunda-bpm-spring-boot-starter-webapp
  ${camunda.version}


  org.camunda.bpm.springboot
  camunda-bpm-spring-boot-starter-rest
  ${camunda.version}

應(yīng)用程序配置

camunda.bpm:
  webapp:
    # 設(shè)置管理控制臺的訪問上下文
    application-path: /workflow
  auto-deployment-enabled: true
  admin-user:
    # 配置登錄管理控制臺的用戶
    id: admin
    password: admin
    firstName: admin
  filter:
    create: All tasks
  database:
    #數(shù)據(jù)庫類型
    type: mysql 
    #是否自動更新表信息
    schema-update: true
logging:
  level:
    #配置日志,這樣在開發(fā)過程中就能看到每步執(zhí)行的SQL語句了
    '[org.camunda.bpm.engine.impl.persistence.entity]': debug
---
spring:
  jersey:
    application-path: /api-flow
    type: servlet
    servlet:
      load-on-startup: 0

通過上面的配置后訪問控制臺:http://localhost:8100/workflow/

默認(rèn)是沒有上面的tasks中的內(nèi)容,這里是我之前測試數(shù)據(jù)

環(huán)境準(zhǔn)備好后,接下來就可以設(shè)計工作流程。

上面的camunda-bpm-spring-boot-starter-rest依賴中定義了一系列操作camunda的 rest api 這api的實現(xiàn)是通過jersey實現(xiàn),我們可以通過/api-flow前綴來訪問這些接口,具體有哪些接口,我們可以通過官方提供的camunda-bpm-run-7.18.0.zip

http://localhost:8080/swaggerui/#/

設(shè)計流程

這里設(shè)計兩個節(jié)點的審批流程,經(jīng)理審批---》人事審批 流程。

經(jīng)理審批節(jié)點

人事審批節(jié)點

上面配置了2個用戶任務(wù)節(jié)點,并且為每個任務(wù)節(jié)點都設(shè)置了表達(dá)式,指定節(jié)點的審批人。

最終生成的流程XML內(nèi)容如下:



  
    
      Flow_18pxcpx
    
    
    
      Flow_18pxcpx
      Flow_0n014x3
    
    
    
      Flow_0n014x3
      Flow_0dsfy6s
    
    
      Flow_0dsfy6s
    
    
  
  
    
      
        
      
      
        
      
      
        
      
      
        
      
      
        
        
      
      
        
        
      
      
        
        
      
    
  

部署流程

這里我不通過上面的rest api 進(jìn)行部署,而是通過自定義的接口然后調(diào)用camunda的相關(guān)api來實現(xiàn)流程部署。

上面的流程設(shè)計我是通過vue整合的camunda進(jìn)行設(shè)計,并沒有使用官方提供的設(shè)計器。設(shè)計完成后直接上傳到服務(wù)端。

接口

@RestController
@RequestMapping("/camunda")
public class BpmnController {


  // 上傳路徑
  @Value("${gx.camunda.upload}")
  private String path ;
  
  // 通用的工作流操作api服務(wù)類
  @Resource
  private ProcessService processService ;
  
  @PostMapping("/bpmn/upload")
  public AjaxResult uploadFile(MultipartFile file, String fileName, String name) throws Exception {
    try {
      // 上傳并返回新文件名稱
      InputStream is = file.getInputStream() ;
      File storageFile = new File(path + File.separator + fileName) ;
      FileOutputStream fos = new FileOutputStream(new File(path + File.separator + fileName)) ;
      byte[] buf = new byte[10 * 1024] ;
      int len = -1 ;
      while((len = is.read(buf)) > -1) {
        fos.write(buf, 0, len) ;
      }
      fos.close() ;
      is.close() ;
      // 創(chuàng)建部署流程
      processService.createDeploy(fileName, name, new FileSystemResource(storageFile)) ;
      return AjaxResult.success();
    } catch (Exception e) {
      return AjaxResult.error(e.getMessage());
    }
  }
}

部署流程Service

// 這個是camunda spring boot starter 自動配置
@Resource
private RepositoryService repositoryService ;


public void createDeploy(String resourceName, String name, org.springframework.core.io.Resource resource) {
  try {
    Deployment deployment = repositoryService.createDeployment()
      .addInputStream(resourceName, resource.getInputStream())
      .name(name)
      .deploy();
    logger.info("流程部署id: {}", deployment.getId());
    logger.info("流程部署名稱: {}", deployment.getName());
  } catch (IOException e) {
    throw new RuntimeException(e) ;
  }
}

執(zhí)行上面的接口就能將上面設(shè)計的流程部署到camunda中(其實就是將流程文件保存到了數(shù)據(jù)庫中,對應(yīng)的數(shù)據(jù)表是:act_ge_bytearray)。

啟動流程

啟動流程還是一樣,通過我們自己的接口來實現(xiàn)。

接口

@RestController
@RequestMapping("/process")
public class ProcessController {


  @Resource
  private ProcessService processService ;
  
  // 根據(jù)流程定義id,啟動流程;整個流程需要動態(tài)傳2個參數(shù)(審批人),如果不傳將會報錯
  @GetMapping("/start/{processDefinitionId}")
  public AjaxResult startProcess(@PathVariable("processDefinitionId") String processDefinitionId) {
    Map variables = new HashMap<>() ;
    variables.put("uid", "1") ;
    variables.put("mid", "1000") ;
    processService.startProcessInstanceAssignVariables(processDefinitionId, "AKF", variables) ;
    return AjaxResult.success("流程啟動成功") ;
  }
}

服務(wù)Service接口

@Resource
private RuntimeService runtimeService ;


public ProcessInstance startProcessInstanceAssignVariables(String processDefinitionId, String businessKey, Map variables) {
  ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, businessKey, variables);
  logger.info("流程定義ID: {}", processInstance.getProcessDefinitionId());
  logger.info("流程實例ID: {}", processInstance.getId());
  logger.info("BussinessKey: {}", processInstance.getBusinessKey()) ;
  return processInstance ;
}

流程啟動后就可以查看當(dāng)前需要自己審批的所有審批單

接口實現(xiàn)

@Resource
private TaskService taskService ;
@Resource
private ManagementService managementService ;
// 根據(jù)時間段查詢
public List queryTasksByBusinessAndCreateTime(String assignee, String businessKey, String startTime, String endTime) {
  NativeTaskQuery nativeQuery = taskService.createNativeTaskQuery() ;
  nativeQuery.sql("select distinct RES.* from " + managementService.getTableName(TaskEntity.class) +  " RES "
                  + " left join " + managementService.getTableName(IdentityLinkEntity.class) + " I on I.TASK_ID_ = RES.ID_ "
                  + " WHERE (RES.ASSIGNEE_ = #{assignee} or "
                  + " (RES.ASSIGNEE_ is null and I.TYPE_ = 'candidate' "
                  + " and (I.USER_ID_ = #{assignee} or I.GROUP_ID_ IN ( #{assignee} ) ))) "
                  + " and RES.CREATE_TIME_ between #{startTime} and #{endTime} "
                  + " order by RES.CREATE_TIME_ asc LIMIT #{size} OFFSET 0") ;
  nativeQuery.parameter("assignee", assignee) ;
  nativeQuery.parameter("startTime", startTime) ;
  nativeQuery.parameter("endTime", endTime) ;
  nativeQuery.parameter("size", Integer.MAX_VALUE) ;
  return nativeQuery.list() ;
}

審批流程

流程啟動后,接下來就是各個用戶任務(wù)節(jié)點配置的用戶進(jìn)行審批

接口

@GetMapping("/approve/{id}")
public AjaxResult approve(@PathVariable("id") String instanceId) {
  if (StringUtils.isEmpty(instanceId)) {
    return AjaxResult.error("未知審批任務(wù)") ;
  }
  // 下面的參數(shù)信息應(yīng)該自行保存管理(與發(fā)起審批設(shè)置的指派人要一致)
  Map variables = new HashMap<>() ;
  // 第一個節(jié)點所要提供的遍歷信息(這里就是依次類推,mid等)
  variables.put("uid", "1") ;
  processService.executionTask(variables, instanceId, task -> {}, null) ;
  return AjaxResult.success() ; 
}

服務(wù)Service接口

@Resource
private TaskService taskService ;
@Resource
private RuntimeService runtimeService ;


@Transactional
public void executionTask(Map variables, String instanceId, Consumer consumer, String type) {
  Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult() ;
  if (task == null) {
    logger.error("任務(wù)【{}】不存在", instanceId) ;
    throw new RuntimeException("任務(wù)【" + instanceId + "】不存在") ;
  }
  taskService.setVariables(task.getId(), variables);
  taskService.complete(task.getId(), variables) ;
  long count = runtimeService.createExecutionQuery().processInstanceId(instanceId).count();
  if (count == 0) {
    consumer.accept(task) ;
  }
}

以上就完成了從整個流程的生命周期:

設(shè)計流程 ---》部署流程 ---》啟動流程 ---》審批流程

完畢!?。?/p>
網(wǎng)頁名稱:Springboot整合Camunda工作流引擎實現(xiàn)審批流程實例
網(wǎng)頁路徑:http://www.dlmjj.cn/article/dpdhsoo.html