成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

SpringBoot整合工作流引擎Activiti

開發(fā) 前端
通過ProcessEngine獲取,Activiti將不同生命周期的服務封裝在不同Service中,包括定義、部署、運行。通過服務類可獲取相關生命周期中的服務信息。

環(huán)境:Springboot2.2.11.RELEASE + Activiti7.1.0.M6 + MySQL

環(huán)境說明:

<dependencies>
  <dependency>
    <groupId>org.activiti.dependencies</groupId>
    <artifactId>activiti-dependencies</artifactId>
    <version>7.1.0.M6</version>
    <type>pom</type>
  </dependency>
  <dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-spring-boot-starter</artifactId>
    <version>7.1.0.M6</version>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.4</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
      <exclusion>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
</dependencies>

不知為何activit7中要吧這security強關聯(lián)。。。

以上是pom.xml中所要引入的依賴。


所有的表:

圖片圖片

表結(jié)構(gòu)說明:

ACT_RE_*: 'RE’表示repository。這個前綴的表包含了流程定義和流程 靜態(tài)資源(圖片、規(guī)則等等)

ACT_RU_*: 'RU’表示runtime。這些運行時的表,包含流程實例,認為,變量,異步任務等運行中的數(shù)據(jù)。Activiti只在流程實例執(zhí)行過程中保持這些數(shù)據(jù),在流程結(jié)束時就會刪除這些記錄。這樣運行時表可以一直很小速度很快。

ACT_HI_*: 'HI’表示history。這些表包含歷史數(shù)據(jù),比如歷史流程實例,遍歷,任務等等。

ACT_GE_*: 'GE’表示general。通用數(shù)據(jù),用于不同場景。

數(shù)據(jù)表分類

通用數(shù)據(jù)(act_ge_*)

圖片圖片

流程定義(act_re_*)

圖片圖片

運行實例(act_ru_*)

圖片圖片

歷史流程(act_hi_*)

圖片圖片

其他

圖片圖片

來源網(wǎng)絡


核心類

ProcessEngine

????流程引擎的抽象,可以通過此類獲取需要的所有服務。

????通過ProcessEngine獲取,Activiti將不同生命周期的服務封裝在不同Service中,包括定義、部署、運行。通過服務類可獲取相關生命周期中的服務信息。

TaskService

????流程運行過程中,每個任務節(jié)點的相關操作接口,如complete,delete,delegate等。
RepositoryService

????流程定義和部署相關的存儲服務。
RuntimeService

????流程運行時相關的服務,如根據(jù)流程好啟動流程實例startProcessInstanceByKey。
HistoryService

????歷史記錄相關服務接口。

關于eclipse中安裝插件就不說了,我是把插件下載下來安裝的,在線安裝不上。

設計請假流程

在src/main/resources下新建processes文件夾,springboot下默認的流程文件定義路徑前綴及文件后綴如下:

圖片圖片

這里可以在application.yml配置文件中更改。

設計一個請假的流程holiday.bpmn

圖片圖片

<?xml versinotallow="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.pack.org">
  <process id="holiday" name="holiday" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <endEvent id="endevent1" name="End"></endEvent>
    <userTask id="usertask1" name="部門經(jīng)理審批" activiti:assignee="${mgr}"></userTask>
    <userTask id="usertask2" name="總經(jīng)理審批" activiti:assignee="${top}"></userTask>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
    <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="endevent1"></sequenceFlow>
    <userTask id="usertask3" name="填寫審批單" activiti:assignee="${assignee}"></userTask>
    <sequenceFlow id="flow4" sourceRef="startevent1" targetRef="usertask3"></sequenceFlow>
    <sequenceFlow id="flow5" sourceRef="usertask3" targetRef="usertask1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_holiday">
    <bpmndi:BPMNPlane bpmnElement="holiday" id="BPMNPlane_holiday">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="505.0" y="60.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="505.0" y="550.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="470.0" y="290.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55.0" width="105.0" x="470.0" y="420.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
        <omgdc:Bounds height="55.0" width="105.0" x="470.0" y="170.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="522.0" y="345.0"></omgdi:waypoint>
        <omgdi:waypoint x="522.0" y="420.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="522.0" y="475.0"></omgdi:waypoint>
        <omgdi:waypoint x="522.0" y="550.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="522.0" y="95.0"></omgdi:waypoint>
        <omgdi:waypoint x="522.0" y="170.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow5" id="BPMNEdge_flow5">
        <omgdi:waypoint x="522.0" y="225.0"></omgdi:waypoint>
        <omgdi:waypoint x="522.0" y="290.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

上面的每一個節(jié)點(任務)都動態(tài)的指派了用戶執(zhí)行。

填寫審批單:${assignee};

部門經(jīng)理審批: ${mgr};

總經(jīng)理審批:${top};

每一個節(jié)點執(zhí)行完成時都需要指明下一個節(jié)點的執(zhí)行人。

配置文件

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.pack.domain
server:
  port: 8080
spring:
  activiti:
    check-process-definitions: true
    db-history-used: true
    history-level: full
    database-schema-update: true
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/activiti?serverTimeznotallow=GMT%2B8
    username: root
    password: xxxxxx
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimumIdle: 10
      maximumPoolSize: 200
      autoCommit: true
      idleTimeout: 30000
      poolName: MasterDatabookHikariCP
      maxLifetime: 1800000
      connectionTimeout: 30000
      connectionTestQuery: SELECT 1

spring.activiti.db-history-used:表示是用歷史表,如果不設置為true那么只會生成17張表,只有設置為true后才會生成25張表。如果不生成歷史表那么,流程圖及運行節(jié)點無法展示。

spring.activiti.history-level:對于歷史數(shù)據(jù),保存到何種粒度,Activiti提供了history-level屬性對其進行配置。history-level屬性有點像log4j的日志輸出級別,該屬性有以下四個值:

  • none:不保存任何的歷史數(shù)據(jù),因此,在流程執(zhí)行過程中,這是最高效的。
  • activity:級別高于none,保存流程實例與流程行為,其他數(shù)據(jù)不保存。
  • audit:除activity級別會保存的數(shù)據(jù)外,還會保存全部的流程任務及其屬性。audit為history的默認值。
  • full:保存歷史數(shù)據(jù)的最高級別,除了會保存audit級別的數(shù)據(jù)外,還會保存其他全部流程相關的細節(jié)數(shù)據(jù),包括一些流程參數(shù)等。

spring.activiti.check-process-definitions:如果不設置為true,那么流程定義必須手動進行部署。

  • sprint security配置,放行任何請求:
  • 服務工具類HolidayService
@Service
public class HolidayService {


  private static final Logger logger = LoggerFactory.getLogger(HolidayService.class);


  @Resource
  private ProcessEngine processEngine;
  @Resource
  private RepositoryService repositoryService ;
  @Resource
  private RuntimeService runtimeService ;
  @Resource
  private TaskService taskService ;


  /**
   * <p>
   * 流程定義的部署 activiti表有哪些?
   * act_re_deployment 流程定義部署表,記錄流程部署信息 
   * act_re_procdef 流程定義表,記錄流程定義信息 
   * act_ge_bytearray 資源表(bpmn文件及png文件)
   * </p>
   * <p>時間:2021年1月22日-下午3:33:00</p>
   * @author xg
   * @return void
   */
  public void createDeploy() {
    Deployment deployment = repositoryService.createDeployment()
        .addClasspathResource("processes/holiday.bpmn")
        .addClasspathResource("processes/holiday.png")
        .name("請假申請單流程")
        .key("holiday")
        .category("InnerP")
        .deploy();
    logger.info("流程部署id: {}", deployment.getId());
    logger.info("流程部署名稱: {}", deployment.getName());
  }
  // 注意這里這個方法是當我們沒有開啟自動部署流程定義時,就需要手動部署。
  /**
   * <p>
   *   流程定義查詢
   * </p>
   * <p>時間:2021年1月22日-下午3:45:02</p>
   * @author xg
   * @param processDefinition
   * @return void
   */
  public List<ProcessDefinition> queryProcessDefinitionByKey(String processDefinition) {
    // 查詢流程定義
    ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
    List<ProcessDefinition> list = processDefinitionQuery.processDefinitionKey(processDefinition).list();
    list.forEach(pd -> {
      logger.info("------------------------------------------------");
      logger.info("流程部署id:{}", pd.getDeploymentId());
      logger.info("流程定義id:{}", pd.getId());
      logger.info("流程定義名稱:{}", pd.getName());
      logger.info("流程定義key:{}", pd.getKey());
      logger.info("流程定義版本:{}", pd.getVersion());
      logger.info("------------------------------------------------");
    });
    return list ;
  }


  /**
   * <p>
   *   刪除流程
   * </p>
   * <p>時間:2021年1月22日-下午4:21:40</p>
   * @author xg
   * @return void
   */
  public void deleteDeployment(String deploymentId) {
    // 設置true 級聯(lián)刪除流程定義,即使該流程有流程實例啟動也可以刪除,設置為false非級別刪除方式,如果流程
    repositoryService.deleteDeployment(deploymentId, true);
  }


  /**
   * <p>
   *   啟動流程實例(比如用戶根據(jù)定義好的流程發(fā)起一個流程的實例(這里的請假流程申請))
   * <p>時間:2021年1月22日-下午4:54:56</p>
   * @author xg
   * @return void
   */
  public void startProcessInstanceById(String processDefinitionId) {
    ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId) ;
    logger.info("流程定義ID: {}", processInstance.getProcessDefinitionId());
    logger.info("流程實例ID: {}", processInstance.getId());
  }
  
  /**
   * <p>
   *   啟動流程實例,指定業(yè)務Key(方便關聯(lián)業(yè)務數(shù)據(jù))(比如用戶根據(jù)定義好的流程發(fā)起一個流程的實例(這里的請假流程申請))
   *   Businesskey(業(yè)務標識)
    啟動流程實例時,指定的businesskey,就會在act_ru_execution #流程實例的執(zhí)行表中存儲businesskey。
    Businesskey:業(yè)務標識,通常為業(yè)務表的主鍵,業(yè)務標識和流程實例一一對應。業(yè)務標識來源于業(yè)務系統(tǒng)。存儲業(yè)務標識就是根據(jù)業(yè)務標識來關聯(lián)查詢業(yè)務系統(tǒng)的數(shù)據(jù)。
    比如:請假流程啟動一個流程實例,就可以將請假單的id作為業(yè)務標識存儲到activiti中,
    將來查詢activiti的流程實例信息就可以獲取請假單的id從而關聯(lián)查詢業(yè)務系統(tǒng)數(shù)據(jù)庫得到請假單信息。
   * <p>時間:2021年1月22日-下午4:54:56</p>
   * @author xg
   * @return void
   */
  public void startProcessInstanceToBussinessKey(String processDefinitionId, String bussinessKey) {
    ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, bussinessKey);
    logger.info("流程定義ID: {}", processInstance.getProcessDefinitionId());
    logger.info("流程實例ID: {}", processInstance.getId());
    logger.info("BussinessKey: {}", processInstance.getBusinessKey()) ;
  }
  
  /**
   *  <p>
   *    設置assignee的取值,用戶可以在界面上設置流程的執(zhí)行人
   *  </p>
   *  <p>時間:2021年1月22日-下午8:30:39</p>
   * @author xg
   * @param processDefinitionId 
   * @return void
   */
  public void startProcessInstanceAssignVariables(String processDefinitionId, Map<String, Object> variables) {
    ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinitionId, variables);
    logger.info("流程定義ID: {}", processInstance.getProcessDefinitionId());
    logger.info("流程實例ID: {}", processInstance.getId());
    logger.info("BussinessKey: {}", processInstance.getBusinessKey()) ;
  }
  
  /**
   *  <p>
   *    查詢指派關聯(lián)的用戶任務
   *  </p>
   *  <p>時間:2021年1月23日-上午11:39:56</p>
   * @author xg
   * @param assignee 關聯(lián)用戶
   * @return List<Task>
   */
  public List<Task> queryTasks(String assignee) {
    TaskQuery query = taskService.createTaskQuery() ;
    return query.taskAssignee(assignee).orderByTaskCreateTime().asc().list() ;
  }
  
  public void executionTask(Map<String, Object> variables, String instanceId) {
    Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult() ;
    if (task == null) {
      logger.error("任務【{}】不存在", instanceId) ;
      throw new RuntimeException("任務【" + instanceId + "】不存在") ;
    }
    taskService.complete(task.getId(), variables) ;
  }


}


  • HolidayController接口
@RestController
@RequestMapping("/holidays")
public class HolidayController {
  
  @Resource
  private HolidayService holidayService ;
  
  /**
   *  <p>查詢制定key的流程審批</p>
   *  <p>時間:2021年1月23日-上午11:17:02</p>
   * @author xg
   * @param key ProcessDefinitionKey
   * @return R
   */
  @GetMapping("")
  public R lists(String key) {
    return R.success(holidayService.queryProcessDefinitionByKey(key)) ;
  }
  
  /**
   *  <p>創(chuàng)建請假流程審批(私有)</p>
   *  <p>時間:2021年1月23日-上午10:31:47</p>
   * @author xg
   * @return R
   */
  @GetMapping("/_deploy")
  public R createDeploy() {
    holidayService.createDeploy();
    return R.success() ;
  }
  
  /**
   *  <p>啟動請假審批流程</p>
   *  <p>時間:2021年1月23日-上午10:32:55</p>
   * @author xg
   * @param userId
   * @param processDefinitionId 流程定義Id
   * @return R
   */
  @GetMapping("/start")
  public R startProcess(String userId, String processDefinitionId) {
    Map<String, Object> variables = new HashMap<>() ;
    variables.put("assignee", userId) ;
    holidayService.startProcessInstanceAssignVariables(processDefinitionId, variables) ;
    return R.success() ;
  }
  
  /**
   *  <p>
   *    查詢指派給我的任務
   *  </p>
   *  <p>時間:2021年1月23日-上午11:41:21</p>
   * @author xg
   * @param userId 用戶Id
   * @return R
   */
  @GetMapping("/tasks")
  public R myTasks(String userId) {
    List<Task> list = holidayService.queryTasks(userId) ;
    // 注意這里需要我們自己組裝下數(shù)據(jù),不然會報錯。
    List<Map<String, Object>> result = list.stream().map(task -> {
      Map<String, Object> res = new HashMap<String, Object>() ;
      res.put("id", task.getId()) ;
      res.put("assignee", task.getAssignee()) ;
      res.put("createTime", task.getCreateTime()) ;
      res.put("bussinessKey", task.getBusinessKey()) ;
      res.put("category", task.getCategory()) ;
      res.put("dueDate", task.getDueDate()) ; // 到期日期
      res.put("desc", task.getDescription()) ;
      res.put("name", task.getName()) ;
      res.put("owner", task.getOwner()) ;
      res.put("instanceId", task.getProcessInstanceId()) ;
      res.put("variables", task.getProcessVariables()) ;
      return res ;
    }).collect(Collectors.toList()) ;
    return R.success(result) ;
  }
  
  /**
   *  <p>
   *    填寫審批單
   *  </p>
   *  <p>時間:2021年1月23日-上午11:57:30</p>
   * @author xg
   * @param Map取值如下
   * @param days 請假天數(shù)
   * @param explain 審批單說明
   * @param instanceId 流程實例ID
   * @param assignee 指定下一個流程執(zhí)行人
   * @return R
   */
  @GetMapping("/apply")
  public R fillApply(@RequestParam Map<String, Object> variables) {
    String instanceId = (String) variables.remove("instanceId") ;
    if (StringUtils.isEmpty(instanceId)) {
      return R.failure("未知任務") ;
    }
    holidayService.executionTask(variables, instanceId);
    return R.success() ; 
  }
  
}

測試:

1、啟動服務

這里放在processes中的流程定義文件已經(jīng)被自動部署上了。查看表act_re_procdef

  1. 查詢制定key的流程審批
    接口:/holidays

圖片圖片

  1. 啟動請假審批流程
    接口:/holidays/start

圖片圖片

參數(shù):
processDefinitionId:流程定義中的ID。
userId:要處理用戶的id。

查看表信息:

圖片圖片

這時候就為用戶id為:10000的生成了一個要處理的任務,填寫審批單。

  1. 查詢指派給我需要處理的任務
    接口:/holidays/tasks

圖片圖片

  1. 填寫審批單
    接口:/holidays/apply

圖片圖片

參數(shù):
mgr:指定下一個節(jié)點處理人。
explain:請假原因。
days:請假天數(shù)。

這里根據(jù)自己的業(yè)務需要去設置。

再次調(diào)用查詢接口userId=10002

圖片圖片

流程已經(jīng)到了部門經(jīng)理。

再次調(diào)用/holidays/apply接口。

圖片圖片

參數(shù):
top:指明總經(jīng)理節(jié)點需要處理的userId。

圖片圖片

再次調(diào)用/holidays/apply接口。(總經(jīng)理處理)

圖片圖片

查詢對應的任務表信息,已經(jīng)沒有數(shù)據(jù)了。

圖片圖片

查詢表:act_hi_actinst

圖片圖片

到此一個流程就走完了。下篇 查看流程圖。

完畢?。?!

責任編輯:武曉燕 來源: 實戰(zhàn)案例錦集
相關推薦

2021-12-17 08:39:39

SpringbootActiviti網(wǎng)關路由

2022-10-26 08:00:43

Activiti工作流BPM

2023-06-12 08:01:57

Camunda工作流引擎

2021-10-14 11:34:05

技術工作流引擎

2023-01-04 08:02:16

工作流架構(gòu)設計

2011-12-14 09:58:58

JavajBPM

2015-07-14 09:26:28

微型工作流引擎設計

2024-10-17 08:39:32

2023-08-02 18:48:23

Flowable工作流引擎

2009-06-11 14:43:34

jbpm工作流引擎jBPM搭建

2009-09-01 18:26:23

C#工作流引擎

2014-07-31 17:03:12

2009-06-11 14:33:11

jbpm工作流引擎什么是jbpm

2021-03-12 06:44:09

Argo Workfl開源項目

2012-05-18 16:55:34

JavaBonita

2013-04-23 10:28:08

IBeamMDAAWF

2024-04-25 08:00:00

DevOps架構(gòu)軟件開發(fā)

2021-03-05 07:47:07

工作流引擎節(jié)點

2009-06-11 14:48:48

jbpm工作流引擎jbpm例子

2012-07-23 10:36:46

工作流
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 福利网站导航 | 久久午夜精品 | 午夜免费网站 | 久久精品青青大伊人av | 国产精品v| 欧美成年网站 | 欧美国产日韩一区二区三区 | av日韩高清 | 丁香一区二区 | 成人av电影免费在线观看 | 国产精品久久久久久久久久久久久 | 丝袜美腿一区二区三区动态图 | 久久久久久黄 | 日韩在线一区二区三区 | 亚洲 欧美 另类 日韩 | 999久久久 | 国产精品a久久久久 | 亚洲精品久久久久久久不卡四虎 | 一区二区三区四区国产精品 | 综合一区二区三区 | 亚洲品质自拍视频网站 | 美女一区二区在线观看 | 久久亚洲二区 | 欧美精品一 | 超碰人人爱 | 亚洲视频二区 | 午夜影院在线播放 | 欧美影院久久 | 四虎精品在线 | 亚洲国产精品网站 | 国产成人精品免费视频大全最热 | 亚洲精品久久久久久宅男 | 亚洲欧美在线视频 | 久久亚洲国产精品日日av夜夜 | 国产精品精品 | 隔壁老王国产在线精品 | 日本不卡免费新一二三区 | 免费一看一级毛片 | 国产精品成人在线播放 | 国产不卡在线观看 | 久久久久一区 |