對於不管是Activtit還是jbpm來說,業務與流程的整合均類似。啟動流程是綁定業務。流程與業務的整合放到動態代理中
- /**
- * 啟動改動課程流程Leave leave,
- *
- * @param leave
- */
- @RequestMapping(value = "start", method = RequestMethod.POST)
- public String startWorkflow(Leave leave,RedirectAttributes redirectAttributes, HttpSession session) {
- try {
- User user = UserUtil.getUserFromSession(session);
- // 用戶未登錄不能操作,實際應用使用權限框架實現,比如Spring Security、Shiro等
- if (user == null || StringUtils.isBlank(user.getId())) {
- return "redirect:/login?timeout=true";
- }
- leave.setUserId(user.getId());
- Map<String, Object> variables = new HashMap<String, Object>();
- variables.put("leave", leave);
- //保存業務實體
- leave.setTestId(new Date().toString());
- leaveBean.saveBeforeEntity(leave);
- Leave Leavetest=null;
- Leavetest=leaveBean.queryByTestid(leave.getTestId());
- leave=Leavetest;
- logger.debug("save entity: {}", leave);
- //不再獲取id,改為獲取類 .getClass().getSimpleName().toString();
- //String businessKey = "leave";
- String businessKey = leave.getId().toString();
- ProcessInstance processInstance = null;
- /*加入的代碼--begin--Proxy*/
- // 調用業務,保存申請信息
- startNode.common(businessKey, variables,runtimeService,identityService);
- LogHandler1 logHandler = startNode.new LogHandler1();
- //放到代理中設置值了
- //stuCourseApply.setExecuteId(pi.getId());
- LeaveBean leaveBeanProxy=(LeaveBean)logHandler.newProxyInstanceStart(leaveBean);
- leaveBeanProxy.updeatChangeApply(leave);
- /*加入的代碼--end--Proxy*/
- /*放到代理中--begin--Proxy*/
- /* try {
- // 用來設置啟動流程的人員ID,引擎會自己主動把用戶ID保存到activiti:initiator中
- identityService.setAuthenticatedUserId(leave.getUserId());
- processInstance = runtimeService.startProcessInstanceByKey("easyChangeCourse", businessKey, variables);
- String processInstanceId = processInstance.getId();
- leave.setProcessInstanceId(processInstanceId);
- logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"easyChangeCourse", processInstanceId, variables});
- } finally {
- identityService.setAuthenticatedUserId(null);
- }*/
- /*放到代理中--end--Proxy*/
- //+ processInstance.getId()
- redirectAttributes.addFlashAttribute("message", "流程已啟動" );
- } catch (ActivitiException e) {
- if (e.getMessage().indexOf("no processes deployed with key") != -1) {
- logger.warn("沒有部署流程!", e);
- redirectAttributes.addFlashAttribute("error", "沒有部署流程,請在[工作流]->[流程管理]頁面點擊<又一次部署流程>");
- } else {
- logger.error("啟動請假流程失敗:", e);
- redirectAttributes.addFlashAttribute("error", "系統內部錯誤!
");
- }
- } catch (Exception e) {
- logger.error("啟動請假流程失敗:", e);
- redirectAttributes.addFlashAttribute("error", "系統內部錯誤!
");
- }
- return "redirect:/oa/leave/apply";
- }
動態代理:
- package com.tgb.itoo.activiti.controller;
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import java.util.Map;
- import org.activiti.engine.IdentityService;
- import org.activiti.engine.RuntimeService;
- import org.activiti.engine.runtime.ProcessInstance;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import org.springframework.transaction.annotation.Transactional;
- import com.tgb.itoo.basic.entity.Leave;
- @Component
- @Transactional
- public class StartNode{
- private Logger logger = LoggerFactory.getLogger(getClass());
- //定義一個屬性變量
- private Map<String, Object> variables;
- private String businessKey;
- //設置人人員
- protected IdentityService identityService;
- @Autowired
- public void setIdentifyService(IdentityService identityService) {
- this.identityService = identityService;
- }
- protected RuntimeService runtimeService;
- @Autowired
- public void setRuntimeService(RuntimeService runtimeService) {
- this.runtimeService = runtimeService;
- }
- @Autowired
- RuntimeService runtimeService1;
- public void common(String businessKey,Map<String, Object> variables,RuntimeService runtimeService,IdentityService identityService){
- this.variables=variables;
- this.businessKey=businessKey;
- this.runtimeService=runtimeService;
- this.identityService=identityService;
- }
- //想嘗試是否能依據其它方式傳參。new的話太耗費資源
- /*public StartAbstractJBPM(String pdKey,Map<String, Object> variablesMap,JBPMService jbpmService){
- this.variablesMap=variablesMap;
- this.pdKey=pdKey;
- this.jbpmService=jbpmService;
- }*/
- //動態代理類僅僅能代理接口(不支持抽象類),代理類都須要實現InvocationHandler類,實現invoke方法。
該invoke方法就是調用被代理接口的全部方法時須要調用的,該invoke方法返回的值是被代理接口的一個實現類
- public class LogHandler1 implements InvocationHandler{
- // 目標對象
- private Object targetObject;
- //綁定關系,也就是關聯到哪個接口(與詳細的實現類綁定)的哪些方法將被調用時,運行invoke方法。
- public Object newProxyInstanceStart(Object targetObject){
- this.targetObject=targetObject;
- //該方法用於為指定類裝載器、一組接口及調用處理器生成動態代理類實例
- //第一個參數指定產生代理對象的類載入器,須要將其指定為和目標對象同一個類載入器
- //第二個參數要實現和目標對象一樣的接口,所以僅僅須要拿到目標對象的實現接口
- //第三個參數表明這些被攔截的方法在被攔截時須要運行哪個InvocationHandler的invoke方法
- //依據傳入的目標返回一個代理對象
- return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
- targetObject.getClass().getInterfaces(),this);
- }
- @Override
- //關聯的這個實現類的方法被調用時將被運行
- // InvocationHandler接口的方法。proxy表示代理,method表示原對象被調用的方法,args表示方法的參數
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- System.out.println("start-->>");
- for(int i=0;i<args.length;i++){
- System.out.println(args[i]);
- }
- Object ret=null;
- try{
- //原對象方法調用前處理日志信息
- System.out.println("satrt-->>");
- //啟動流程
- //調用目標方法
- Leave leave=(Leave)args[0];
- // 用來設置啟動流程的人員ID,引擎會自己主動把用戶ID保存到activiti:initiator中
- try {
- identityService.setAuthenticatedUserId(leave.getUserId());
- ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("ChangeCourse", businessKey, variables);
- String processInstanceId = processInstance.getId();
- leave.setProcessInstanceId(processInstanceId);
- logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"ChangeCourse", processInstanceId, variables});
- } finally {
- identityService.setAuthenticatedUserId(null);
- }
- args[0]=leave;
- ret=method.invoke(targetObject, args);
- //調用完畢當前結點
- // >> 辦理完第1個任務“提交申請”
- //jbpmService.completeFirstTask(pi);
- //原對象方法調用后處理日志信息
- System.out.println("success-->>");
- }catch(Exception e){
- e.printStackTrace();
- System.out.println("error-->>");
- throw e;
- }
- return ret;
- }
- }
- }
- /**
- * 任務列表ERROR [stderr] (http-localhost/127.0.0.1:8080-3) ScriptEngineManager providers.next(): javax.script.ScriptEngineFactory: Provider com.sun.script.javascript.RhinoScriptEngineFactory not found
- *
- * @param leave
- */
- @RequestMapping(value = "list/task")
- public ModelAndView taskList(HttpSession session, HttpServletRequest request) {
- List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
- String userId = UserUtil.getUserFromSession(session).getId();
- results=abstractTaskList(userId);
- return new ModelAndView("/oa/leave/taskList","results",results);
- }
- /**
- * 抽象出來的查看任務列表。與基本業務無關
- *
- * @param userId 用戶id
- * @return
- */
- public List<Map<String, Object>> abstractTaskList(String userId){
- List<Leave> results = new ArrayList<Leave>();
- // 依據當前人的ID查詢
- TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(userId);
- List<Task> tasks = taskQuery.list();
- int i=0;
- List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
- // 依據流程的業務ID查詢實體並關聯
- for (Task task : tasks) {
- String processInstanceId = task.getProcessInstanceId();
- ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
- String businessKey = processInstance.getBusinessKey();
- if (businessKey == null) {
- continue;
- }
- Map<String, Object> map = new HashMap<String, Object>();
- Leave leave = leaveBean.findEntityById(businessKey);
- //leave.setProcessInstance(processInstance);
- //leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
- //leave.setTask(task);
- map.put("leave", leave);//存入“申請信息”
- map.put("task", task);
- map.put("processDefinition", getProcessDefinition(processInstance.getProcessDefinitionId()));
- map.put("processInstance", processInstance);//存入“流程實例”
- mapList.add(map);
- /*Leave leave=updateEntity(processInstance,task,businessKey);
- results.add(leave); */
- i=i+1;
- }
- return mapList;
- }
- /**
- * 讀取執行中的流程實例(查看我的申請)involvedUser(userId)(涉及到的用戶)
- *
- * @return
- */
- @RequestMapping(value = "list/running")
- public ModelAndView runningList(HttpSession session,HttpServletRequest request) {
- String userId = UserUtil.getUserFromSession(session).getId();
- List<Map<String, Object>> results = new ArrayList<Map<String, Object>>();
- results=abstractRuningList(userId);
- return new ModelAndView ("/oa/leave/running","results",results);
- }
- /**
- * 抽象出來讀取執行中的流程實例(查看我的申請)。與基本業務無關
- *
- * @param userId 用戶id
- * @return
- */
- public List<Map<String, Object>> abstractRuningList(String userId){
- List<Leave> results = new ArrayList<Leave>();
- ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery().processDefinitionKey("ChangeCourse").involvedUser(userId).active().orderByProcessInstanceId().desc();//依據流程定義Key查詢流程實例
- List<ProcessInstance> list = query.list();
- List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
- // 關聯業務實體
- for (ProcessInstance processInstance : list) {
- String businessKey = processInstance.getBusinessKey();
- if (businessKey == null) {
- continue;
- }
- // 設置當前任務信息
- List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).active().orderByTaskCreateTime().desc().listPage(0, 1);
- Map<String, Object> map = new HashMap<String, Object>();
- Leave leave = leaveBean.findEntityById(businessKey);
- /*leave.setProcessInstance(processInstance);
- leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
- leave.setTask(tasks.get(0));*/
- map.put("leave", leave);//存入“考試信息”
- map.put("task", tasks.get(0));
- map.put("processDefinition", getProcessDefinition(processInstance.getProcessDefinitionId()));
- map.put("processInstance", processInstance);//存入“流程實例”
- mapList.add(map);
- /*Leave leave=updateEntity(processInstance,task,businessKey);
- results.add(leave); */
- //Leave leave=updateEntity(processInstance,tasks.get(0),businessKey);
- }
- return mapList;
- }
- /**
- * 讀取完畢的流程實例(已經完畢的流程申請-我)
- *
- * @return
- */
- @RequestMapping(value = "list/finished")
- public ModelAndView finishedList(HttpSession session,HttpServletRequest request) {
- String userId = UserUtil.getUserFromSession(session).getId();
- List<Leave> results = new ArrayList<Leave>();
- HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("ChangeCourse").involvedUser(userId).finished().orderByProcessInstanceEndTime().desc();
- List<HistoricProcessInstance> list = query.list();
- List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
- // 關聯業務實體
- for (HistoricProcessInstance historicProcessInstance : list) {
- Map<String, Object> map = new HashMap<String, Object>();
- String businessKey = historicProcessInstance.getBusinessKey();
- Leave leave = leaveBean.findEntityById(businessKey);
- /* leave.setProcessDefinition(getProcessDefinition(historicProcessInstance.getProcessDefinitionId()));
- leave.setHistoricProcessInstance(historicProcessInstance);
- results.add(leave);*/
- map.put("leave", leave);//存入“申請信息”
- map.put("processDefinition", getProcessDefinition(historicProcessInstance.getProcessDefinitionId()));
- map.put("historicProcessInstance", historicProcessInstance);//存入“流程實例”
- mapList.add(map);
- }
- return new ModelAndView("/oa/leave/finished","results",mapList);
- }
- /**
- * 完畢任務
- *
- * @param id
- * @return
- */
- @RequestMapping(value = "/complete/{id}", method = {RequestMethod.POST, RequestMethod.GET})
- @ResponseBody
- public String complete(@PathVariable("id") String taskId, Variable var) {
- try {
- //deptLeaderPass=true or hrBackReason=666, hrPass=false-----{leaderBackReason=78, deptLeaderPass=false}
- Map<String, Object> variables = var.getVariableMap();
- //taskService.getVariables(taskId);
- //Object variablesResult=variables.get("deptLeaderPass");
- //variablesResult=variables.get("hrPass");
- taskService.complete(taskId, variables);
- //獲取map中的值
- // if(hrPass=true){
- // //更新業務表信息
- // }
- return "success";
- } catch (Exception e) {
- logger.error("error on complete task {}", new Object[]{taskId, e});
- return "error";
- }
- }
總結:
對於在流程與業務的整合中應用動態代理也不知道是否符合AOP的理念,類似其它方面的流程操作還未抽取出來(交互太多),在這里記錄一下學習Activiti的一個過程,在之后的嘗試中能夠換個方式。換個思路,直接將整個工作流應用抽取出來(請假,改動課程等)。