对于无论是Activtit还是jbpm来说,业务与流程的整合均类似,启动流程是绑定业务,流程与业务的整合放到动态代理中
[java] view plain copy
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
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
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
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
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
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
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
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的一个过程,在之后的尝试中可以换个方式,换个思路,直接将整个工作流应用抽取出来(请假,修改课程等)。