首页 > 代码库 > 【整合篇】Activiti业务与流程的整合

【整合篇】Activiti业务与流程的整合

对于不管是Activtit还是jbpm来说,业务与流程的整合均类似。启动流程是绑定业务。流程与业务的整合放到动态代理中

[java] view plain copy
 print

" style="text-decoration:none; background-color:inherit; border:none; padding:0px; margin:0px 10px 0px 0px; font-size:9px; color:rgb(12,137,207)">?

技术分享技术分享

  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?技术分享技术分享
  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?技术分享技术分享
  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?

技术分享技术分享

  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?技术分享技术分享
  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

" style="text-decoration:none; background-color:inherit; border:none; padding:0px; margin:0px 10px 0px 0px; font-size:9px; color:rgb(12,137,207)">?

技术分享技术分享

  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?技术分享技术分享
  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?技术分享技术分享
  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的一个过程,在之后的尝试中能够换个方式。换个思路,直接将整个工作流应用抽取出来(请假,改动课程等)。

【整合篇】Activiti业务与流程的整合