You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Activiti任务分配疑问:如何为用户或用户组分配任务

解决Activiti任务分配时单用户选择的Candidate Groups空值异常

这个问题我之前做Activiti流程开发时也碰到过,核心原因是Activiti对Candidate Groups属性的表达式解析要求比Assignee更严格:当你只选择单个用户时,${selectedGroup}变量大概率是null,而Activiti要求Candidate Groups的表达式必须解析为字符串或字符串集合,null会直接触发ActivitiIllegalArgumentException;但Assignee属性允许null值,所以选组时Assignee为空不会报错。

给你几个简单有效的解决方案:

1. 用Activiti表达式处理空值(推荐,流程设计层解决)

在流程定义的Candidate Groups属性里,修改表达式为:

${empty selectedGroup ? '' : selectedGroup}

或者另一种等价写法:

${selectedGroup != null ? selectedGroup : ''}

这样当用户没选择组时,表达式会返回空字符串,Activiti会将其视为“无候选组”,不会抛出异常;当选择组时,正常传入组名即可。

2. 变量传入前预处理(后端/前端处理)

在把变量传递给Activiti之前,手动处理selectedGroup的值:

  • 如果是Java后端:
Map<String, Object> processVars = new HashMap<>();
processVars.put("selectedPerson", selectedPerson);
// 处理空值,将null转为空字符串
processVars.put("selectedGroup", selectedGroup != null ? selectedGroup : "");

// 启动流程或分配任务
runtimeService.startProcessInstanceByKey("yourProcessKey", processVars);
  • 如果是前端传递参数,确保当没选择组时,selectedGroup字段传空字符串而不是null。

3. 验证效果

修改后测试两种场景:

  • 选择单个用户:Assignee设置为${selectedPerson},Candidate Groups解析为空字符串,Activiti只会给指定用户分配任务,无异常。
  • 选择用户组:Assignee为空(如果没选用户),Candidate Groups正常生效,任务分配给整个组。

附你提供的异常堆栈:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.activiti.engine.ActivitiIllegalArgumentException: Expression did not resolve to a string or collection of strings
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(AbstractInstrumentedFilter.java:97)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:149)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:168)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
com.activiti.security.CustomStatelessCSRFFilter.doFilterInternal(CustomStatelessCSRFFilter.java:68)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)

内容的提问来源于stack exchange,提问作者Master Yoda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:13:01