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




[java]  view plain  copy


 print

?


    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. new HashMap<String, Object>();   
    17. "leave", leave);  
    18. //保存业务实体  
    19. new Date().toString());              
    20.             leaveBean.saveBeforeEntity(leave);   
    21.               
    22. null;  
    23.             Leavetest=leaveBean.queryByTestid(leave.getTestId());  
    24.             leave=Leavetest;  
    25. "save entity: {}", leave);   
    26.               
    27.               
    28. //不再获取id,改为获取类  .getClass().getSimpleName().toString();            
    29. //String businessKey = "leave";              
    30.             String businessKey = leave.getId().toString();              
    31. null;  
    32.               
    33. /*添加的代码--begin--Proxy*/  
    34.               
    35. // 调用业务,保存申请信息        
    36.             startNode.common(businessKey, variables,runtimeService,identityService);  
    37. 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. "message", "流程已启动" );  
    62. catch (ActivitiException e) {  
    63. if (e.getMessage().indexOf("no processes deployed with key") != -1) {  
    64. "没有部署流程!", e);  
    65. "error", "没有部署流程,请在[工作流]->[流程管理]页面点击<重新部署流程>");  
    66. else {  
    67. "启动请假流程失败:", e);  
    68. "error", "系统内部错误!");  
    69.             }  
    70. catch (Exception e) {  
    71. "启动请假流程失败:", e);  
    72. "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. 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. "start-->>");    
    78. for(int i=0;i<args.length;i++){    
    79.             System.out.println(args[i]);    
    80.         }    
    81. null;    
    82. try{    
    83. //原对象方法调用前处理日志信息    
    84. "satrt-->>");   
    85.                                
    86. //启动流程  
    87. //调用目标方法    
    88. 0];            
    89. // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中  
    90. try {  
    91.             identityService.setAuthenticatedUserId(leave.getUserId());                                  
    92. "ChangeCourse", businessKey, variables);  
    93.             String processInstanceId = processInstance.getId();  
    94.               
    95.             leave.setProcessInstanceId(processInstanceId);  
    96. "start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"ChangeCourse", processInstanceId, variables});  
    97. finally {  
    98. null);  
    99.             }  
    100. 0]=leave;  
    101.             ret=method.invoke(targetObject, args);    
    102.               
    103. //调用完成当前结点  
    104. // >> 办理完第1个任务“提交申请”        
    105. //jbpmService.completeFirstTask(pi);    
    106.               
    107. //原对象方法调用后处理日志信息    
    108. "success-->>");    
    109. catch(Exception e){    
    110.             e.printStackTrace();    
    111. "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. 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. new ArrayList<Leave>();  
    9. // 根据当前人的ID查询  
    10.          TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(userId);          
    11.          List<Task> tasks = taskQuery.list();       
    12. int i=0;        
    13.            
    14. 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. 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. "leave", leave);//存入“申请信息”  
    33. "task", task);  
    34. "processDefinition", getProcessDefinition(processInstance.getProcessDefinitionId()));  
    35. "processInstance", processInstance);//存入“流程实例”  
    36.              mapList.add(map);  
    37. /*Leave leave=updateEntity(processInstance,task,businessKey);
    38.              results.add(leave); */  
    39. 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. 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

    ?

    1. /**
    2.      * 抽象出来读取运行中的流程实例(查看我的申请),与基本业务无关
    3.      *
    4.      * @param userId 用户id
    5.      * @return
    6.      */  
    7. public List<Map<String, Object>> abstractRuningList(String userId){  
    8. new ArrayList<Leave>();  
    9. "ChangeCourse").involvedUser(userId).active().orderByProcessInstanceId().desc();//根据流程定义Key查询流程实例  
    10.         List<ProcessInstance> list = query.list();  
    11. 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. 0, 1);  
    20. 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. "leave", leave);//存入“考试信息”  
    29. "task", tasks.get(0));  
    30. "processDefinition", getProcessDefinition(processInstance.getProcessDefinitionId()));  
    31. "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. new ArrayList<Leave>();  
      10. "ChangeCourse").involvedUser(userId).finished().orderByProcessInstanceEndTime().desc();  
      11.          List<HistoricProcessInstance> list = query.list();  
      12. new ArrayList<Map<String, Object>>();  
      13. // 关联业务实体  
      14. for (HistoricProcessInstance historicProcessInstance : list) {  
      15. 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. "leave", leave);//存入“申请信息”           
      22. "processDefinition", getProcessDefinition(historicProcessInstance.getProcessDefinitionId()));  
      23. "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. "error on complete task {}", new Object[]{taskId, e});  
      26. return "error";  
      27.         }  
      28.     }





      总结:

          对于在流程与业务的整合中应用动态代理也不知道是否符合AOP的理念,类似其他方面的流程操作还未抽取出来(交互太多),在这里记录一下学习Activiti的一个过程,在之后的尝试中可以换个方式,换个思路,直接将整个工作流应用抽取出来(请假,修改课程等)。