继上篇博客:【整合篇】JBPM4.4业务与流程的整合
对于无论是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的一个过程,在之后的尝试中可以换个方式,换个思路,直接将整个工作流应用抽取出来(请假,修改课程等)。