动手实现了一下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和表单引擎)的情况下, 可以不编写任何代码而配置一个逐级审批模型出来。