首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

jBPM3入門實戰:基於MySQL的簡單報銷流程完整實現

     編輯:Java 相關知識

專案背景與核心概念速覽

jBPM(Java Business Process Management)是經典的開源工作流引擎。本文基於jBPM 3.2版本,使用MySQL數據庫,完整演示一個「員工填單→經理審批→財務審批→結束」的報銷流程,涵蓋環境搭建、流程定義、API調用、單元測試全鏈路。

核心概念對照表

概念說明運行時對應
ProcessDefinition流程靜態定義:節點、轉移、業務邏輯部署後存入數據庫
ProcessInstance流程運行實例,含啟動/結束時間、變量等每次啟動創建一個
Task節點中定義的具體工作項屬於ProcessDefinition
TaskInstance任務運行實態:創建/開始/結束時間、辦理人屬於ProcessInstance,三種狀態:create/start/end
Actor參與者標識,僅需actorId,具體用戶解析由業務層完成任務分配依據
Token執行指針,指向當前活動節點,樹狀結構支持並發,唯一root token運行期核心概念

環境搭建:MySQL + Hibernate配置

1. 數據庫準備

  • 創建數據庫jbpm,字符集UTF-8
  • 引入mysql-connector-java-5.1.5-bin.jar(注意:3.2.0-alpha版本有兼容性問題)

2. hibernate.cfg.xml關鍵配置

<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///jbpm</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>
建議顯式指定MySQLInnoDBDialect以支持事務與外鍵。

流程定義:processdefinition.xml

<?xml version="1.0" encoding="UTF-8"?>
<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="test">
    <start-state name="start">
        <transition to="fillForm"/>
    </start-state>

    <task-node name="fillForm">
        <task name="填寫報銷單">
            <assignment actor-id="employee"/>
        </task>
        <transition to="managerDecide"/>
    </task-node>

    <task-node name="managerDecide">
        <task name="經理審批">
            <assignment actor-id="manager"/>
        </task>
        <transition to="finaceAudit"/>
    </task-node>

    <task-node name="finaceAudit">
        <task name="財務審批">
            <assignment actor-id="finace"/>
        </task>
        <transition to="end"/>
    </task-node>

    <end-state name="end"/>
</process-definition>

特點:順序流、固定辦理人(actor-id)、無條件分支,適合入門理解基礎API。

工程目錄結構

src/
├── cn/senta/test/TestJBPM.java      # JUnit測試類
├── cn/senta/bx/processdefinition.xml # 流程定義文件
└── hibernate.cfg.xml                # Hibernate配置
lib/
├── jbpm-3.2.x.jar
├── hibernate-3.x.jar
├── mysql-connector-java-5.1.5-bin.jar
└── ... 其他依賴
工程目錄結構截圖

工程目錄結構截圖

核心API操作步驟與JUnit測試代碼

package cn.senta.test;

import java.util.List;
import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.db.GraphSession;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.taskmgmt.exe.TaskInstance;
import junit.framework.TestCase;

public class TestJBPM extends TestCase {

    // 1. 創建表結構(僅首次運行)
    public void testCreateSchema() {
        JbpmConfiguration.getInstance().createSchema();
        System.out.println("數據庫表創建成功!");
    }

    // 2. 部署流程定義
    public void testDeployProcessDefinition() {
        JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
        try {
            ProcessDefinition pd = ProcessDefinition.parseXmlResource(
                "cn/senta/bx/processdefinition.xml"
            );
            ctx.deployProcessDefinition(pd);
        } finally { ctx.close(); }
        System.out.println("流程部署成功!");
    }

    // 3. 啟動流程實例
    public void testStartProcessInstance() {
        JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
        try {
            GraphSession gs = ctx.getGraphSession();
            ProcessDefinition pd = gs.findLatestProcessDefinition("test");
            ProcessInstance pi = new ProcessInstance(pd);
            ctx.save(pi);
            pi.signal(); // 從start-state推進到第一個task-node
        } finally { ctx.close(); }
        System.out.println("流程實例啟動成功!");
    }

    // 4. 獲取指定用戶任務列表
    @SuppressWarnings("unchecked")
    public void testGetTaskList() {
        String actorId = "employee";
        JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
        try {
            List<TaskInstance> tasks = ctx.getTaskList(actorId);
            for (TaskInstance ti : tasks) {
                System.out.printf("id=%d, name=%s, create=%s, start=%s, end=%s%n",
                    ti.getId(), ti.getName(), ti.getCreate(), ti.getStart(), ti.getEnd());
            }
        } finally { ctx.close(); }
        System.out.println("任務列表獲取成功!");
    }

    // 5. 開始任務(設置開始時間、辦理人)
    public void testStartTask() {
        long taskId = 1; // 從上一步獲取
        JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
        try {
            TaskInstance ti = ctx.getTaskInstance(taskId);
            ti.start(); // 狀態變為start
            ctx.save(ti);
        } finally { ctx.close(); }
        System.out.println("任務開始成功!");
    }

    // 6. 結束任務(觸發流程流轉至下一節點)
    public void testEndTask() {
        long taskId = 1;
        JbpmContext ctx = JbpmConfiguration.getInstance().createJbpmContext();
        try {
            TaskInstance ti = ctx.getTaskInstance(taskId);
            ti.end(); // 狀態變為end,token沿transition移動
            ctx.save(ti);
        } finally { ctx.close(); }
        System.out.println("任務結束成功,流程自動流轉!");
    }
}

關鍵執行流程說明

  1. testCreateSchema:自動建表,生成JBPM_*系列表。
  2. testDeployProcessDefinition:解析XML,持久化ProcessDefinition及關聯Task/Transition。
  3. testStartProcessInstance:創建ProcessInstance,調用signal()從start-state推進到fillForm任務節點,生成TaskInstance(狀態create)。
  4. testGetTaskList:員工查詢待辦任務,獲取fillForm對應的TaskInstance。
  5. testStartTask:員工領取任務,start()設置開始時間、狀態變start。
  6. testEndTask:員工提交,end()設置結束時間、狀態變end,token自動沿transition移動到managerDecide,生成經理的TaskInstance。
實際業務中,start()與end()通常合併在「提交」一個動作中;此處拆分演示API語義。

常見問題與避坑指南

問題原因解決
創建表報錯MySQL驅動版本不匹配使用5.1.x及以上穩定版驅動
部署報解析錯誤XML命名空間或標簽拼寫錯誤對照jPDL 3.2 XSD校驗,注意task-node/task/assignment層次
啟動實例無任務生成未調用signal()或start-state無出口transition檢查流程定義與啟動代碼
任務列表為空actorId不匹配或任務已被領取/完成確認assignment actor-id與查詢actorId一致
end()後流程未流轉目標節點無入口transition或條件不滿足檢查transition配置,無條件transition無需guard

擴展方向

  • 動態分配辦理人:使用AssignmentHandler接口,根據流程變量決定actorId。
  • 表單數據綁定:結合ContextInstance設置/獲取流程變量,實現報銷金額、事由等業務數據流轉。
  • 決策分支:在managerDecide節點添加decision節點,根據金額走不同審批路徑。
  • 事件監聽:在節點enter/leave/transition上掛載ActionHandler實現郵件通知、日誌記錄等橫切邏輯。

總結

本文通過完整可運行的代碼示例,演示了jBPM3從建表、部署、啟動、任務查詢、處理到流轉的核心API鏈路。掌握JbpmContext、ProcessInstance、TaskInstance、Token四大運行時對象的交互關係,是進階學習jBPM複雜流程建模、持久化策略、集群部署的基石。雖然jBPM3已停止維護,但其核心設計思想(PDL、Token驅動、命令模式)對理解Activiti、Flowable、Camunda等新一代引擎仍有極高參考價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved