利用JBPM4.4的AssignmentHandler实现用户角色整合另一种构思

本文探讨了JBPM4中任务分配的问题,特别是如何利用AssignmentHandler接口动态调整任务负责人。介绍了自定义AssignTask类和UserAssignHandler类的方法,以实现更灵活的任务分配策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Jbpm4提供的IdentitySession接口并不是一种很好的处理方式,鉴于我们每个业务系统都有一套自己的用户及权限认证管理机制,需要与jbpm4.4集成的话,就比较周折了,我们经常需要查询的就是用户自己的任务。jbpm4的任务里有一个比较好的任务人员指派定义方式,就是使用AssignmentHandler接口,其定义如下所示:

Java代码 复制代码
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <processname="TaskAssignmentHandler"xmlns="http://jbpm.org/4.4/jpdl">
  3. <startg="20,20,48,48">
  4. <transitionto="review"/>
  5. </start>
  6. <taskname="review"g="96,16,127,52">
  7. <assignment-handlerclass="org.jbpm.examples.task.assignmenthandler.AssignTask">
  8. <fieldname="assignee">
  9. <stringvalue="johndoe"/>
  10. </field>
  11. </assignment-handler>
  12. <transitionto="wait"/>
  13. </task>
  14. <statename="wait"g="255,16,88,52"/>
  15. </process>
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <processname="TaskAssignmentHandler"xmlns="http://jbpm.org/4.4/jpdl">
  3. <startg="20,20,48,48">
  4. <transitionto="review"/>
  5. </start>
  6. <taskname="review"g="96,16,127,52">
  7. <assignment-handlerclass="org.jbpm.examples.task.assignmenthandler.AssignTask">
  8. <fieldname="assignee">
  9. <stringvalue="johndoe"/>
  10. </field>
  11. </assignment-handler>
  12. <transitionto="wait"/>
  13. </task>
  14. <statename="wait"g="255,16,88,52"/>
  15. </process>
<?xml version="1.0" encoding="UTF-8"?>

<process name="TaskAssignmentHandler" xmlns="http://jbpm.org/4.4/jpdl">

  <start g="20,20,48,48">
    <transition to="review" />
  </start>

  <task name="review" g="96,16,127,52">
    <assignment-handler class="org.jbpm.examples.task.assignmenthandler.AssignTask">
      <field name="assignee">
        <string value="johndoe" />
      </field>
    </assignment-handler>
    <transition to="wait" />
  </task>

  <state name="wait" g="255,16,88,52" />

</process>

Java代码 复制代码
  1. packageorg.jbpm.examples.task.assignmenthandler;
  2. importorg.jbpm.api.model.OpenExecution;
  3. importorg.jbpm.api.task.Assignable;
  4. importorg.jbpm.api.task.AssignmentHandler;
  5. /**
  6. *@authorTomBaeyens
  7. */
  8. publicclassAssignTaskimplementsAssignmentHandler{
  9. privatestaticfinallongserialVersionUID=1L;
  10. Stringassignee;
  11. publicvoidassign(Assignableassignable,OpenExecutionexecution){
  12. assignable.setAssignee(assignee);
  13. }
  14. }
  1. packageorg.jbpm.examples.task.assignmenthandler;
  2. importorg.jbpm.api.model.OpenExecution;
  3. importorg.jbpm.api.task.Assignable;
  4. importorg.jbpm.api.task.AssignmentHandler;
  5. /**
  6. *@authorTomBaeyens
  7. */
  8. publicclassAssignTaskimplementsAssignmentHandler{
  9. privatestaticfinallongserialVersionUID=1L;
  10. Stringassignee;
  11. publicvoidassign(Assignableassignable,OpenExecutionexecution){
  12. assignable.setAssignee(assignee);
  13. }
  14. }
package org.jbpm.examples.task.assignmenthandler;

import org.jbpm.api.model.OpenExecution;
import org.jbpm.api.task.Assignable;
import org.jbpm.api.task.AssignmentHandler;


/**
 * @author Tom Baeyens
 */
public class AssignTask implements AssignmentHandler {
  
  private static final long serialVersionUID = 1L;

  String assignee;

  public void assign(Assignable assignable, OpenExecution execution) {
    assignable.setAssignee(assignee);
  }
}

这要求我们在设计流程定义后,任务的处理人已经必须定下来了,但若我们在流程发布后,还需要手工改这里的任务执行人员(并且人员是我们系统的用户),甚至人员可能在流程运行过程中,由用户在任务表单或计算过程中动态指定,以上的方式并不能满足我们的要求。

基于这种想法,应该设计另一种允许用户修改流程定义中的人员,并且跟我们的系统用户角色结合起来。

jbpm4之后的版本,启动流程及运行流程时,都会去读取流程定义,因此,我们可以动态修改以上配置文件,让其生成类似如下的配置格式即可以满足我们的要求:

Java代码 复制代码
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <processname="TaskAssignmentHandler"xmlns="http://jbpm.org/4.4/jpdl">
  3. <startg="20,20,48,48">
  4. <transitionto="review"/>
  5. </start>
  6. <taskname="review"g="96,16,127,52">
  7. <assignment-handlerclass="com.htsoft.core.jbpm.AssignmentHandler">
  8. <fieldname="userIds">
  9. <stringvalue="1"/>
  10. </field>
  11. <fieldname="roleIds">
  12. <stringvalue="1,2"/>
  13. </field>
  14. </assignment-handler>
  15. <transitionto="wait"/>
  16. </task>
  17. <statename="wait"g="255,16,88,52"/>
  18. </process>
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <processname="TaskAssignmentHandler"xmlns="http://jbpm.org/4.4/jpdl">
  3. <startg="20,20,48,48">
  4. <transitionto="review"/>
  5. </start>
  6. <taskname="review"g="96,16,127,52">
  7. <assignment-handlerclass="com.htsoft.core.jbpm.AssignmentHandler">
  8. <fieldname="userIds">
  9. <stringvalue="1"/>
  10. </field>
  11. <fieldname="roleIds">
  12. <stringvalue="1,2"/>
  13. </field>
  14. </assignment-handler>
  15. <transitionto="wait"/>
  16. </task>
  17. <statename="wait"g="255,16,88,52"/>
  18. </process>
<?xml version="1.0" encoding="UTF-8"?>

<process name="TaskAssignmentHandler" xmlns="http://jbpm.org/4.4/jpdl">

  <start g="20,20,48,48">
    <transition to="review" />
  </start>

  <task name="review" g="96,16,127,52">
    <assignment-handler class="com.htsoft.core.jbpm.AssignmentHandler">
      <field name="userIds">
        <string value="1" />
      </field>
     <field name="roleIds">
        <string value="1,2" />
      </field>
    </assignment-handler>
    <transition to="wait" />
  </task>

  <state name="wait" g="255,16,88,52" />

</process>

以上的userIds的1,以及roleIds的1,2则代表我们系统中的用户id与角色的id,其值由后台用户在后面通过界面来设置。

其设置后,就生成以上的代码写至jbpm4_lob表中的blobvalue字段中去则可,这是持久化的处理。

也可以临时调用类似以下的代码动态实现以上效果:

Java代码 复制代码
  1. /**
  2. *为流程定义加上任务的指派人员接口
  3. *@paramdeployId
  4. */
  5. publicvoidaddAssignHandler(ProUserAssignproUserAssign){
  6. ProcessDefinitionImplpd=(ProcessDefinitionImpl)repositoryService.createProcessDefinitionQuery().deploymentId(proUserAssign.getDeployId()).uniqueResult();
  7. EnvironmentFactoryenvironmentFactory=(EnvironmentFactory)processEngine;
  8. EnvironmentImplenv=null;
  9. try{
  10. env=environmentFactory.openEnvironment();
  11. //找到任务的定义
  12. TaskDefinitionImpltaskDef=pd.getTaskDefinition(proUserAssign.getActivityName());
  13. UserCodeReferenceuserCodeReference=newUserCodeReference();
  14. ObjectDescriptordescriptor=newObjectDescriptor();
  15. //加上任务的人员动态指派
  16. descriptor.setClassName("com.htsoft.core.jbpm.UserAssignHandler");
  17. //动态加参数
  18. FieldOperationuserIdsFo=newFieldOperation();
  19. userIdsFo.setFieldName("userIds");
  20. userIdsFo.setDescriptor(newStringDescriptor(proUserAssign.getUserId()));
  21. FieldOperationgroupIdsFo=newFieldOperation();
  22. groupIdsFo.setFieldName("groupIds");
  23. groupIdsFo.setDescriptor(newStringDescriptor(proUserAssign.getRoleId()));
  24. List<Operation>listOp=newArrayList<Operation>();
  25. listOp.add(userIdsFo);
  26. listOp.add(groupIdsFo);
  27. descriptor.setOperations(listOp);
  28. userCodeReference.setCached(false);
  29. userCodeReference.setDescriptor(descriptor);
  30. taskDef.setAssignmentHandlerReference(userCodeReference);
  31. }catch(Exceptionex){
  32. logger.error("ADDAssignHandlerError:"+ex.getMessage());
  33. }finally{
  34. if(env!=null){
  35. env.close();
  36. }
  37. }
  38. }
  1. /**
  2. *为流程定义加上任务的指派人员接口
  3. *@paramdeployId
  4. */
  5. publicvoidaddAssignHandler(ProUserAssignproUserAssign){
  6. ProcessDefinitionImplpd=(ProcessDefinitionImpl)repositoryService.createProcessDefinitionQuery().deploymentId(proUserAssign.getDeployId()).uniqueResult();
  7. EnvironmentFactoryenvironmentFactory=(EnvironmentFactory)processEngine;
  8. EnvironmentImplenv=null;
  9. try{
  10. env=environmentFactory.openEnvironment();
  11. //找到任务的定义
  12. TaskDefinitionImpltaskDef=pd.getTaskDefinition(proUserAssign.getActivityName());
  13. UserCodeReferenceuserCodeReference=newUserCodeReference();
  14. ObjectDescriptordescriptor=newObjectDescriptor();
  15. //加上任务的人员动态指派
  16. descriptor.setClassName("com.htsoft.core.jbpm.UserAssignHandler");
  17. //动态加参数
  18. FieldOperationuserIdsFo=newFieldOperation();
  19. userIdsFo.setFieldName("userIds");
  20. userIdsFo.setDescriptor(newStringDescriptor(proUserAssign.getUserId()));
  21. FieldOperationgroupIdsFo=newFieldOperation();
  22. groupIdsFo.setFieldName("groupIds");
  23. groupIdsFo.setDescriptor(newStringDescriptor(proUserAssign.getRoleId()));
  24. List<Operation>listOp=newArrayList<Operation>();
  25. listOp.add(userIdsFo);
  26. listOp.add(groupIdsFo);
  27. descriptor.setOperations(listOp);
  28. userCodeReference.setCached(false);
  29. userCodeReference.setDescriptor(descriptor);
  30. taskDef.setAssignmentHandlerReference(userCodeReference);
  31. }catch(Exceptionex){
  32. logger.error("ADDAssignHandlerError:"+ex.getMessage());
  33. }finally{
  34. if(env!=null){
  35. env.close();
  36. }
  37. }
  38. }
/**
     * 为流程定义加上任务的指派人员接口
     * @param deployId
     */
    public void addAssignHandler(ProUserAssign proUserAssign){
    	ProcessDefinitionImpl pd=(ProcessDefinitionImpl)repositoryService.createProcessDefinitionQuery().deploymentId(proUserAssign.getDeployId()).uniqueResult();
    	 EnvironmentFactory environmentFactory = (EnvironmentFactory) processEngine;
		 EnvironmentImpl env=null;
		 try {
			 env = environmentFactory.openEnvironment();
			 //找到任务的定义
			 TaskDefinitionImpl taskDef=pd.getTaskDefinition(proUserAssign.getActivityName());
			 UserCodeReference userCodeReference = new UserCodeReference();
			 ObjectDescriptor descriptor = new ObjectDescriptor();
			 //加上任务的人员动态指派
			 descriptor.setClassName("com.htsoft.core.jbpm.UserAssignHandler");
			 //动态加参数
			 FieldOperation userIdsFo = new FieldOperation();
			 userIdsFo.setFieldName("userIds");	
			 userIdsFo.setDescriptor(new StringDescriptor(proUserAssign.getUserId()));
			 
			 FieldOperation groupIdsFo=new FieldOperation();
			 groupIdsFo.setFieldName("groupIds");
			 groupIdsFo.setDescriptor(new StringDescriptor(proUserAssign.getRoleId()));
			 
			 List<Operation> listOp=new ArrayList<Operation>();
			 listOp.add(userIdsFo);
			 listOp.add(groupIdsFo);
			 descriptor.setOperations(listOp);
			 
			 userCodeReference.setCached(false);
			 userCodeReference.setDescriptor(descriptor);
			 taskDef.setAssignmentHandlerReference(userCodeReference);
			 
		 }catch(Exception ex){
			 logger.error("ADD AssignHandler Error:" + ex.getMessage());
		 }finally{
			 if(env!=null){
				 env.close();
			 }
		 }
    }

不过该方式没有持久久,重启系统后,保存的用户及角色设置并不会生效。

UserAssignHandler类代码如下:

Java代码 复制代码
  1. packagecom.htsoft.core.jbpm;
  2. importorg.apache.commons.lang.StringUtils;
  3. importorg.apache.commons.logging.Log;
  4. importorg.apache.commons.logging.LogFactory;
  5. importorg.jbpm.api.model.OpenExecution;
  6. importorg.jbpm.api.task.Assignable;
  7. importorg.jbpm.api.task.AssignmentHandler;
  8. importcom.htsoft.core.Constants;
  9. /**
  10. *尚未开始使用
  11. *<B><P>Joffice--http://www.jee-soft.cn</P></B>
  12. *<B><P>Copyright(C)2008-2010GuangZhouHongTianSoftwareCompany(广州宏天软件有限公司)</P></B>
  13. *<B><P>description:</P></B>
  14. *<P></P>
  15. *<P>product:joffice</P>
  16. *<P></P>
  17. *@seecom.htsoft.core.jbpm.UserAssignHandler
  18. *<P></P>
  19. *@author
  20. *@versionV1
  21. *@create:2010-11-23下午02:58:01
  22. */
  23. publicclassUserAssignHandlerimplementsAssignmentHandler{
  24. privateLoglogger=LogFactory.getLog(UserAssignHandler.class);
  25. //授予用户ID
  26. StringuserIds;
  27. //授权角色ID
  28. StringgroupIds;
  29. @Override
  30. publicvoidassign(Assignableassignable,OpenExecutionexecution)throwsException{
  31. StringassignId=(String)execution.getVariable(Constants.FLOW_ASSIGN_ID);
  32. logger.info("assignId:===========>"+assignId);
  33. //在表单提交中指定了固定的执行人员
  34. if(StringUtils.isNotEmpty(assignId)){
  35. assignable.setAssignee(assignId);
  36. return;
  37. }
  38. //在表单中指定了执行的角色TODO
  39. //在表单中指定了会签人员
  40. StringsignUserIds=(String)execution.getVariable(Constants.FLOW_SIGN_USERIDS);
  41. if(signUserIds!=null){
  42. //TODO取到该任务,进行会签设置
  43. }
  44. logger.debug("EnterUserAssignHandlerassignmethod~~~~");
  45. if(userIds!=null){//若用户不为空
  46. String[]uIds=userIds.split("[,]");
  47. if(uIds!=null&&uIds.length>1){//多于一个人的
  48. for(StringuId:uIds){
  49. assignable.addCandidateUser(uId);
  50. }
  51. }else{
  52. assignable.setAssignee(userIds);
  53. }
  54. }
  55. if(groupIds!=null){//若角色组不为空
  56. String[]gIds=userIds.split("[,]");
  57. if(gIds!=null&&gIds.length>1){//多于一个角色的
  58. for(StringgId:gIds){
  59. assignable.addCandidateGroup(gId);
  60. }
  61. }else{
  62. assignable.addCandidateGroup(groupIds);
  63. }
  64. }
  65. }
  66. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值