Jbpm学习二

本文介绍了一个基于JBPM的工作流引擎实现的报销流程定义及其实现细节,包括流程定义文件的结构、Java类的设计以及流程实例的创建和流转等关键步骤。
一个简单的流程定义文件

<?xml version="1.0" encoding="UTF-8"?>
<process-definition name="ExpenseAccountSwim">
<swimlane name="initiator">
<assignment actor-id="#{firstPerson}" />
</swimlane>
<start-state name="startLog">
<transition name="到填写报销单" to="startExpense"></transition>
</start-state>
<task-node name="startExpense">
<task name="填写报销单" swimlane="initiator">
</task>
<transition name="到经理审核" to="managerAudit"></transition>
</task-node>
<task-node name="managerAudit">
<task name="经理审核">
<assignment actor-id="1" />
</task>
<transition name="到会计审核" to="accountantAudit"></transition>
<transition name="重新填写报销单" to="startExpense"></transition>
</task-node>
<task-node name="accountantAudit">
<task name="会计审核">
<assignment actor-id="3" />
</task>

<transition name="通知领款" to="lingkuan"></transition>
</task-node>
<task-node name="lingkuan">
<task name="领款" swimlane="initiator">
</task>

<transition name="审核完毕" to="endLog"></transition>
</task-node>
<end-state name="endLog"></end-state>
</process-definition>


报销单对应的java是

public class ExpenseAccount implements java.io.Serializable {
private int id;

private int expense;//报销费用
private String type;//报销类型
/**
* 描述
* @hibernate.property
*/
private String description;
private long processInstanceId;//流程实例id
.....getter
.....setter

}


发布完流程定义文件后。
我们填写报销单,并建立一个流程实例,将填写的报销单和这个流程实例绑定。

public void saveExpenseAccount(IBean domain,String definitionName) {
ExpenseAccount expenseAccount = (ExpenseAccount) domain;
expenseAccount.setDeleteFlag("1");
expenseAccount.setCreateDate(Common.getCurrentTime());
allDao.insert(expenseAccount);

//绑定流程实例
allDao.createProcessInstance(definitionName,expenseAccount.getCreateUser(),expenseAccount.getId());
}


/**
* 建立流程实例并绑定流程实例
*
* @param definitionName
* 流程名称
* @param personId
* 提交人id
* @param docId
* 公文id(申请单id)
*/
public void createProcessInstance(String definitionName, String personId,
int docId) {
JbpmContext context = null;
try {
context = getContext();

// 从数据库中加载ProcessDefinition对象
ProcessDefinition definition = context.getGraphSession()
.findLatestProcessDefinition(definitionName);

// 从流程中创建一个流程实例
ProcessInstance processInstance = new ProcessInstance(definition);


// 加载公文
ExpenseAccount doc = (ExpenseAccount) context.getSession().load(
ExpenseAccount.class, docId);

// 绑定流程实例到公文
doc.setProcessInstanceId(processInstance.getId());

// 绑定公文到流程实例(ContextInstance-相当于一个变量的实例)
processInstance.getContextInstance().createVariable("document",
doc.getId());
processInstance.getContextInstance().setVariable("firstPerson",
personId);

processInstance.getContextInstance().setVariable("money",doc.getExpense());

// 触发流程实例走向下一步
processInstance.signal();

// 将第一个提交人改为动态的,<assignment actor-id="#{firstPerson}" />,要设置任务的执行者。
TaskInstance taskInstance = (TaskInstance) processInstance
.getTaskMgmtInstance().getTaskInstances().iterator().next();
taskInstance.setActorId(personId);
taskInstance.setVariable("firstPerson", personId);
// 存储流程实例的信息
context.save(processInstance);
} catch (Exception e) {
e.printStackTrace();
} finally {
context.close();
}

}


然后用户提交这个报销单。

/**
* 触发流程向下一步流动,适用于当前只用一个transition,通过页面选择的transition,直接end到transition
*
* @param personId
* 登录人id
* @param processInstanceId
* 流程实例id
*
* @param transitionName transition名称
*/
public String flowToNextNode(String personId, long processInstanceId,String transitionName) {

JbpmContext context = jbpmConfiguration.createJbpmContext();
context.setSession(getSession());
try{
List tasks = context.getTaskMgmtSession().findTaskInstances(personId);
for (Iterator it = tasks.iterator(); it.hasNext();) {

TaskInstance taskInstance = (TaskInstance) it.next();
//判断流程实例是否一致
if (processInstanceId == taskInstance.getProcessInstance().getId()) {
taskInstance.end(transitionName);
} else {
continue;
}
}
}finally{
context.close();
}


return "";
}

此时报销单回流转到
managerAudit,他的执行者是actor-id="1" .
查询actor-id="1"的任务列表。

// 查找等待审批的公文
public List searchApprovingDocuments(String aoctor_Id) {


JbpmContext context = getContext();

List docIds = new ArrayList();

// 首先获得流转到用户的任务列表
List tasks = context.getTaskMgmtSession().findTaskInstances(aoctor_Id);
for (Iterator iter = tasks.iterator(); iter.hasNext();) {
System.out.println("tasks");
TaskInstance taskInstance = (TaskInstance) iter.next();

// 任务实例是否正在等待审批,如果不是,则忽略(即不应该被列到待审批列表中!)
if (!taskInstance.isSignalling()) {
continue;
}


Integer docId = Integer.parseInt(String.valueOf(taskInstance
.getProcessInstance().getContextInstance().getVariable(
"document")));
docIds.add(docId);
}

return docIds;
}

//上面只是返回的任务id,然后可以根据id查询出该用户要审核的报销单:如下面
String docIds="1,2,3,4,5";
//select * from ExpenseAccount where id in(docIds);


上面会列出所有要审核的报销单,选择一个报销单时,因为该节点有一个或多个Transition
,如果是多个时,就要让用户选择Transition,所以可以显示的在页面上列出Transition供用户选择。

/**
* 获得当前流程实例下的transition
* @param processInstanceId 流程实例id
* */
public List getTransitions(String personId,long processInstanceId){
List list=new ArrayList();
TaskInstance taskInstance=null;
JbpmContext context=jbpmConfiguration.createJbpmContext();
context.setSession(this.getSession());

try{
List tasks=context.getTaskMgmtSession().findTaskInstances(personId);
if(tasks!=null&&tasks.size()>0){
for(Iterator it=tasks.iterator();it.hasNext();){
taskInstance = (TaskInstance) it.next();
if(processInstanceId==taskInstance.getProcessInstance().getId()){

List listTrans=taskInstance.getTask().getTaskNode().getLeavingTransitions();
list.addAll(listTrans);
}
}
}


}catch(Exception e){
e.printStackTrace();

}finally{
context.close();
}

return list;


}

我用struts2的<s:select >来显示

<c:if test="${!empty transList}">
<s:select list="transList" name="transname" listKey="name" listValue="name" headerKey="0" headerValue="--请选择--"></s:select>
</c:if>

后面的审核都是反复的调用flowToNextNode方法。
actor-id="#{firstPerson}" 表示可以在java文件中定义执行者,可以看到上面在新增报销单时定义
processInstance.getContextInstance().setVariable("firstPerson",personId);

<swimlane name="initiator">
如果一个任务用同一个角色或人来执行,那么可以用swimlane 来定义任务参与者或执行者。在任务中只需要引用就行。
<task name="填写报销单" swimlane="initiator">

<task name="领款" swimlane="initiator">
【评估多目标跟踪方法】9个高度敏捷目标在编队中的轨迹和测量研究(Matlab代码实现)内容概要:本文围绕“评估多目标跟踪方法”,重点研究9个高度敏捷目标在编队飞行中的轨迹生成与测量过程,并提供完整的Matlab代码实现。文中详细模拟了目标的动态行为、运动约束及编队结构,通过仿真获取目标的状态信息与观测数据,用于验证和比较不同多目标跟踪算法的性能。研究内容涵盖轨迹建模、噪声处理、传感器测量模拟以及数据可视化等关键技术环节,旨在为雷达、无人机编队、自动驾驶等领域的多目标跟踪系统提供可复现的测试基准。; 适合人群:具备一定Matlab编程基础,从事控制工程、自动化、航空航天、智能交通或人工智能等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①用于多目标跟踪算法(如卡尔曼滤波、粒子滤波、GM-CPHD等)的性能评估与对比实验;②作为无人机编队、空中交通监控等应用场景下的轨迹仿真与传感器数据分析的教学与研究平台;③支持对高度机动目标在复杂编队下的可观测性与跟踪精度进行深入分析。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注轨迹生成逻辑与测量模型构建部分,可通过修改目标数量、运动参数或噪声水平来拓展实验场景,进一步提升对多目标跟踪系统设计与评估的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值