徐海嘯 董颯 魏楓林 于美銘 張巖
(1.吉林大學計算機科學與技術學院 吉林省長春市 130012 2.吉林大學公共計算機教學與研究中心 吉林省長春市 130012)
在計算機技術的應用中工作流技術可以稱的上是一個重要的方面,同時在并行活動執行過程中也是一項非常重要的技術,在本文小結我們主要介紹了工作流管理技術的研究現狀以及發展歷史,并且全面的闡述了工作流理論的一些相關概念、技術成果和研究內容,
目前,在國內工作流技術的研究已經開展多年,有很多的技術人士已經從事了原型系統的開發,并且很多實驗室已經研制出來先進的原型系統,研究人員從工作流系統的可行性、實用性、事務、安全、模型、架構等多方面考慮,不斷地提高系統的使用價值,而且大量的學術論文被撰寫出來共研發人員參考。21 世紀以后,隨著信息產業的興起,和工作流技術相關的標準化組織也逐漸的成立,多個組織也都相繼的提出了各自的工作流技術的標準化規則,比較權威的規范有WSFL 和XLANG 等。
設計和實現基于數據文件處理的工作流管理系統。構建系統的總體結構,實現系統的三個組成部分:流程定義、流程控制、流程管理。建立流程定義方法、用戶與系統進行交互的界面等;實現流程控制的數據結構、方法以及一些算法;實現流程管理中的界面、關鍵功能。解決工作流管理的問題,實現工作流間各個模塊的信息交互,協同工作;實現對工作流任務狀態進行跟蹤與監控,達到工作流模塊間的協調運行。
1993年工作流管理聯盟(Workflow Management Coalition,WfMC)作為工作流管理的標準化組織而成立,標志著工作流技術逐步走向成熟。WfMC 對工作流給出定義為:工作流是指一類能夠完全自動執行的經營過程,根據一系列過程規則,將文檔、信息或任務在不同的執行者之間進行傳遞與執行[1][2][3]。
WfMS 定義的工作流管理系統為,工作流管理系統(Workflow Management System, WfMS)是一個軟件系統,它完成工作量的定義和管理,并按照在系統中預先定義好的工作流邏輯進行工作流實例的執行。工作流管理系統不是企業的業務系統,而是為企業的業務系統的運行提供了一個軟件的支撐環境[4]。工作流管理系統(Workflow Management System,WFMS)是定義、創建、執行工作流的系統。
任何的系統在設計和實施之前都要進行需求的分析,正因為有著相應的需求所以人們才會來開發相應的產品。在軟件工程中,需求分析指的是在建立一個新的或改變一個現存的電腦系統時描寫新系統的目的、范圍、定義和功能時所要做的所有的工作。需求分析是軟件工程中的一個關鍵過程。在這個過程中,系統分析員和軟件工程師確定顧客的需要。只有在確定了這些需要后,他們才能夠分析和尋求新系統的解決方法。需求分析階段的任務是確定軟件系統功能,接下來我將要詳細的敘述本系統所要實現的功能。如下:
本系統主要的功能是基于工作流的操作是對文件的處理上,日常生活和工作中,都要處理大量的文件數據,并且對文件數據進行整理、收集、統計等等一系列工作,那么本系統就從日常出發,從用戶的使用情況考慮,提供了以下幾大文本處理功能:
刪除功能:在正常的Window下,刪除文件是一件很簡單的事情,并不繁瑣,但是Window 并沒有提供多樣的刪除功能,比如:刪除指定行,刪除含有特定標示的字段或者行數等等。這些擴展的工作都需要用戶自己手動的去操作,手動定位到指定行,手動搜索特俗字段等等。操作起來可想而知十分不方便。基于以上觀點,本系統提供了多樣式的刪除功能(行數,字段)等,只需要把要操作的文件拖拽到軟件指定位置,然后在系統中填寫上相應的參數,就可以按照自己的意愿對文本進行多樣式的刪除操作,增強了用戶的體驗也方便了用戶的操作。
合并功能:在平時的工作處理中,或多或少的我們會涉及到多個文本文件的合并操作,那么Window 自身是不提供多文本合并功能的,兩個文本文件的合并可能相對來將不算復雜,復制兩個文本到指定目錄下面即可,但是如果一旦操作的文件數目多起來,對用戶來講一定會是一件乏味枯燥的事情,而且數目多的時候,也會降低操作的正確性,提高誤差。因此本系統需要提供多文本文件的合并操作,用程序去實現合并功能,操作簡單,而且可靠性也得到了提升,用戶只需要把合并的多個文件拖拽到指定位置,然后設定一個文件作為合并后的目錄,執行操作。簡單操作、快速準確。
內容替換:任何一個編輯器都會提供這個功能,操作系統自帶的文本編輯器也提供了內容替換功能,相對其它的文本編輯器來講可能功能簡單些不支持正則表達式。本系統中也只是提供了簡單的操作,我們并不是把內容替換作為重要的討論范圍,因為簡單的文本替換就可以滿足用戶的要求。之所以把這個功能考慮在系統中,是為了工作流操作。在這里不做太多的介紹和深入的研究。
文本比較:這是個非常常用的功能,尤其在項目開發、版本升級的過程中,至關重要。有的時候我們會對比一下代碼的改動點,看看自己的代碼和之前有什么不同,如果用肉眼去觀察對比,那將是一件令你痛心的事情,甚至眼花繚亂也看不出什么名堂來。所以有了文本比較功能這個工作就變得簡單了。目前市場上最好的文本比較產品是Compare 軟件,這個軟件的功能十分強大,比較的結果更是一目了然大快人心。在本系統中實現的功能無法和compare 相提并論,自愧不如。我的文本比較功能只能以行為單位進行比較,比較的結果也會輸出到result 文件中。至于結果文件的顯示格式我們在下面的章節中會詳細的介紹。
內容統計:操作系統現有的文本編輯器并沒有提供內容統計相關的功能,不像word office 這些商用的軟件集成了這個功能。有的時候我們需要知道整個文本的行數、字符數、不同字段出現的頻數等等。如果手工的操作起來,尤其字符數那將是一個很繁瑣的工作。因此在本系統中我們開發了多功能的內容統計功能,包括文本的行數、文本的總字數、相應的字符出現的頻數。在需求分析中,我們的設計思想都是采用拖拽的方式來獲取操作的文件,然后在文本域中輸入執行參數。執行操作。
重命名:重命名操作系統中已經提供,但是由于鼠標鍵盤操作比較繁瑣,所以我們把這個功能設計到里面來,能夠方便用戶進行批處理的更名操作,同時也是為了增加工作流的定義形式,打造多種文件操作方式。
行排序:行排序操作是Window 系統無法提供的,甚至一般的文本編輯器也都不提供此項功能,而且行排序在特定的情況是會被頻繁使用的,因此有必要將此功能設計在內,作為需求分析的一部分。但是我們開發的比較簡單,系統只能提供按行排序,用戶可以選擇是按照升序還是降序操作,至于更加多樣的排序操作還有待開發。在此不做過多的說明。
工作流操作:這個是本系統的重點,也是實現的難點所在。在工作流模式下面我們可以指定上述操作的執行順序,也就是順序執行,前一個操作的輸出可以作為后一個操作的輸入,以用戶的意向為主導,自己定義工作流,對系統提供的功能任意組合,來達到用戶所要完成的工作。而且我們還會給用戶提供一個意見窗口,來不斷地完善系統的基本功能。工作流模式是系統的靈魂,上面所講述的基本操作都是為工作流模式做鋪墊,所以本系統主要任務就是實現工作流模式的管理和定義。
利用WindowBuilder 插件來完成本次畢設的界面設計,開發者可以把主要的精力投入到系統內部的實現上面,而不用過多的去關心怎么設計和實現界面,同時也免去了重復式的硬編碼過程,給開發者帶來便捷。下面我會把界面設計的過程詳細的呈現給大家。
功能區:首先在WindowBuilder 工程中新建了一個JFrame 類,取名為OperatorUI.java,本系統的主要界面就是在這個類中實現的,包含了所有的操作。界面的風格很簡潔有層次性,頁面的左側是一系列的操作按鈕,包含了上面介紹的幾大基本操作,主要是一系列的Jbutton 組件,并且每一個JButton 組件都添加了事件監聽器。WindowBuilder 插件真是一個功能強大的界面設計軟件,如果采用硬編碼的形式下,我們對組件添加事件監聽器要一步一步的手工編寫匿名內部類,但是,現在只需要一步就可以完成,我們只需要雙擊JButton 按鈕,系統就會自動的生成相應代碼,并且,鼠標也會跳轉到代碼區,我們只需要在鼠標跳轉處寫上事件的處理邏輯即可,非常的便捷。由于WindowBuilder 的設計中組件都是拖拽的方式,因此本系統中的所有JPane 都是采用絕對布局管理器,組件拖放的位置就是程序執行時的位置。這只是頁面左側的幾個功能按鈕介紹,并且按鈕已經添加了事件處理。我們把這個區域的設計取名為功能區。
操作區:在介紹操作區之前有必要先了解一下CardLayout布局,卡片布局能夠讓多個組件共享同一個顯示空間,共享空間的組件之間的關系就像一疊牌,組件疊在一起,初始時顯示該空間中第一個添加的組件,通過CardLayout 類提供的方法可以切換該空間中顯示的組件。
操作區,是用戶在功能區選定一個功能按鈕之后進行操作的頁面,由于每個功能的操作不一樣,輸入的參數、輸出的格式也大相徑庭,無法用一個頁面來實現,所以一個主要的問題就是不同的功能之間涉及到頁面的切換。故而,操作區的設計采用CardLayout布局管理器。其主要的思想是,新建一個JPane 坐為最底層的面板,這個面板采用卡片布局管理器,承接多個操作的頁面,在本系統中基于底層面板我們新建了6 個JPane,其中有一個負責頁面的初始化,顯示基本的提示信息,剩余的5 個JPane 則是真正的操作區,每一個面板都對應著左側的一個功能按鈕,面板中有相應的輸入參數,和相應的輸出結果。唯一的共同點就是,每個面板都有一個執行按鈕,沒有把執行操作抽離出來,是為了提高程序的耦合度。在上一小節中介紹了功能區按鈕的事件處理,其主要的工作就是在點擊按鈕的時候,實現相應頁面之間的切換,切換的操作也很簡單,得益于WindowBuilder,當添加不同的面板到卡片布局管理器中的時候,系統會自動的給這個面板分配一個ID 號,并且這個號碼是編寫在代碼中的,在程序執行的時候如果想跳轉到相應的頁面,只需要利用卡片布局管理器提供的show(ID)方法就可以完成,可想而知,功能區按鈕的事件處理邏輯就是提供一個顯示方法,在此不做過多的闡述。
卡片布局管理器的優勢在于頁面之間的便捷切換,最初的設計是采用簡單的JFrame 來實現,但是程序開發到一半發現很難實現,而且程序的性能很低,每一個頁面都用一個窗口組件來隱藏、顯示,給用戶帶來的體驗也是相當的差,而且對于開發者來講代碼工作量也是相當的大,而卡片布局管理器完美的解決了這個問題。
工作流模式區:這個區域的功能是程序的靈魂所在,也是本次畢設的主旨,但是從其界面設計上來講,界面非常簡潔,整個工作流模式區只有三個按鈕,一個工作流模式按鈕,一個退出工作流模式按鈕,一個執行工作流模式。并且每一個按鈕都添加了事件監聽器,至于內部的實現邏輯和相應的操作,我們將會在下面的章節功能的設計和實現中進行介紹。這里只做簡單敘述,工作流模式按鈕主要的任務是區別于功能區的基本操作,以工作流的形式執行程序。退出工作流模式,回復到基本操作模式,本系統涉及到的兩個模式的操作類型就是通過這兩個按鈕來進行切換的。執行工作流模式,程序執行定義好的工作流。其實從三個按鈕的名字上面就可以看出來每個按鈕的功能。在區域的右側中心位置,有一個文本顯示組件(JTextField)用來顯示工作流的具體操作內容,只是簡單的顯示出功能順序,并不能顯示出相應的輸入和輸出。所以這個區域的界面也就不用花費太多的文章來介紹。
工作流區域最初的設計是采取拖拽組件的方式來定義工作流,但是由于每個功能的輸入參數不好控制,如果在同一個區域內給每個功能都提供一個入參的接口,那么最終構思出來的界面十分混亂,極其的不美觀,所以只好放棄這個設計方案。采用了操作簡單、可控制的順序點擊方案,這個方案雖然不像剛剛提到的拖拽方式時尚,但是無論從開發者還是用戶的角度來講,都是一件大快人心的事情。便捷開發,方便用戶操作,提高用戶體驗。
在上面的小結中我們介紹了界面的設計和實現,那么界面的下一層設計就是功能了,美觀的界面是呈現給用戶的,換句話說,界面只不過是程序和人的一個交互界面,沒有實質性的作用,而對于開發者來講,程序才是軟件的靈魂,我們看待界面只不過是一個面具罷了,我們提供給用戶一個接口來和內部進行交流溝通,這才是開發者眼中的界面。程序的開發目的就是實現其應該具備的功能,美觀的界面加上高質量的代碼才可稱的上是一個成功的軟件設計,所以本小結中我們將會重點介紹功能的設計和實現,和上一小節中的界面設計相吻合,到達界面功能一體化。
在需求分析的章節中我們對系統的基本功能需求進行了整理和采集,最終為程序設定了以下七大功能,既文件刪除、文件合并、內容替換、文本比較、內容統計、重命名、行排序。在本小結中我們將一一講解每個功能的實現方式。
文件刪除:首先我們利用JTextFilder 組件的事件監聽器,來獲得輸入的文件參數,這樣我們就知道了要刪除的文件路徑,然后利用Window 的命令行形式來刪除文件,考慮到性能的方面,我們采用了Close的方式,既程序執行完之后,操作系統自動關閉cmd后臺。并且把這個方法解耦到單獨的類中,方便日后的維護和版本的升級。
文件合并:同理,我們采用同樣的技術獲得輸入的文本參數。操作的文本是一個字符串,保存在一個字符數組中,這個數組目前的限定是3 個空間,也就是我們同時最多可以合并3 個文件,這個空間的大小是可以隨時改變的,而且不用修改其他任何地方,在調用和賦值的地方我使用一個size 的變量來控制,方便以后的空間擴展。考慮到性能方面,在合并的操作中我沒有采用簡單的java 輸入輸出流,而是用到了FileChannel(文件通道),Java NIO 中的FileChannel 是一個連接到文件的通道??梢酝ㄟ^文件通道讀寫文件。FileChannel 無法設置為非阻塞模式,它總是運行在阻塞模式下。所以利用FileChannel 來合并文件不但快速而且還可以多線程工作,合并文件的本質就是,把多個文件一一復制到指定文件中。代碼的實現邏輯也是同樣的道理,逐個字符的讀取然后寫入到合并結果文件中,直到所有的文件都讀取完畢,代碼在此就不明示了。
內容替換:同樣方式,同一個字符串數組變量來保存獲得的文件參數,而且還需要額外的兩個字符串變量,一個是要替換的文本,另一個保存替換后的文本,這兩個參數都是通過JTextFild 組件提供的getText()方法獲得的,所需的輸入參數都已經獲取到。接下來分析實現機制,本功能中我們采用的是FileReader 類,通過這個對象的read()方法,可以將文件中的所有內容都讀取出來,然后保存在一個字符串中。在java 提供的API 中有很多對字符串的操作,利用其replace()函數,就可以實現字符串的替換,最后在將替換后的字符串重新寫入文件中去,完成字符串替換操作。本功能的主要思想就是把文本內容轉為字符串,通過對字符串的操作來實現替換功能。
文本比較:比較功能是提供的基本操作里面最有價值的。實現的過程中采用了BufferedWriter 對象,因為本系統的文本比較功能比較簡易,只是提供了以行為單位的文本比較,BufferedWriter 對象恰恰提供了按行讀取的方法。所以按行讀取兩個比較文本,然后進行字符串對比,循環遍歷整個文本內容,相等的行我們會在結果輸出文件中打印Equal:+行數的字樣,不相等的行,我們會輸出different 字樣。比較結果一目了然,可以清楚的看出改動的行數。
內容統計:實際上這個操作包含著三個小的功能:第一,文本行數統計采用LineNumberReader 對象,這個對象的優勢在于可以獲取到當前IO 流所在文本行數,遍歷IO 流直到文本末尾,然后利用所提供的getLineNumber()函數獲得行數,最后把這個值返回到調用出。第二,字符數統計仍然采用緩存流來讀取文件,將整個的文本內容轉換為一個字符串,返回length()函數的值。第三,指定字符出現的頻數也是將文本內容先轉換為字符串,然后利用API 提供的indexof()函數,這里有必要講解一下函數的作用,indexOf 方法返回一個整數值,指出 String 對象內子字符串的開始位置。即indexOf()括號內所包含的字符在該字符串內的循序位置,在第幾位就返回幾,如果有重復的字符出現,以第一個字符為準。如果沒有找到子字符串,則返回 -1。 因此從首位開始循環調用直到返回-1 為止,然后用一個計數器記錄出現的次數,這樣我們就能計算出字符的頻數了,最終返回給調用處。在這里介紹一下結果的顯示方式,這三個結果都是直接顯示在界面中的,并沒有進行緩存處理,利用JTextFild 組件的setText()方法直接呈現給用戶。
重命名:這個功能的內部實現相對比較簡單,首先我們獲取到操作的文件參數表,然后給用戶提供一個JTestFild 組件用于輸入文件名參數,在調用處我們直接getText()來獲取并沒有對其進行緩存。我們是利用File 對象提供的renameTo()方法來實現重命名操作的,函數的具體使用規則,詳見java API。由于這個操作實現十分的簡單,因此我們并沒有把其抽離到單獨的對象中,直接放在了主類里面即可。
行排序:這個功能里面我們用到了LineNumberReader 對象,因為我們要實現的是按照行來排序那么就要獲取整行的內容,所以這個對象是最好的選擇,我們循環的調用readLine 函數,目的就是把每一行的內容都存儲到List 數組中,然后對list 數組進行排序,這里簡單的講解一下List 數組按照指定升降排序的方法。Comparator 是個接口,可重寫compare()及equals()這兩個方法,用于比價功能;如果是null 的話,就是使用元素的默認順序,如a,b,c,d,e,f,g,就是a,b,c,d,e,f,g 這樣,當然數字也是這樣的。我們就是用這個接口實現的排序功能,默認的sort()函數是按照字典序升序排列的,我們可以重載Collections.sort(list, new PriceComparator())函數來實現降序排列,第二個參數返回一個int型的值,就相當于一個標志,告訴sort 方法按什么順序來對list 進行排序。對list 排序之后我們在重新的把內容輸入到文件中,這樣,行排序工作就完成了。
接下來是流程的定義,這里才是程序的重中之重,真正涉及到了工作流的概念,可以說前面的章節都是在為本小結做鋪墊,這部分的前期設計是想采用拖拽的方式來給用戶提供操作的,但是考慮到和內部的連通,比較繁瑣,而且用戶的參數不好輸入等等,最后放棄了這種的設計概念。工作流的功能設計和實現我們打算按照按鈕的層次來介紹,在界面的設計和實現中簡單的介紹了三個按鈕的主要功能,那么接下來我們詳細的說明這些功能是怎么實現的。三大按鈕既:工作流模式、退出工作流模式、執行工作流。
工作流模式按鈕:我們申明了一個全局布爾變量(isWorkFlow),這是普通模式和工作流模式的一個標志位,當點擊次按鈕的時候,事件觸發器會把這個變量設置為true,再true 的情況下,我們獲取的處理文件參數和普通模式下的參數的保存方式是不一樣的,兩種模式下采用了不同的存儲方式,普通模式用統一的變量來存儲,因為他不需要對獲取的參數進行緩存,但是工作流模式下面我們是需要不留不同操作的參數的,然后定義好工作流之后再執行,因此我們設置了一個標志位來區別不同模式下的存儲方式。此外,我們還申明了一個工作流尺寸的數組變量,這個int 數組變量的功能主要是記錄工作流的順序,數組的大小等于提供的基本操作數量,并且初始化都是0。當點擊按鈕之后,我們會按照參照步驟去任意點擊上述基本操作,每個操作的內部都設定了一個int 值來標示,所以在點擊之后我們就會把數組按照點擊順序賦值成內部的操作ID,這樣我們就把定義的工作流記錄下來。
退出工作流模式按鈕:這個按鈕的操作十分簡單,和工作流模式按鈕的操作相反,把isWorkFlow 標志位設置為false,回退到普通模式,這樣以后的所有操作都是普通模式下的處理方式,并且恢復所有工作流模式下的變量值,保證下次進入工作流模式的時候,所有的變量都是初始值,減少錯誤的發生。
執行工作流按鈕:這個按鈕的事件處理,主要是通過switch 語句來實現的,在工作流模式按鈕中介紹了一個數組,這個數組就是定義的工作流執行操作,在這里我們通過case 語句,遍歷數組,把操作id 指定為case 的取值,然后就可以依據數組中的值進行不同的操作了,并且數組的值是按照執行順序賦值的,所以遍歷之后,我們就把定義的工作流執行了一遍。這里有必要說一句關于代碼的耦合度,在需求分析里面我們提及到,所有的操作都是封裝在單獨的類里面的,在調用出只需要直接調用對象的方法就可以,幾乎都是static 的對象。同理,case 語句我們的處理只是調用了不同的對象方法。這樣代碼的邏輯很高,并且易于管理和維護。此外,在事件監聽器方法的開始我們用一個字數串變量來記錄工作流,在case中對字符串進行疊加,然后將字符串輸出在界面中,來提示用戶此工作流的工作。
本文主要是按照開發的順序來講解軟件的開發流程,開始我們介紹了軟件的開發環境和所用到的技術,包括開發語言、使用的插件等等。
用WindowBuilder 插件實現簡潔的UI 界面以便和用戶進行交互,省去了枯燥繁瑣的硬編碼過程。然后我們對系統的基本需求分析也做了簡單的描述,概況了要實現的基本功能。最后,對系統的設計和實現進行了細致的闡述,從上層的界面設計到底層的內部實現,每一個組件,每一個實現細節都做了精心的描述。本文層次清晰,由里到外,對系統進行了全面的剖析。不但給用戶提供了明確的操作方法,也讓相關的技術人士能夠清晰的知道內部的實現邏輯,對系統的運行有清楚的理解。