assignee

更新时间:2022-11-27 10:40:27 阅读: 评论:0


2022年11月27日发(作者:摩登家庭第二季下载)

activiti5⼊门(四)流程图之六⼤构成元素

1、Events事件

2、Tasks任务(任务⽆法删除,只能结束。执⾏任务只要taskId即可,不需要当前⽤户,因为不排除⽤户离职的情况)

3、Gateways⽹关

4、Container容器

5、Connection连接

6、Artifacts说明

-----------------------------------------------------------

仅涉及Tasks任务的流程图实例:

根据⽤户查询当前任务:

StringurId=(String)sion().getAttribute("urId");这个urid和流程图xml格式中的activiti:assignee⼀致

ListtaskLists=TaskQuery().taskAssignee(urId).list();

如果我们在流程图⾥没有指定⽤户,⽽是⽤${urId}指定,那么最好每个urtask都要⽤不同的${xxx},因为如果相同,就说明这个

urTask是同⼀个⼈

那我们怎么⽤起来呢?

在流程启动的时候就要把它⽤进去:

Mapmap=newHashMap<>();

("urId","admin1");()...

rocessInstanceByKey(pdKey,bussinessId,map);

这样就在代码中指定了⽤户,这样每个流程实例都可能会有不同的⼈

注意,这⾥使⽤了bussinessId,这个值的作⽤,可以理解为它是另外⼀张业务表(⾮activiti表)的某个主键字段,这个字段会被很多其他

业务表引⽤,当我们查询act_hi_procinst表时就会⽤到BUSINESS_KEY_这个字段。不⽤查,⽤inessKey();即可

⽤户执⾏任务:

StringtaskId=ameter("taskId");

te(taskId);

可见只要知道任务id即可,不关⼼真正的⽤户是谁

每执⾏⼀次任务,act_ru_task表中不会增加⼀条数据,⽽是更新⼀条数据,且把ID都更新了,那原来那条数据保存在哪⾥?保存在

act_hi_taskinst中。

----------------------------------

ACT_RU_EXECUTION表中的executionID⼀般与流程实例ID相同,所以流程实例有多少条,他就有多少条,当⼀个流程⾛到某个节点,此时这个节点既有

urtask⼜有消息边界事件,那么ACT_RU_EXECUTION中会多出⼀个⼀条数据,假设ID为0001,这条数据的⽗ID是该流程,在act_ru_task表和

act_ru_event_subscr都会出现⼀条数据,表中的执⾏ID不再是流程ID,⽽是0001。正常情况下,执⾏任务ID和流程ID都是⼀致的。当存在不知道要⾛哪个时,

就会多出⼀条数据,即流程ID的延伸流程。出现这种情况如何获取执⾏ID?

Executionexecution=ExecutionQuery().messageEventSubscriptionName("全局消息名").singleResult();

eEventReceived("全局消息名",());//相当于执⾏了消息边界事件,没有执⾏urtask。

--------------------------

根据流程实例id查询当前任务(流程实例理解为譬如⼀张请假单)

ListtaskLists=TaskQuery().processInstanceId(piId).list();

-------------------

查询所有历史流程实例,涉及act_hi_procinst表

HistoryServicehistoryService=toryService();

ListhpiLists=

HistoricProcessInstanceQuery().orderByProcessInstanceId().asc().list();

根据某历史流程实例id查询对应的历史任务(包括没有执⾏完的历史流程)涉及act_hi_taskinst表

HistoryServicehistoryService=toryService();

ListhtiLists=HistoricTaskInstanceQuery().processInstanceId(hpiId).list();

----------------------------------------------------

当urtask的⽤户为候选⼈时

例如xml中为activiti:candidateUrs="xxx1,xxx2,xxx13":指定候选⼈.(拉模式),

那么在⽤流程实例查询时是找不到指定⼈的,⼀定要有个指定⼈去认领任务才有⽤

TaskQuerytq=TaskQuery();

ListcandidateUrTaskLists=ndidateUr(urId).list();

//迭代任务

for(Tasktask:candidateUrTaskLists){

//领取任务

((),urId);//领取任务时,也就是所谓的任务分配时,因为这个时候有assignee了

}

//根据任务的处理⼈查询任务

ListtaskLists=TaskQuery().taskAssignee(urId).list();//注意这⾥⼜要去重新获取⼀把任务查询,因为

不重新获取,查的还是⽼数据,有种默认可重复读的感觉

-----------------------------------------------

当urtask的⽤户为候选组,且⽤了变量${group}时,那么在启动流程实例时,

("group","g1");//这⾥g1⽤字符串仅表⽰组名,不代表组员。因为业务中最后可能是根据⽤户名查找到组名,然后通过组名查找

到这个组的所有任务

rocessInstanceById(pdId,map);

查询组任务:

StringurId=(String)sion().getAttribute("urId");

Mapmap=newHashMap<>();

String[]arr={"a","b","c"};

ListasList=(arr);

("g1",asList);//这⾥只是模拟表⽰g1这个组有abc三个⽤户

Stringgroup=null;

for(Entryentry:et()){

Listlist=(List)ue();

if(ns(urId)){//根据⽤户找到⽤户所在组

group=();

}

}

ListtaskLists1=newArrayList<>();

if(group!=null){

taskLists1=TaskQuery().taskCandidateGroup(group).list();//根据⽤户所在组名找到所有任务

}

for(Tasktask:taskLists1){

((),urId);//第⼀个登录的⽤户将认领任务,同时这个组就不在有这个任务,即

taskCandidateGroup(group).list()将没有任务

}

ListtaskLists2=TaskQuery().taskAssignee(urId).list();//当⽤户认领后,那么act_ru_task中这个任务

的Assignee就是他了,它就能查到。没有领取任务的⽤户就查不到任务,除⾮是其它⾮组任务

ribute("taskLists",taskLists2);

uestDispatcher("/").forward(request,respon);

-----------------------------------------------------------

urTask的监听器

总共有4种:

create表⽰当创建任务时触发。

assignment表⽰当任务被分配后触发。

complete表⽰当任务完成后触发。

activiti中的表达式是${}形式,也有#{},后者在监听器中的表达式中有使⽤,也叫流程变量,在⼀个流程中有效。在启动流程时或在该

urtask之前要做好初始化。放map中。

要使⽤监听器,我们必须在流程图中找到urtask⾥⾯的listener,然后新建,指定我们⾃定义的监听器。我们写的监听器要实现

TaskListener。

以创建时定时器为例⼦:

publicclassCreateTaskListenerimplementsTaskListener{

privateExpressionname;//这个变量是在流程图中指定的,可以⽤来传⼊到java代码中

privateExpressionage;

@Override

publicvoidnotify(DelegateTaskdelegateTask){//DelegateTask称为委派任务

n("事件:"+ntName());

n(ue(delegateTask));//使⽤getValue的⽅法获取流程图中监听器的变量

n(ue(delegateTask));

//分配任务

StringurId=(String)ue(delegateTask);

ignee(urId);//分配任务到某个⼈

//分配完成后,分配监听器开始启动

}

delegateTask的api有很多,⽐如获取所有流程变量等。

除了java类型的定时器,还有#{}表达式,⽐如#{()}就是⼀个。我们创建⼀个Ur类实现Serializable,因为要存数据库,所以要

实现序列化。#{()}⾥⾯是能传参数的,⽐如#{(‘james’)}。他也分create、create和complete。它是怎么找到ur

的。⼀样在启动流程实例时,使⽤map,("ur",newUr());

除了,java,expression,还有与spring连⽤的delegateexpression委托表达式,以后会说。

urtask不仅仅有tasklistener,也有executionlistener,与tasklistener的区别是,后者只有两个阶段,start和end,start会⽐creat

还早。另外实现的监听接⼝不⼀样,后者是ExecutionListener。

监听器中获取引擎的⽅式:cution().getEngineServices()就是引擎(ProcessEngine)

taskUr中的表单我们很少⽤,它要配合监听器使⽤,为的是在监听器中能获取表单服务。但表单⼀般我们都有⾃⼰的表。

taskur⾥⾯还有⼀个多实例,即表⽰⼀个任务必须多个⽤户都做好后才能⾛到下⼀步。

有⼏个选项:

Sequential为true表⽰有顺序,必须⼀个⼀个做;为fal表⽰⽆顺序,⽤户不必等前⼀个⽤户。

collection是⼀个变量名,如urList。在流程启动时赋值,如

ListurList=newArrayList<>();

("admin1");

("admin2");

("admin3");

("admin4");

("admin5");

("urList",urList);

elementVariable是⼀个变量名(必须的),在assignee⽤${admin}这个表⽰后,在multiInstance中就能⽤admin代表${admin}了

completionCondition条件:⽐如有5个⼈完成,我现在只有三个⼈完成,我也算他任务完成,那就要⽤

${nrOfCompletedInstances/nrOfInstances>=0.6}表⽰。其中nrOfCompletedInstances和nrOfInstances是activiti在

act_ru_variable中⽣成的字段名,表⽰已完成实例和总实例。在流程图中我们不需要指定Loop,因为collection⾥⾯就能知道循环次数

-----------------------------------------------------------------------

其它任务类型:

ScriptTask脚本任务(⾃动触发),写⼀段javascript脚本

ServiceTask服务任务(⾃动触发),写⼀个类实现ServiceTaskDelegate,和⾃定义监听器实现监听器接⼝类似

ManualTask⼿⼯任务(⾃动触发)

ReceiveTask接收任务(信号触发).这4种我们都很少⽤

邮件任务(挺有⽤):例⼦

依赖

s

commons-email

1.4

在部署前调⽤ProcessEngineConfiguration的

.tMailServerDefaultFrom("xxx@").tMailServerHost("")

.tMailServerUrname("xxx").tMailServerPassword("xxx");

在流程图中选择mailtask,在配置中⽤流程变量指定发送者,接受者等,如${to},${from},${subject}(主题)。它的正⽂有html格式

或者普通⽂本格式

最后在启动流程实例时

("to","zzz@");

("from","xxx@");

("subject","邮件任务");

即可。

-------------------------------------------

Events事件

⽤得最多的是StartEvent,可以在流程图中定义发起⼈,但我们可以不⽤这样做,我们⼀般将第⼀个任务看成是流程发起⼈

TimerStartEvent定时开始事件,它的定时时间由activiti特殊规定,但在使⽤前,要调⽤

ExecutorActivate(true)激活定时任务

MessageStartEvent消息开始事件,要先定义⼀个全局消息,在空⽩处点击,然后就可以在properties界⾯找到message,定义消息了。

然后在开始事件中引⽤这个消息,启动流程实例要⽤message,如rocessInstanceByMessage("xxx");xxx就是前

⾯全局消息的name值。

SignalStartEvent信号开始事件:要先定义⼀个全局信号,在空⽩处点击,然后就可以在properties界⾯找到signal,然后在开始事件中引

⽤这个消息,动流程实例要⽤signal,

EventReviced("xxx");xxx就是前⾯全局信号的name值。

结束事件ErrorEndEvent错误结束事件⽤于⼦流程。与ErrorBoundaryEvent错误边界事件(接收错误码)⼦流程连⽤

边界事件,只能放在任务上,⽐如任务不处理了,那么就可以由边界事件来完成

TimerBoundaryEvent定时边界事件,⽐如PT10S就是延迟10秒后做

MessageBoundaryEvent消息边界事件上⾯有提到过

SignalBoundaryEvent信号边界事件与上⾯是雷同的

定义全局信号,然后在边界事件引⽤它,

/**根据信号名查询执⾏对象*/

Executionexecution=ExecutionQuery().signalEventSubscriptionName("mySignal").singleResult();

/**信号事件接收完成当前信号边界事件*/

EventReceived("全局信号名",());

ErrorBoundaryEvent错误边界事件在⼦流程的时候说

中间捕获事件:

TimerCatchingEvent定时捕获事件

MessageCatchingEvent消息捕获事件

SignalCatchingEvent信号捕获事件

NoneThrowingEvent空引发事件

这个事件意义不⼤

-----------------------------

本文发布于:2022-11-27 10:40:27,感谢您对本站的认可!

本文链接:http://www.wtabcd.cn/fanwen/fan/90/30502.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:modernize
下一篇:weariness
标签:assignee
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图