【整合篇】Activiti業務與流程的整合


對於不管是Activtit還是jbpm來說,業務與流程的整合均類似。啟動流程是綁定業務。流程與業務的整合放到動態代理中

[java]  view plain  copy
 print ?

在CODE上查看代碼片派生到我的代碼片

  1. /** 
  2.      * 啟動改動課程流程Leave leave,  
  3.      * 
  4.      * @param leave 
  5.      */  
  6.     @RequestMapping(value = "start", method = RequestMethod.POST)  
  7.     public String startWorkflow(Leave leave,RedirectAttributes redirectAttributes, HttpSession session) {  
  8.         try {  
  9.               
  10.             User user = UserUtil.getUserFromSession(session);  
  11.             // 用戶未登錄不能操作,實際應用使用權限框架實現,比如Spring Security、Shiro等  
  12.             if (user == null || StringUtils.isBlank(user.getId())) {  
  13.                 return "redirect:/login?timeout=true";  
  14.             }              
  15.             leave.setUserId(user.getId());  
  16.             Map<String, Object> variables = new HashMap<String, Object>();   
  17.             variables.put("leave", leave);  
  18.             //保存業務實體  
  19.             leave.setTestId(new Date().toString());              
  20.             leaveBean.saveBeforeEntity(leave);   
  21.               
  22.             Leave Leavetest=null;  
  23.             Leavetest=leaveBean.queryByTestid(leave.getTestId());  
  24.             leave=Leavetest;  
  25.             logger.debug("save entity: {}", leave);   
  26.               
  27.               
  28.             //不再獲取id,改為獲取類  .getClass().getSimpleName().toString();            
  29.             //String businessKey = "leave";              
  30.             String businessKey = leave.getId().toString();              
  31.             ProcessInstance processInstance = null;  
  32.               
  33.            /*加入的代碼--begin--Proxy*/  
  34.               
  35.             // 調用業務,保存申請信息        
  36.             startNode.common(businessKey, variables,runtimeService,identityService);  
  37.             LogHandler1 logHandler = startNode.new LogHandler1();  
  38.             //放到代理中設置值了  
  39.             //stuCourseApply.setExecuteId(pi.getId());  
  40.               
  41.             LeaveBean leaveBeanProxy=(LeaveBean)logHandler.newProxyInstanceStart(leaveBean);    
  42.             leaveBeanProxy.updeatChangeApply(leave);      
  43.               
  44.         /*加入的代碼--end--Proxy*/  
  45.            
  46.               
  47.         /*放到代理中--begin--Proxy*/   
  48.            /* try { 
  49.                 // 用來設置啟動流程的人員ID,引擎會自己主動把用戶ID保存到activiti:initiator中 
  50.                 identityService.setAuthenticatedUserId(leave.getUserId());                                 
  51.                 processInstance = runtimeService.startProcessInstanceByKey("easyChangeCourse", businessKey, variables); 
  52.                 String processInstanceId = processInstance.getId(); 
  53.                 leave.setProcessInstanceId(processInstanceId); 
  54.                 logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"easyChangeCourse", processInstanceId, variables}); 
  55.             } finally { 
  56.                 identityService.setAuthenticatedUserId(null); 
  57.             }*/  
  58.         /*放到代理中--end--Proxy*/       
  59.               
  60.         //+ processInstance.getId()  
  61.             redirectAttributes.addFlashAttribute("message""流程已啟動" );  
  62.         } catch (ActivitiException e) {  
  63.             if (e.getMessage().indexOf("no processes deployed with key") != -1) {  
  64.                 logger.warn("沒有部署流程!", e);  
  65.                 redirectAttributes.addFlashAttribute("error""沒有部署流程,請在[工作流]->[流程管理]頁面點擊<又一次部署流程>");  
  66.             } else {  
  67.                 logger.error("啟動請假流程失敗:", e);  
  68.                 redirectAttributes.addFlashAttribute("error""系統內部錯誤!

    ");  

  69.             }  
  70.         } catch (Exception e) {  
  71.             logger.error("啟動請假流程失敗:", e);  
  72.             redirectAttributes.addFlashAttribute("error""系統內部錯誤!

    ");  

  73.         }  
  74.         return "redirect:/oa/leave/apply";  
  75.     }  

動態代理:


[java]  view plain  copy
 print ? 在CODE上查看代碼片 派生到我的代碼片
  1. package com.tgb.itoo.activiti.controller;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.Method;  
  5. import java.lang.reflect.Proxy;  
  6. import java.util.Map;  
  7.   
  8. import org.activiti.engine.IdentityService;  
  9. import org.activiti.engine.RuntimeService;  
  10. import org.activiti.engine.runtime.ProcessInstance;  
  11. import org.slf4j.Logger;  
  12. import org.slf4j.LoggerFactory;  
  13. import org.springframework.beans.factory.annotation.Autowired;  
  14. import org.springframework.stereotype.Component;  
  15. import org.springframework.transaction.annotation.Transactional;  
  16. import com.tgb.itoo.basic.entity.Leave;  
  17.   
  18. @Component  
  19. @Transactional  
  20. public class StartNode{  
  21.   
  22.     private Logger logger = LoggerFactory.getLogger(getClass());  
  23.     //定義一個屬性變量  
  24.     private Map<String, Object> variables;  
  25.     private String businessKey;  
  26.       
  27.     //設置人人員  
  28.     protected IdentityService identityService;  
  29.     @Autowired  
  30.     public void setIdentifyService(IdentityService identityService) {  
  31.         this.identityService = identityService;  
  32.     }  
  33.     protected RuntimeService runtimeService;  
  34.     @Autowired  
  35.     public void setRuntimeService(RuntimeService runtimeService) {  
  36.         this.runtimeService = runtimeService;  
  37.     }  
  38.       
  39.     @Autowired  
  40.     RuntimeService runtimeService1;  
  41.       
  42.     public void common(String businessKey,Map<String, Object> variables,RuntimeService runtimeService,IdentityService identityService){  
  43.         this.variables=variables;  
  44.         this.businessKey=businessKey;  
  45.         this.runtimeService=runtimeService;  
  46.         this.identityService=identityService;  
  47.     }  
  48.     //想嘗試是否能依據其它方式傳參。new的話太耗費資源  
  49.     /*public StartAbstractJBPM(String pdKey,Map<String, Object> variablesMap,JBPMService jbpmService){ 
  50.         this.variablesMap=variablesMap; 
  51.         this.pdKey=pdKey; 
  52.         this.jbpmService=jbpmService; 
  53.     }*/  
  54.                       
  55.       
  56.     //動態代理類僅僅能代理接口(不支持抽象類),代理類都須要實現InvocationHandler類,實現invoke方法。

    該invoke方法就是調用被代理接口的全部方法時須要調用的,該invoke方法返回的值是被代理接口的一個實現類       

  57.     public class LogHandler1 implements InvocationHandler{          
  58.     // 目標對象    
  59.     private Object targetObject;    
  60.     //綁定關系,也就是關聯到哪個接口(與詳細的實現類綁定)的哪些方法將被調用時,運行invoke方法。                
  61.     public Object newProxyInstanceStart(Object targetObject){    
  62.         this.targetObject=targetObject;    
  63.         //該方法用於為指定類裝載器、一組接口及調用處理器生成動態代理類實例      
  64.         //第一個參數指定產生代理對象的類載入器,須要將其指定為和目標對象同一個類載入器    
  65.         //第二個參數要實現和目標對象一樣的接口,所以僅僅須要拿到目標對象的實現接口    
  66.         //第三個參數表明這些被攔截的方法在被攔截時須要運行哪個InvocationHandler的invoke方法    
  67.         //依據傳入的目標返回一個代理對象    
  68.         return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),    
  69.                 targetObject.getClass().getInterfaces(),this);    
  70.     }    
  71.         
  72.     @Override    
  73.     //關聯的這個實現類的方法被調用時將被運行    
  74.    // InvocationHandler接口的方法。proxy表示代理,method表示原對象被調用的方法,args表示方法的參數    
  75.     public Object invoke(Object proxy, Method method, Object[] args)    
  76.             throws Throwable {    
  77.         System.out.println("start-->>");    
  78.         for(int i=0;i<args.length;i++){    
  79.             System.out.println(args[i]);    
  80.         }    
  81.         Object ret=null;    
  82.         try{    
  83.             //原對象方法調用前處理日志信息    
  84.             System.out.println("satrt-->>");   
  85.                                
  86.             //啟動流程  
  87.             //調用目標方法    
  88.             Leave leave=(Leave)args[0];            
  89.             // 用來設置啟動流程的人員ID,引擎會自己主動把用戶ID保存到activiti:initiator中  
  90.             try {  
  91.             identityService.setAuthenticatedUserId(leave.getUserId());                                  
  92.             ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("ChangeCourse", businessKey, variables);  
  93.             String processInstanceId = processInstance.getId();  
  94.               
  95.             leave.setProcessInstanceId(processInstanceId);  
  96.             logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}"new Object[]{"ChangeCourse", processInstanceId, variables});  
  97.             } finally {  
  98.                 identityService.setAuthenticatedUserId(null);  
  99.             }  
  100.             args[0]=leave;  
  101.             ret=method.invoke(targetObject, args);    
  102.               
  103.             //調用完畢當前結點  
  104.             // >> 辦理完第1個任務“提交申請”        
  105.             //jbpmService.completeFirstTask(pi);    
  106.               
  107.             //原對象方法調用后處理日志信息    
  108.             System.out.println("success-->>");    
  109.         }catch(Exception e){    
  110.             e.printStackTrace();    
  111.             System.out.println("error-->>");    
  112.                 throw e;    
  113.             }    
  114.             return ret;    
  115.         }             
  116.     }     
  117.   
  118. }  

[java]  view plain  copy
 print ? 在CODE上查看代碼片 派生到我的代碼片
  1. /** 
  2.      * 任務列表ERROR [stderr] (http-localhost/127.0.0.1:8080-3) ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider com.sun.script.javascript.RhinoScriptEngineFactory not found 
  3.      * 
  4.      * @param leave 
  5.      */  
  6.     @RequestMapping(value = "list/task")  
  7.     public ModelAndView taskList(HttpSession session, HttpServletRequest request) {  
  8.         List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();  
  9.         String userId = UserUtil.getUserFromSession(session).getId();  
  10.         results=abstractTaskList(userId);         
  11.         return new ModelAndView("/oa/leave/taskList","results",results);  
  12.                                  
  13.     }  

[java]  view plain  copy
 print ?

在CODE上查看代碼片派生到我的代碼片

  1. /** 
  2.      * 抽象出來的查看任務列表。與基本業務無關 
  3.      * 
  4.      * @param userId 用戶id 
  5.      * @return 
  6.      */  
  7.     public List<Map<String, Object>> abstractTaskList(String userId){  
  8.          List<Leave> results = new ArrayList<Leave>();  
  9.          // 依據當前人的ID查詢  
  10.          TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(userId);          
  11.          List<Task> tasks = taskQuery.list();       
  12.          int i=0;        
  13.            
  14.          List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();  
  15.          // 依據流程的業務ID查詢實體並關聯  
  16.          for (Task task : tasks) {  
  17.              String processInstanceId = task.getProcessInstanceId();  
  18.              ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();  
  19.              String businessKey = processInstance.getBusinessKey();  
  20.              if (businessKey == null) {  
  21.                  continue;  
  22.              }   
  23.                
  24.              Map<String, Object> map = new HashMap<String, Object>();  
  25.                
  26.              Leave leave = leaveBean.findEntityById(businessKey);  
  27.                
  28.             //leave.setProcessInstance(processInstance);  
  29.             //leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));                     
  30.         //leave.setTask(task);  
  31.               
  32.              map.put("leave", leave);//存入“申請信息”  
  33.              map.put("task", task);  
  34.              map.put("processDefinition", getProcessDefinition(processInstance.getProcessDefinitionId()));  
  35.              map.put("processInstance", processInstance);//存入“流程實例”  
  36.              mapList.add(map);  
  37.              /*Leave leave=updateEntity(processInstance,task,businessKey); 
  38.              results.add(leave); */  
  39.              i=i+1;  
  40.          }  
  41.         return mapList;  
  42.     }  

[java]  view plain  copy
 print ? 在CODE上查看代碼片 派生到我的代碼片
  1. /** 
  2.      * 讀取執行中的流程實例(查看我的申請)involvedUser(userId)(涉及到的用戶) 
  3.      * 
  4.      * @return 
  5.      */  
  6.     @RequestMapping(value = "list/running")  
  7.     public ModelAndView runningList(HttpSession session,HttpServletRequest request) {  
  8.         String userId = UserUtil.getUserFromSession(session).getId();  
  9.         List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();  
  10.         results=abstractRuningList(userId);  
  11.     
  12.         return new ModelAndView ("/oa/leave/running","results",results);  
  13.        }  

[java]  view plain  copy
 print ?

在CODE上查看代碼片派生到我的代碼片

  1. /** 
  2.      * 抽象出來讀取執行中的流程實例(查看我的申請)。與基本業務無關 
  3.      * 
  4.      * @param userId 用戶id 
  5.      * @return 
  6.      */  
  7.     public List<Map<String, Object>> abstractRuningList(String userId){  
  8.         List<Leave> results = new ArrayList<Leave>();  
  9.         ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery().processDefinitionKey("ChangeCourse").involvedUser(userId).active().orderByProcessInstanceId().desc();//依據流程定義Key查詢流程實例  
  10.         List<ProcessInstance> list = query.list();  
  11.         List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();  
  12.         // 關聯業務實體  
  13.         for (ProcessInstance processInstance : list) {  
  14.             String businessKey = processInstance.getBusinessKey();  
  15.             if (businessKey == null) {  
  16.                 continue;  
  17.             }  
  18.             // 設置當前任務信息  
  19.             List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).active().orderByTaskCreateTime().desc().listPage(01);  
  20.             Map<String, Object> map = new HashMap<String, Object>();  
  21.                
  22.             Leave leave = leaveBean.findEntityById(businessKey);  
  23.               
  24.             /*leave.setProcessInstance(processInstance); 
  25.             leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));                  
  26.             leave.setTask(tasks.get(0));*/  
  27.               
  28.              map.put("leave", leave);//存入“考試信息”  
  29.              map.put("task", tasks.get(0));  
  30.              map.put("processDefinition", getProcessDefinition(processInstance.getProcessDefinitionId()));  
  31.              map.put("processInstance", processInstance);//存入“流程實例”  
  32.              mapList.add(map);  
  33.              /*Leave leave=updateEntity(processInstance,task,businessKey); 
  34.              results.add(leave); */  
  35.               
  36.               
  37.             //Leave leave=updateEntity(processInstance,tasks.get(0),businessKey);  
  38.               
  39.               
  40.         }  
  41.         return mapList;  
  42.     }  

[java]  view plain  copy
 print ? 在CODE上查看代碼片 派生到我的代碼片
  1. /** 
  2.      * 讀取完畢的流程實例(已經完畢的流程申請-我) 
  3.      * 
  4.      * @return 
  5.      */  
  6.     @RequestMapping(value = "list/finished")  
  7.     public ModelAndView finishedList(HttpSession session,HttpServletRequest request) {  
  8.          String userId = UserUtil.getUserFromSession(session).getId();    
  9.          List<Leave> results = new ArrayList<Leave>();  
  10.          HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("ChangeCourse").involvedUser(userId).finished().orderByProcessInstanceEndTime().desc();  
  11.          List<HistoricProcessInstance> list = query.list();  
  12.          List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();  
  13.          // 關聯業務實體  
  14.          for (HistoricProcessInstance historicProcessInstance : list) {  
  15.              Map<String, Object> map = new HashMap<String, Object>();  
  16.              String businessKey = historicProcessInstance.getBusinessKey();  
  17.              Leave leave = leaveBean.findEntityById(businessKey);  
  18.             /* leave.setProcessDefinition(getProcessDefinition(historicProcessInstance.getProcessDefinitionId())); 
  19.              leave.setHistoricProcessInstance(historicProcessInstance);             
  20.              results.add(leave);*/   
  21.              map.put("leave", leave);//存入“申請信息”           
  22.              map.put("processDefinition", getProcessDefinition(historicProcessInstance.getProcessDefinitionId()));  
  23.              map.put("historicProcessInstance", historicProcessInstance);//存入“流程實例”  
  24.              mapList.add(map);  
  25.                
  26.          }  
  27.           
  28.         return new ModelAndView("/oa/leave/finished","results",mapList);  
  29.     }  

[java]  view plain  copy
 print ? 在CODE上查看代碼片 派生到我的代碼片
  1.  /** 
  2.      * 完畢任務 
  3.      * 
  4.      * @param id 
  5.      * @return 
  6.      */  
  7.     @RequestMapping(value = "/complete/{id}", method = {RequestMethod.POST, RequestMethod.GET})  
  8.     @ResponseBody  
  9.     public String complete(@PathVariable("id") String taskId, Variable var) {  
  10.         try {   
  11.             //deptLeaderPass=true or  hrBackReason=666, hrPass=false-----{leaderBackReason=78, deptLeaderPass=false}  
  12.             Map<String, Object> variables = var.getVariableMap();  
  13.             //taskService.getVariables(taskId);  
  14.             //Object variablesResult=variables.get("deptLeaderPass");             
  15.             //variablesResult=variables.get("hrPass");  
  16.               
  17.             taskService.complete(taskId, variables);              
  18.               
  19.             //獲取map中的值  
  20. //            if(hrPass=true){  
  21. //              //更新業務表信息  
  22. //            }  
  23.             return "success";  
  24.         } catch (Exception e) {  
  25.             logger.error("error on complete task {}"new Object[]{taskId, e});  
  26.             return "error";  
  27.         }  
  28.     }  



總結:

    對於在流程與業務的整合中應用動態代理也不知道是否符合AOP的理念,類似其它方面的流程操作還未抽取出來(交互太多),在這里記錄一下學習Activiti的一個過程,在之后的嘗試中能夠換個方式。換個思路,直接將整個工作流應用抽取出來(請假,改動課程等)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM