OA早就流行應用于辦公自動化管理,軟件行業的前輩們相比做過很多OA系統的開發。他們積累了非富的OA開發經驗,以至于JBOSS開發出了一套專門針對OA系統開發的框架——jbpm。
OA使得辦公自動化,那么jbpm就是為了使編寫OA自動化(jbpm需要手動添加的代碼比較少)。同時jbpm可以靈活定制辦公流程與組件。功能十分強大,真是為了解放程序員的雙手(去除那些不必要的重復性工作)。
Jbpm與OA項目,繼續由湯陽光老師傳授。開發經驗非富的老師在講課時都喜歡使用畫圖工具來講解理論知識,流程圖可以讓同學們很快的了解理論結構,視覺化的威力非常大。湯兄講課比較細致,常用的快捷鍵他也有講解以及各方面操作細節。
一、工作流
什么是工作流?就是與某一工作相關的一整套操作流程唄!比如說網絡購物的簡單流程:

(圖1)
是不是每家網購公司的訂單處理流程都一樣呢?當然不是,比如互動網(圖書)與vancl(服裝),vancl可以在有限時間內無條件退貨。這就是工作流程中比較特殊的一項。所以針對不同的工作流程需要,jbpm提供了靈活的設計方案。
Jbpm的工作流管理系統,主要包含兩方面:流程設計器、工作流引擎。工作流引擎是根據用戶設計的工作流程,自動建表并執行工作流任務…。流程設計器是一大亮點,用戶主要使用流程設計器來實現工作流的創建以及各任務之間的關系等。(就像畫流程圖一樣)
二、jbpm流程設計器
湯兄先是直接編寫“processdefinition.xml”配置文件,來實現(圖1)中的流程。然后再使用流程設計器來完成(圖1)的工作流程。兩種方法相比,效率和直觀性相差懸殊。我們就直接畫圖吧!
首先需要安裝eclipse插件,關于jbmp插件的安裝方法網上有很多。我們直接切入正題。
1.創建一個普通的Java工程。
2.在工程中的src目錄上右鍵“new”->”other…”->”JBossjBPM”->”ProcessDefinition”。
3.打開“processdefinition.xml”(如果沒有看到設計器,在文件上右鍵”Open With”->”jBPM”)。
4.添加如下圖形:

5.為每個《TaskNode》添加name(屬性面板General分頁)為(圖1)過程中的內容(非括號內容),添加actor(屬性面板Assignment分頁)為(圖1)過程中的括號里的內容。
6.上面圖形自動生成的“processdefinition.xml”配置文件內容為:
<?xml version="1.0" encoding="UTF-8"?> <process-definition xmlns="" name="test"> <start-state name="start-state1"> <task> <assignment actor-id="開始"></assignment> </task> <transition to="task-node1"></transition> </start-state> <task-node name="task-node1"> <task name="下訂單"> <assignment actor-id="客戶"></assignment> </task> <transition to="task-node2"></transition> </task-node> <task-node name="task-node2"> <task name="發貨"> <assignment actor-id="公司"></assignment> </task> <transition to="task-node3"></transition> </task-node> <task-node name="task-node3"> <task name="收貨"> <assignment actor-id="客戶"></assignment> </task> <transition to="end-state1"></transition> </task-node> <end-state name="end-state1"></end-state> </process-definition> |
7.運行jbpm目錄中的“jbpm-jpdl-3.2.2\server\start.bat”文件,在瀏覽器地址欄中輸入http://localhost:8080/jbpm-console。
8.使用用戶名與密碼為“manager”登陸。
9.選擇“Deploy a new process”(提前將工程中的“processdefinition.xml”、“gpd.xml”、“ processimage.jpg”添加到zip壓縮文件),部署zip壓縮文件。
10.在頁面中會出現導入后的流程名稱,選擇旁邊的“start”開始流程中的第一個任務(如果沒有start,需要先signal。)。點擊“end”結束第一個任務…。
11.選擇左邊的“Process Image”可以查看,流程圖的執行過程。
OK就這么簡單,我們沒有參與編碼工作!
三、jbpmAPI
我們使用編碼實現上面的功能,以了解jbmpAPI的使用。
1.新建立一個普通JAVA工程。
2.將上面生成的三個文件,入到工程src的“helloworld”包中。
3.導入jbm目錄下以及lib目錄下的所有jar文件,部分jar文件在此無用。我只是不想一一列出這些jar文件。
4.在工程中添加一個類。
我們來看一下jbpm的工作流程:
1.部署流程定義:
@Test public void deploy() { //通過jbpm的配置文件創建jbpmContext工廠,并通過工廠創建一個jbpmContext實例。 JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); //通過資源文件載入工作流程定義 ProcessDefinition pd = ProcessDefinition.parseXmlResource("helloworld/processdefinition.xml"); try { //部署工作流程定義 jbpmContext.deployProcessDefinition(pd); } catch (RuntimeException e) { //如果出現異常,則設置回滾標記。 jbpmContext.setRollbackOnly(); throw e; } finally{ //如果沒出現異常則保存后關閉,否則回滾后關閉。 jbpmContext.close(); } } |
創建jbpmContext工廠有2種方式(6個方法):
(1).使用“processdefinition.xml”文件:
ProcessDefinition.parseXmlResource(String xml);
ProcessDefinition.parseXmlResource(String xmlResource);
ProcessDefinition.parseXmlInputStream(InputStream inputStream);
ProcessDefinition.parseXmlReader(Reader reader);
(2).使用zip文件,jbpm中的JBOSS WEB容器使用的是zip:
ProcessDefinition.parseParZipInputStream(ZipInputStream zipInputStream);
ProcessDefinition.parseParResource(String parResource);
3. 執行流程(流程實例)、啟動/創建(signal)
@Test public void startProcessInstance() { JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); ProcessDefinition pd = jbpmContext.getGraphSession().findLatestProcessDefinition("helloworld"); //創建一個工作流程的實例,就像定義一個類實例一樣。工作流程定義好比類,工作流程實例好比是類的實例。 ProcessInstance pi = pd.createProcessInstance(); //進入工作流 pi.getRootToken().signal(); jbpmContext.close(); } |
4.查看/獲取 任務列表(某一任務節點,只能被對應Actor看到)
@Test public void getTaskList() { JbpmConfiguration jbpmCfg = JbpmConfiguration .getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); // 獲取任務列表 List<TaskInstance> list = jbpmContext.getTaskList("客戶"); for (TaskInstance item : list) { //下面每一行加個“//”是湯兄的技巧哦!~ Ctrl+Shift+F也改變不了它的排版。 System.out.println("id=" + item.getId()// + ",name=" + item.getName()// + ",actorId=" + item.getActorId()// + ",create=" + item.getCreate()// + ",start=" + item.getStart()// + ",end=" + item.getEnd()); } jbpmContext.close(); } |
5.開始/結束 辦理任務
// 開始任務 @Test public void startTask() { JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); // 開一個任務 TaskInstance taskIns = jbpmContext.getTaskInstance(1); taskIns.start(); jbpmContext.close(); } // 結束任務 @Test public void endTask() { JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); //結束一個任務,然后跳轉到下一個任務 TaskInstance taskIns = jbpmContext.getTaskInstance(3); taskIns.end(); jbpmContext.close(); } |
6.4-5循環。
四、jbpm中的流程變量
一個工作流程中包含多個任務,比如上邊的網購。客戶生成了一個訂單,店家需要處理訂單并發貨。這兩個任務間就需要一個“訂單變量”。
首先我們在工程中添加一個Order類(domain)。jbpm使用hibernate框架進行數據庫操作,所以需要為Order類添加一個hibernate映射文件,并添加hibernate的配置文件。在jbpm中使用變量的代碼如下:
添加變量:
@Test public void setVariable() { // 加載配置,創建context JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance(); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); //獲取流程定義 ProcessDefinition proDef = jbpmContext.getGraphSession() .findLatestProcessDefinition("helloworld"); ProcessInstance proIns = proDef.createProcessInstance(); //創建一個order對象并保存 Order order = new Order(); order.setName("*****jbpmVariableTest*****"); ContextInstance conIns = proIns.getContextInstance(); conIns.setVariable("order", order); proIns.getRootToken().signal(); //關閉后自動保存 jbpmContext.close(); } |
獲取變量:
@Test public void getVariable() { // 加載配置,創建context JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance(); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); // 根據任務實例ID獲取任務 TaskInstance task = jbpmContext.getTaskInstance(17); task.start(); //幫助JbpmContext分擔工作的ContextInstance ContextInstance conIns = task.getProcessInstance().getContextInstance(); //獲取變量 Order order = (Order) conIns.getVariable("order"); System.out.println(order.getName()); task.end(); jbpmContext.close(); } |
在總結jbpm的過程中還是遇到一些問題的,感覺jbpm比較大。今天是第一天學習它,希望在以后的學習課程中會掌握它。
加油!