OA早就流行應(yīng)用于辦公自動(dòng)化管理,軟件行業(yè)的前輩們相比做過很多OA系統(tǒng)的開發(fā)。他們積累了非富的OA開發(fā)經(jīng)驗(yàn),以至于JBOSS開發(fā)出了一套專門針對OA系統(tǒng)開發(fā)的框架——jbpm。
OA使得辦公自動(dòng)化,那么jbpm就是為了使編寫OA自動(dòng)化(jbpm需要手動(dòng)添加的代碼比較少)。同時(shí)jbpm可以靈活定制辦公流程與組件。功能十分強(qiáng)大,真是為了解放程序員的雙手(去除那些不必要的重復(fù)性工作)。
Jbpm與OA項(xiàng)目,繼續(xù)由湯陽光老師傳授。開發(fā)經(jīng)驗(yàn)非富的老師在講課時(shí)都喜歡使用畫圖工具來講解理論知識(shí),流程圖可以讓同學(xué)們很快的了解理論結(jié)構(gòu),視覺化的威力非常大。湯兄講課比較細(xì)致,常用的快捷鍵他也有講解以及各方面操作細(xì)節(jié)。
一、工作流
什么是工作流?就是與某一工作相關(guān)的一整套操作流程唄!比如說網(wǎng)絡(luò)購物的簡單流程:
(圖1)
是不是每家網(wǎng)購公司的訂單處理流程都一樣呢?當(dāng)然不是,比如互動(dòng)網(wǎng)(圖書)與vancl(服裝),vancl可以在有限時(shí)間內(nèi)無條件退貨。這就是工作流程中比較特殊的一項(xiàng)。所以針對不同的工作流程需要,jbpm提供了靈活的設(shè)計(jì)方案。
Jbpm的工作流管理系統(tǒng),主要包含兩方面:流程設(shè)計(jì)器、工作流引擎。工作流引擎是根據(jù)用戶設(shè)計(jì)的工作流程,自動(dòng)建表并執(zhí)行工作流任務(wù)…。流程設(shè)計(jì)器是一大亮點(diǎn),用戶主要使用流程設(shè)計(jì)器來實(shí)現(xiàn)工作流的創(chuàng)建以及各任務(wù)之間的關(guān)系等。(就像畫流程圖一樣)
二、jbpm流程設(shè)計(jì)器
湯兄先是直接編寫“processdefinition.xml”配置文件,來實(shí)現(xiàn)(圖1)中的流程。然后再使用流程設(shè)計(jì)器來完成(圖1)的工作流程。兩種方法相比,效率和直觀性相差懸殊。我們就直接畫圖吧!
首先需要安裝eclipse插件,關(guān)于jbmp插件的安裝方法網(wǎng)上有很多。我們直接切入正題。
1.創(chuàng)建一個(gè)普通的Java工程。
2.在工程中的src目錄上右鍵“new”->”other…”->”JBossjBPM”->”ProcessDefinition”。
3.打開“processdefinition.xml”(如果沒有看到設(shè)計(jì)器,在文件上右鍵”O(jiān)pen With”->”jBPM”)。
4.添加如下圖形:
5.為每個(gè)《TaskNode》添加name(屬性面板General分頁)為(圖1)過程中的內(nèi)容(非括號(hào)內(nèi)容),添加actor(屬性面板Assignment分頁)為(圖1)過程中的括號(hào)里的內(nèi)容。
6.上面圖形自動(dòng)生成的“processdefinition.xml”配置文件內(nèi)容為:
<?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="發(fā)貨"> <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.運(yùn)行jbpm目錄中的“jbpm-jpdl-
8.使用用戶名與密碼為“manager”登陸。
9.選擇“Deploy a new process”(提前將工程中的“processdefinition.xml”、“gpd.xml”、“ processimage.jpg”添加到zip壓縮文件),部署zip壓縮文件。
10.在頁面中會(huì)出現(xiàn)導(dǎo)入后的流程名稱,選擇旁邊的“start”開始流程中的第一個(gè)任務(wù)(如果沒有start,需要先signal。)。點(diǎn)擊“end”結(jié)束第一個(gè)任務(wù)…。
11.選擇左邊的“Process Image”可以查看,流程圖的執(zhí)行過程。
OK就這么簡單,我們沒有參與編碼工作!
三、jbpmAPI
我們使用編碼實(shí)現(xiàn)上面的功能,以了解jbmpAPI的使用。
1.新建立一個(gè)普通JAVA工程。
2.將上面生成的三個(gè)文件,入到工程src的“helloworld”包中。
3.導(dǎo)入jbm目錄下以及lib目錄下的所有jar文件,部分jar文件在此無用。我只是不想一一列出這些jar文件。
4.在工程中添加一個(gè)類。
我們來看一下jbpm的工作流程:
1.部署流程定義:
@Test public void deploy() { //通過jbpm的配置文件創(chuàng)建jbpmContext工廠,并通過工廠創(chuàng)建一個(gè)jbpmContext實(shí)例。 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) { //如果出現(xiàn)異常,則設(shè)置回滾標(biāo)記。 jbpmContext.setRollbackOnly(); throw e; } finally{ //如果沒出現(xiàn)異常則保存后關(guān)閉,否則回滾后關(guān)閉。 jbpmContext.close(); } } |
創(chuàng)建jbpmContext工廠有2種方式(6個(gè)方法):
(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. 執(zhí)行流程(流程實(shí)例)、啟動(dòng)/創(chuàng)建(signal)
@Test public void startProcessInstance() { JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); ProcessDefinition pd = jbpmContext.getGraphSession().findLatestProcessDefinition("helloworld"); //創(chuàng)建一個(gè)工作流程的實(shí)例,就像定義一個(gè)類實(shí)例一樣。工作流程定義好比類,工作流程實(shí)例好比是類的實(shí)例。 ProcessInstance pi = pd.createProcessInstance(); //進(jìn)入工作流 pi.getRootToken().signal(); jbpmContext.close(); } |
4.查看/獲取 任務(wù)列表(某一任務(wù)節(jié)點(diǎn),只能被對應(yīng)Actor看到)
@Test public void getTaskList() { JbpmConfiguration jbpmCfg = JbpmConfiguration .getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); // 獲取任務(wù)列表 List<TaskInstance> list = jbpmContext.getTaskList("客戶"); for (TaskInstance item : list) { //下面每一行加個(gè)“//”是湯兄的技巧哦!~ 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.開始/結(jié)束 辦理任務(wù)
// 開始任務(wù) @Test public void startTask() { JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); // 開一個(gè)任務(wù) TaskInstance taskIns = jbpmContext.getTaskInstance(1); taskIns.start(); jbpmContext.close(); } // 結(jié)束任務(wù) @Test public void endTask() { JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance("jbpm.cfg.xml"); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); //結(jié)束一個(gè)任務(wù),然后跳轉(zhuǎn)到下一個(gè)任務(wù) TaskInstance taskIns = jbpmContext.getTaskInstance(3); taskIns.end(); jbpmContext.close(); } |
6.4-5循環(huán)。
四、jbpm中的流程變量
一個(gè)工作流程中包含多個(gè)任務(wù),比如上邊的網(wǎng)購。客戶生成了一個(gè)訂單,店家需要處理訂單并發(fā)貨。這兩個(gè)任務(wù)間就需要一個(gè)“訂單變量”。
首先我們在工程中添加一個(gè)Order類(domain)。jbpm使用hibernate框架進(jìn)行數(shù)據(jù)庫操作,所以需要為Order類添加一個(gè)hibernate映射文件,并添加hibernate的配置文件。在jbpm中使用變量的代碼如下:
添加變量:
@Test public void setVariable() { // 加載配置,創(chuàng)建context JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance(); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); //獲取流程定義 ProcessDefinition proDef = jbpmContext.getGraphSession() .findLatestProcessDefinition("helloworld"); ProcessInstance proIns = proDef.createProcessInstance(); //創(chuàng)建一個(gè)order對象并保存 Order order = new Order(); order.setName("*****jbpmVariableTest*****"); ContextInstance conIns = proIns.getContextInstance(); conIns.setVariable("order", order); proIns.getRootToken().signal(); //關(guān)閉后自動(dòng)保存 jbpmContext.close(); } |
獲取變量:
@Test public void getVariable() { // 加載配置,創(chuàng)建context JbpmConfiguration jbpmCfg = JbpmConfiguration.getInstance(); JbpmContext jbpmContext = jbpmCfg.createJbpmContext(); // 根據(jù)任務(wù)實(shí)例ID獲取任務(wù) TaskInstance task = jbpmContext.getTaskInstance(17); task.start(); //幫助JbpmContext分擔(dān)工作的ContextInstance ContextInstance conIns = task.getProcessInstance().getContextInstance(); //獲取變量 Order order = (Order) conIns.getVariable("order"); System.out.println(order.getName()); task.end(); jbpmContext.close(); } |
在總結(jié)jbpm的過程中還是遇到一些問題的,感覺jbpm比較大。今天是第一天學(xué)習(xí)它,希望在以后的學(xué)習(xí)課程中會(huì)掌握它。
加油!