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

  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. User user = UserUtil.getUserFromSession(session);
  10. // 用户未登录不能操作,实际应用使用权限框架实现,比如Spring Security、Shiro等
  11. if (user == null || StringUtils.isBlank(user.getId())) {
  12. return "redirect:/login?timeout=true";
  13. }
  14. leave.setUserId(user.getId());
  15. Map<String, Object> variables = new HashMap<String, Object>();
  16. variables.put("leave", leave);
  17. //保存业务实体
  18. leave.setTestId(new Date().toString());
  19. leaveBean.saveBeforeEntity(leave);
  20. Leave Leavetest=null;
  21. Leavetest=leaveBean.queryByTestid(leave.getTestId());
  22. leave=Leavetest;
  23. logger.debug("save entity: {}", leave);
  24. //不再获取id,改为获取类  .getClass().getSimpleName().toString();
  25. //String businessKey = "leave";
  26. String businessKey = leave.getId().toString();
  27. ProcessInstance processInstance = null;
  28. /*加入的代码--begin--Proxy*/
  29. // 调用业务,保存申请信息
  30. startNode.common(businessKey, variables,runtimeService,identityService);
  31. LogHandler1 logHandler = startNode.new LogHandler1();
  32. //放到代理中设置值了
  33. //stuCourseApply.setExecuteId(pi.getId());
  34. LeaveBean leaveBeanProxy=(LeaveBean)logHandler.newProxyInstanceStart(leaveBean);
  35. leaveBeanProxy.updeatChangeApply(leave);
  36. /*加入的代码--end--Proxy*/
  37. /*放到代理中--begin--Proxy*/
  38. /* try {
  39. // 用来设置启动流程的人员ID,引擎会自己主动把用户ID保存到activiti:initiator中
  40. identityService.setAuthenticatedUserId(leave.getUserId());
  41. processInstance = runtimeService.startProcessInstanceByKey("easyChangeCourse", businessKey, variables);
  42. String processInstanceId = processInstance.getId();
  43. leave.setProcessInstanceId(processInstanceId);
  44. logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"easyChangeCourse", processInstanceId, variables});
  45. } finally {
  46. identityService.setAuthenticatedUserId(null);
  47. }*/
  48. /*放到代理中--end--Proxy*/
  49. //+ processInstance.getId()
  50. redirectAttributes.addFlashAttribute("message", "流程已启动" );
  51. } catch (ActivitiException e) {
  52. if (e.getMessage().indexOf("no processes deployed with key") != -1) {
  53. logger.warn("没有部署流程!", e);
  54. redirectAttributes.addFlashAttribute("error", "没有部署流程,请在[工作流]->[流程管理]页面点击<又一次部署流程>");
  55. } else {
  56. logger.error("启动请假流程失败:", e);
  57. redirectAttributes.addFlashAttribute("error", "系统内部错误!

    ");

  58. }
  59. } catch (Exception e) {
  60. logger.error("启动请假流程失败:", e);
  61. redirectAttributes.addFlashAttribute("error", "系统内部错误!

    ");

  62. }
  63. return "redirect:/oa/leave/apply";
  64. }

动态代理:

  1. package com.tgb.itoo.activiti.controller;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Method;
  4. import java.lang.reflect.Proxy;
  5. import java.util.Map;
  6. import org.activiti.engine.IdentityService;
  7. import org.activiti.engine.RuntimeService;
  8. import org.activiti.engine.runtime.ProcessInstance;
  9. import org.slf4j.Logger;
  10. import org.slf4j.LoggerFactory;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.stereotype.Component;
  13. import org.springframework.transaction.annotation.Transactional;
  14. import com.tgb.itoo.basic.entity.Leave;
  15. @Component
  16. @Transactional
  17. public class StartNode{
  18. private Logger logger = LoggerFactory.getLogger(getClass());
  19. //定义一个属性变量
  20. private Map<String, Object> variables;
  21. private String businessKey;
  22. //设置人人员
  23. protected IdentityService identityService;
  24. @Autowired
  25. public void setIdentifyService(IdentityService identityService) {
  26. this.identityService = identityService;
  27. }
  28. protected RuntimeService runtimeService;
  29. @Autowired
  30. public void setRuntimeService(RuntimeService runtimeService) {
  31. this.runtimeService = runtimeService;
  32. }
  33. @Autowired
  34. RuntimeService runtimeService1;
  35. public void common(String businessKey,Map<String, Object> variables,RuntimeService runtimeService,IdentityService identityService){
  36. this.variables=variables;
  37. this.businessKey=businessKey;
  38. this.runtimeService=runtimeService;
  39. this.identityService=identityService;
  40. }
  41. //想尝试是否能依据其它方式传參。new的话太耗费资源
  42. /*public StartAbstractJBPM(String pdKey,Map<String, Object> variablesMap,JBPMService jbpmService){
  43. this.variablesMap=variablesMap;
  44. this.pdKey=pdKey;
  45. this.jbpmService=jbpmService;
  46. }*/
  47. //动态代理类仅仅能代理接口(不支持抽象类),代理类都须要实现InvocationHandler类,实现invoke方法。

    该invoke方法就是调用被代理接口的全部方法时须要调用的,该invoke方法返回的值是被代理接口的一个实现类

  48. public class LogHandler1 implements InvocationHandler{
  49. // 目标对象
  50. private Object targetObject;
  51. //绑定关系,也就是关联到哪个接口(与详细的实现类绑定)的哪些方法将被调用时,运行invoke方法。
  52. public Object newProxyInstanceStart(Object targetObject){
  53. this.targetObject=targetObject;
  54. //该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
  55. //第一个參数指定产生代理对象的类载入器,须要将其指定为和目标对象同一个类载入器
  56. //第二个參数要实现和目标对象一样的接口,所以仅仅须要拿到目标对象的实现接口
  57. //第三个參数表明这些被拦截的方法在被拦截时须要运行哪个InvocationHandler的invoke方法
  58. //依据传入的目标返回一个代理对象
  59. return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
  60. targetObject.getClass().getInterfaces(),this);
  61. }
  62. @Override
  63. //关联的这个实现类的方法被调用时将被运行
  64. // InvocationHandler接口的方法。proxy表示代理,method表示原对象被调用的方法,args表示方法的參数
  65. public Object invoke(Object proxy, Method method, Object[] args)
  66. throws Throwable {
  67. System.out.println("start-->>");
  68. for(int i=0;i<args.length;i++){
  69. System.out.println(args[i]);
  70. }
  71. Object ret=null;
  72. try{
  73. //原对象方法调用前处理日志信息
  74. System.out.println("satrt-->>");
  75. //启动流程
  76. //调用目标方法
  77. Leave leave=(Leave)args[0];
  78. // 用来设置启动流程的人员ID,引擎会自己主动把用户ID保存到activiti:initiator中
  79. try {
  80. identityService.setAuthenticatedUserId(leave.getUserId());
  81. ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("ChangeCourse", businessKey, variables);
  82. String processInstanceId = processInstance.getId();
  83. leave.setProcessInstanceId(processInstanceId);
  84. logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"ChangeCourse", processInstanceId, variables});
  85. } finally {
  86. identityService.setAuthenticatedUserId(null);
  87. }
  88. args[0]=leave;
  89. ret=method.invoke(targetObject, args);
  90. //调用完毕当前结点
  91. // >> 办理完第1个任务“提交申请”
  92. //jbpmService.completeFirstTask(pi);
  93. //原对象方法调用后处理日志信息
  94. System.out.println("success-->>");
  95. }catch(Exception e){
  96. e.printStackTrace();
  97. System.out.println("error-->>");
  98. throw e;
  99. }
  100. return ret;
  101. }
  102. }
  103. }
  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. }
  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. List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
  14. // 依据流程的业务ID查询实体并关联
  15. for (Task task : tasks) {
  16. String processInstanceId = task.getProcessInstanceId();
  17. ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
  18. String businessKey = processInstance.getBusinessKey();
  19. if (businessKey == null) {
  20. continue;
  21. }
  22. Map<String, Object> map = new HashMap<String, Object>();
  23. Leave leave = leaveBean.findEntityById(businessKey);
  24. //leave.setProcessInstance(processInstance);
  25. //leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
  26. //leave.setTask(task);
  27. map.put("leave", leave);//存入“申请信息”
  28. map.put("task", task);
  29. map.put("processDefinition", getProcessDefinition(processInstance.getProcessDefinitionId()));
  30. map.put("processInstance", processInstance);//存入“流程实例”
  31. mapList.add(map);
  32. /*Leave leave=updateEntity(processInstance,task,businessKey);
  33. results.add(leave); */
  34. i=i+1;
  35. }
  36. return mapList;
  37. }
  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. return new ModelAndView ("/oa/leave/running","results",results);
  12. }
  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(0, 1);
  20. Map<String, Object> map = new HashMap<String, Object>();
  21. Leave leave = leaveBean.findEntityById(businessKey);
  22. /*leave.setProcessInstance(processInstance);
  23. leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
  24. leave.setTask(tasks.get(0));*/
  25. map.put("leave", leave);//存入“考试信息”
  26. map.put("task", tasks.get(0));
  27. map.put("processDefinition", getProcessDefinition(processInstance.getProcessDefinitionId()));
  28. map.put("processInstance", processInstance);//存入“流程实例”
  29. mapList.add(map);
  30. /*Leave leave=updateEntity(processInstance,task,businessKey);
  31. results.add(leave); */
  32. //Leave leave=updateEntity(processInstance,tasks.get(0),businessKey);
  33. }
  34. return mapList;
  35. }
  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. return new ModelAndView("/oa/leave/finished","results",mapList);
  27. }
  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. taskService.complete(taskId, variables);
  17. //获取map中的值
  18. //            if(hrPass=true){
  19. //              //更新业务表信息
  20. //            }
  21. return "success";
  22. } catch (Exception e) {
  23. logger.error("error on complete task {}", new Object[]{taskId, e});
  24. return "error";
  25. }
  26. }

总结:

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

05-26 09:25