使用 OSWorkflow 已經有段時間了,現在看來實際需求不是請假條流程原型這么簡單。 有這樣的需求:OA 系統中的公文審批共有六個 step,采用單點(不牽涉 split 和 join)逐級審核方式,不同角色登陸時,由同一頁面處理,為了便于收發文統計,必須知道下一個接收人是哪個。 由于在觸發當前 action 的同時就要設置好下一接收者,遂需要引進新的協作表。當 action 時要調用另外的 save 方法,而這一過程當然不能在表現層進行。最開始的做法是用一個輔助 service 來取出每個 action 的下一接收者,如下:
這種做法在開發的前期還覺得不錯,隨著需求的進一步詳細,發現當新增、修改流程時,也許我們要在這個 service 中滿山遍野的找尋到底代碼在哪里。更糟糕的是產品提交用戶后,用戶不會花費這么大的耐心讓你這樣維護。在經過短暫的思考后,決定利用 OSWorkflow 的 FunctionProvider 接口和 script 做文章。 一個比較成熟的想法是(如各位有更好的方案不妨交流):每個流程都可能面臨修改,那就把流程的每個 action 要做的事抽取出來,這樣修改起來相對獨立,比如要把下一默認接收者改成其他人;另一個目的是快速響應用戶對新流程的需求,在提出需求后,生成相應的流程文件及每個 action 要做的事,提交到服務器,重啟就可以用了,而不是在已有代碼基礎上新增。這里的“每個 action 要做的事”就是 OSWorkflow 的 FunctionProvider 接口,實現這個接口,就可以為所欲為了。 代碼片斷如下:
流程定義 <step id="1" name="科領導審批"> <actions> <action id="2" name="批準" view="批準"> <results> <unconditional-result id="2" old-status="Finished" status="Queued" step="2" owner="${stepOwner}"> <pre-functions> //向 FacultyLea 類說明當前調用者 <function type="beanshell"> <arg name="script"> String caller = context.getCaller(); transientVars.put("caller", caller); </arg> </function> //FunctionProvider 實現類 //向協作表中寫入當前調用者和下一默認接收者 <function name="set.caller" type="class"> <arg name="class.name">***.*****.util.FacultyLea</arg> </function> </pre-functions> </unconditional-result> </results> </action> <action id="3" name="拒絕" view="拒絕"> <results> <unconditional-result id="3" old-status="Finished" status="Finished" step="7"/> </results> </action> </actions> </step>
FacultyLea
public class FacultyLea implements FunctionProvider{ ReadProperty readProperty = ReadProperty.getInstance(); ApplicationContext ctx=new FileSystemXmlApplicationContext(System.getProperty("user.dir")+"/web/WEB-INF/classes/applicationContext.xml"); private SendDao sendDao = (SendDao) ctx.getBean("sendDao"); private DocService docService = (DocService) ctx.getBean("docService"); public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException { long l=((HibernateCurrentStep)((Collection)transientVars.get("currentSteps")).toArray()[0]).getEntryId(); Doc md=docService.findDocByWrokFlowId(l+""); String caller=(String)transientVars.get("caller"); //設置下一步的接收者 Timestamp date = new Timestamp(System.currentTimeMillis()); String query = "some hql here"; List leaders = docSendDao.find(query); for(int i=0;i<leaders.size();i++){ Send send = new Send(); send.setSendUser(new UserLogin(new Integer(caller))); send.setDoc(md); ...... sendDao.save(send); } //設置該步驟處理者 transientVars.put("stepOwner", caller); }}
function 只是 OSWorkflow 為我們提供眾多功能中的一個,如果可能,我會把另外的使用心得寫出來。
請注意!引用、轉貼本文應注明原作者:Rosen Jiang 以及出處:http://www.tkk7.com/rosen
Powered by: BlogJava Copyright © Rosen