动手实现了一下activiti下实现中国特色的逐级审批。
准备工作是写一个人力资源服务类并将它注入到applicationContext;这个服务类就是模拟上下级关系:kermit -> gonzo -> fozzie ->john. 这个类在流程中的作用就是查找用户的直接上级;
public class HumanService { public String getDirectLeader(String user){ if("kermit".equals(user)){ return "gonzo"; } else if("gonzo".equals(user)){ return "fozzie"; } else if("fozzie".equals(user)){ return "john"; } else{ return null; } } }
<bean id="humanService" class="test.basic.HumanService" />
新建一个流程,有两个人工任务:员工提交一个休假请求,老板逐级审批。
有一个流程变量叫做currentOperator, 用来存放当前操作人;在流程开始节点的表单上我定义了一个field映射到currentOperator(这样做只是为了图省事,没有其他目的)
用户提交请求的任务上定义两个表单字段,分别表示请假天数和原因,当然他们也和同名的流程变量对应;同时我给该节点分配的assignee为kermit以方便测试;
在老板审批节点上,设置assignee为表达式${humanService.getDirectLeader(currentOperator)}。意义不用我多说;
审批节点定义一个field用来接收当前操作人,并映射为流程变量currentOperator.
设置multi instance选项, Sequential=true,因为逐级审批,所以需顺序执行;loop cardinality=10, 为什么设置这个呢?因为如果一个节点需多次运行,则至少要设置运行次数或者遍历对象collection.对于逐级审批来说,这两个都不适合为固定量,因 为人事结构可能随时变化;所以我耍了点小聪明,设置运行次数loop cardinality绝对大于可能的运行次数,同时设置结束条件completion condition=${humanService.getDirectLeader(currentOperator)==null}, 即当找不到操作人的上级的时候就该结束了。
下面是测试用例:
public class TestMultiInstance extends TestCase { private static final Logger log = LoggerFactory.getLogger(Test.class); public void test() throws InterruptedException { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext( "applicationContext.xml"); RuntimeService runtimeService = (RuntimeService) ctx .getBean("runtimeService"); ProcessEngine processEngine = (ProcessEngine) ctx .getBean("processEngine"); FormService formService = processEngine.getFormService(); TaskService taskService = (TaskService) ctx.getBean("taskService"); Map map = new HashMap(); map.put("currentOperator", "kermit"); // start a process multiInstanceTest; runtimeService.startProcessInstanceByKey("multiInstanceTest", map); // query kermit's tasks; List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit") .list(); for (Task task : tasks) { Map info = new HashMap(); map.put("leaveDays", "12"); map.put("leaveReason", "I will go home"); // complete kermit's task with assigned parameters; taskService.complete(task.getId(), info); } // query gonzo's tasks; tasks = taskService.createTaskQuery().taskAssignee("gonzo").list(); for (Task task : tasks) { System.out.println("gonzo has job to do"); Map info = new HashMap(); info.put("currentOperator", task.getAssignee()); // complete gonzo's task; taskService.complete(task.getId(), info); } // query fozzie's tasks; tasks = taskService.createTaskQuery().taskAssignee("fozzie").list(); for (Task task : tasks) { System.out.println("fozzie has job to do"); Map info = new HashMap(); info.put("currentOperator", task.getAssignee()); // complete fozzie's task; taskService.complete(task.getId(), info); } // query john's tasks; tasks = taskService.createTaskQuery().taskAssignee("john").list(); for (Task task : tasks) { System.out.println("john has job to do"); Map info = new HashMap(); info.put("currentOperator", task.getAssignee()); //complete john's task; taskService.complete(task.getId(), info); } } }
测试结果:
kermit has job to do gonzo has job to do fozzie has job to do john has job to do
所以综上,在流程系统提供一定的基础设施(如HumanService和表单引擎)的情况下, 可以不编写任何代码而配置一个逐级审批模型出来。