任务(Task)管理: 用户任务、服务任务、脚本任务、人工任务的生命周期
2025/8/30大约 21 分钟
在企业级BPM平台中,任务管理是流程引擎的核心功能之一,它负责管理流程执行过程中产生的各种类型任务,包括用户任务、服务任务、脚本任务和人工任务等。一个完善的任务管理系统不仅要能够高效地创建、分配、执行和跟踪任务,还需要提供灵活的配置选项和强大的扩展能力。本文将深入探讨任务管理的设计与实现。
任务管理的核心价值
业务流程协调
任务管理在业务流程协调中发挥着关键作用:
- 任务创建:根据流程定义自动创建相应的任务
- 任务分配:将任务分配给合适的处理者
- 任务执行:协调任务的执行过程
- 任务完成:确保任务按预期完成并推进流程
用户体验优化
良好的任务管理能够显著提升用户体验:
- 任务可见性:用户可以清晰地看到待处理的任务
- 操作便捷性:提供简单直观的任务操作界面
- 通知及时性:及时通知用户新任务的到达
- 状态透明性:实时展示任务的执行状态
管理效率提升
任务管理为流程管理提供了高效的工具:
- 集中监控:通过统一界面监控所有任务状态
- 批量处理:支持批量处理多个任务
- 统计分析:提供任务执行的统计分析功能
- 绩效评估:支持基于任务执行的绩效评估
任务类型详解
用户任务(User Task)
用户任务是需要人工参与处理的任务类型:
基本特性
public class UserTask extends Task {
private String assignee; // 指定处理者
private List<String> candidateUsers; // 候选用户
private List<String> candidateGroups; // 候选用户组
private String dueDate; // 到期时间
private String priority; // 优先级
private String formKey; // 表单标识
private boolean skipExpression; // 跳过表达式
// getter和setter方法
}分配策略
静态分配
public class StaticAssignmentStrategy implements AssignmentStrategy {
@Override
public void assignTask(TaskEntity task, UserTask userTask) {
// 直接指定处理者
if (userTask.getAssignee() != null) {
task.setAssignee(userTask.getAssignee());
return;
}
// 指定候选用户
if (userTask.getCandidateUsers() != null && !userTask.getCandidateUsers().isEmpty()) {
for (String candidateUser : userTask.getCandidateUsers()) {
task.addCandidateUser(candidateUser);
}
}
// 指定候选用户组
if (userTask.getCandidateGroups() != null && !userTask.getCandidateGroups().isEmpty()) {
for (String candidateGroup : userTask.getCandidateGroups()) {
task.addCandidateGroup(candidateGroup);
}
}
}
}动态分配
public class DynamicAssignmentStrategy implements AssignmentStrategy {
@Override
public void assignTask(TaskEntity task, UserTask userTask) {
// 基于业务规则的动态分配
String assignee = determineAssignee(task, userTask);
if (assignee != null) {
task.setAssignee(assignee);
} else {
// 如果无法确定处理者,使用候选用户或用户组
applyFallbackAssignment(task, userTask);
}
}
private String determineAssignee(TaskEntity task, UserTask userTask) {
// 获取流程变量
Map<String, Object> variables = task.getExecution().getVariables();
// 根据业务规则确定处理者
// 例如:根据部门、职位、工作负载等因素
String department = (String) variables.get("department");
String priority = (String) variables.get("priority");
// 调用用户服务确定合适的处理者
UserService userService = ServiceRegistry.getUserService();
return userService.findSuitableAssignee(department, priority);
}
private void applyFallbackAssignment(TaskEntity task, UserTask userTask) {
// 应用备选分配策略
if (userTask.getCandidateUsers() != null && !userTask.getCandidateUsers().isEmpty()) {
// 随机选择一个候选用户
String randomUser = userTask.getCandidateUsers()
.get(new Random().nextInt(userTask.getCandidateUsers().size()));
task.setAssignee(randomUser);
} else if (userTask.getCandidateGroups() != null && !userTask.getCandidateGroups().isEmpty()) {
// 将任务分配给候选用户组
for (String candidateGroup : userTask.getCandidateGroups()) {
task.addCandidateGroup(candidateGroup);
}
}
}
}表单集成
public class FormIntegrationManager {
public FormData getTaskFormData(String taskId) {
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new TaskException("任务不存在: " + taskId);
}
// 获取表单键
String formKey = task.getFormKey();
if (formKey == null) {
return null;
}
// 根据表单键获取表单定义
FormService formService = processEngine.getFormService();
return formService.getTaskFormData(taskId);
}
public void submitTaskForm(String taskId, Map<String, Object> properties) {
TaskService taskService = processEngine.getTaskService();
// 验证表单数据
validateFormData(taskId, properties);
// 提交表单
FormService formService = processEngine.getFormService();
formService.submitTaskFormData(taskId, properties);
}
private void validateFormData(String taskId, Map<String, Object> properties) {
// 获取任务表单定义
FormData formData = getTaskFormData(taskId);
if (formData == null) {
return;
}
// 验证必填字段
for (FormField field : formData.getFields()) {
if (field.isRequired() &&
(properties.get(field.getId()) == null ||
properties.get(field.getId()).toString().isEmpty())) {
throw new FormValidationException("必填字段不能为空: " + field.getId());
}
}
}
}服务任务(Service Task)
服务任务是自动执行的系统任务:
实现方式
Java服务任务
public class JavaServiceTask implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
// 获取流程变量
String businessKey = execution.getProcessBusinessKey();
Map<String, Object> variables = execution.getVariables();
// 执行业务逻辑
try {
performBusinessLogic(execution, variables);
// 设置输出变量
execution.setVariable("serviceResult", "SUCCESS");
execution.setVariable("serviceOutput", generateOutput(variables));
} catch (Exception e) {
// 处理异常
execution.setVariable("serviceResult", "ERROR");
execution.setVariable("errorMessage", e.getMessage());
// 根据配置决定是否抛出异常
if (shouldThrowException(execution)) {
throw new BpmnError("SERVICE_TASK_ERROR", e.getMessage());
}
}
}
private void performBusinessLogic(DelegateExecution execution,
Map<String, Object> variables) {
// 实际的业务逻辑实现
// 例如:调用外部服务、处理数据、发送消息等
String serviceName = (String) execution.getVariable("serviceName");
ServiceInvoker serviceInvoker = ServiceRegistry.getServiceInvoker(serviceName);
serviceInvoker.invoke(variables);
}
private Object generateOutput(Map<String, Object> inputVariables) {
// 根据输入变量生成输出结果
// 这里可以是复杂的数据处理逻辑
return "Processed result based on " + inputVariables.size() + " input variables";
}
private boolean shouldThrowException(DelegateExecution execution) {
// 根据配置决定是否抛出异常
return Boolean.TRUE.equals(execution.getVariable("throwExceptionOnFailure"));
}
}表达式服务任务
public class ExpressionServiceTask {
public void executeExpression(DelegateExecution execution) {
// 获取表达式
String expressionString = (String) execution.getVariable("expression");
if (expressionString == null || expressionString.isEmpty()) {
throw new ProcessEngineException("表达式不能为空");
}
// 解析和执行表达式
ExpressionManager expressionManager = processEngine.getProcessEngineConfiguration()
.getExpressionManager();
Expression expression = expressionManager.createExpression(expressionString);
Object result = expression.getValue(execution);
// 设置结果变量
String resultVariable = (String) execution.getVariable("resultVariable");
if (resultVariable != null) {
execution.setVariable(resultVariable, result);
}
}
}外部服务任务
public class ExternalServiceTask implements ExternalTaskHandler {
@Override
public void execute(ExternalTask externalTask, ExternalTaskService externalTaskService) {
try {
// 获取外部任务参数
String topicName = externalTask.getTopicName();
Map<String, Object> variables = externalTask.getAllVariables();
// 调用外部服务
ExternalServiceClient client = ExternalServiceRegistry.getClient(topicName);
ExternalServiceResponse response = client.invoke(variables);
// 完成外部任务
Map<String, Object> resultVariables = new HashMap<>();
resultVariables.put("externalServiceResult", response.getResult());
resultVariables.put("externalServiceStatus", response.getStatus());
externalTaskService.complete(externalTask.getId(), resultVariables);
} catch (Exception e) {
// 处理失败情况
externalTaskService.handleFailure(externalTask.getId(),
"External service call failed",
e.getMessage(),
0, 0);
}
}
}脚本任务(Script Task)
脚本任务允许在流程中执行脚本代码:
脚本引擎集成
public class ScriptTaskExecutor {
public void executeScript(DelegateExecution execution) {
// 获取脚本相关信息
String scriptFormat = (String) execution.getVariable("scriptFormat");
String scriptText = (String) execution.getVariable("script");
if (scriptFormat == null || scriptText == null) {
throw new ProcessEngineException("脚本格式或内容不能为空");
}
// 获取脚本引擎
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(scriptFormat);
if (scriptEngine == null) {
throw new ProcessEngineException("不支持的脚本格式: " + scriptFormat);
}
// 设置脚本上下文
ScriptContext scriptContext = new SimpleScriptContext();
Bindings bindings = scriptEngine.createBindings();
// 将流程变量添加到脚本上下文
Map<String, Object> variables = execution.getVariables();
bindings.putAll(variables);
bindings.put("execution", execution);
scriptContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
try {
// 执行脚本
Object result = scriptEngine.eval(scriptText, scriptContext);
// 将脚本执行结果设置为流程变量
execution.setVariable("scriptResult", result);
// 获取脚本中设置的变量
for (Map.Entry<String, Object> entry : bindings.entrySet()) {
if (!variables.containsKey(entry.getKey())) {
// 新增的变量
execution.setVariable(entry.getKey(), entry.getValue());
} else if (!Objects.equals(variables.get(entry.getKey()), entry.getValue())) {
// 修改的变量
execution.setVariable(entry.getKey(), entry.getValue());
}
}
} catch (ScriptException e) {
throw new ProcessEngineException("脚本执行失败", e);
}
}
}安全脚本执行
public class SecureScriptTaskExecutor {
private static final Set<String> BLACKLISTED_CLASSES = new HashSet<>(Arrays.asList(
"java.lang.System",
"java.lang.Runtime",
"java.lang.ProcessBuilder"
));
public void executeSecureScript(DelegateExecution execution) {
String scriptFormat = (String) execution.getVariable("scriptFormat");
String scriptText = (String) execution.getVariable("script");
// 安全检查
if (!isScriptSafe(scriptText)) {
throw new SecurityException("脚本包含不安全的代码");
}
// 创建安全的脚本引擎
ScriptEngine scriptEngine = createSecureScriptEngine(scriptFormat);
// 执行脚本
executeScriptWithEngine(scriptEngine, scriptText, execution);
}
private boolean isScriptSafe(String scriptText) {
// 检查脚本是否包含黑名单类
for (String blacklistedClass : BLACKLISTED_CLASSES) {
if (scriptText.contains(blacklistedClass)) {
return false;
}
}
// 检查其他潜在的安全问题
// 例如:文件操作、网络访问等
return true;
}
private ScriptEngine createSecureScriptEngine(String scriptFormat) {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(scriptFormat);
if (scriptEngine instanceof Compilable) {
// 对于可编译的脚本引擎,可以进行额外的安全检查
// 例如:使用安全管理器限制脚本权限
}
return scriptEngine;
}
}人工任务(Manual Task)
人工任务表示需要人工完成但不涉及系统交互的任务:
任务管理
public class ManualTaskManager {
public void completeManualTask(String taskId, String userId) {
TaskService taskService = processEngine.getTaskService();
// 验证任务存在性
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new TaskException("任务不存在: " + taskId);
}
// 验证任务类型
if (!"manual".equals(task.getTaskDefinitionKey())) {
throw new TaskException("任务类型不匹配: " + taskId);
}
// 验证用户权限
if (!canCompleteManualTask(userId, taskId)) {
throw new SecurityException("用户无权完成任务: " + taskId);
}
// 完成任务
taskService.complete(taskId);
// 记录操作日志
auditLog("MANUAL_TASK_COMPLETE", taskId, userId, "人工任务已完成");
}
private boolean canCompleteManualTask(String userId, String taskId) {
// 检查用户是否为流程实例的参与者
Task task = processEngine.getTaskService().createTaskQuery().taskId(taskId).singleResult();
String processInstanceId = task.getProcessInstanceId();
// 检查用户是否参与了该流程实例
return isUserInvolvedInProcess(userId, processInstanceId);
}
private boolean isUserInvolvedInProcess(String userId, String processInstanceId) {
// 查询用户是否参与了该流程实例
// 可以检查启动用户、任务处理者等
HistoricProcessInstance processInstance = processEngine.getHistoryService()
.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId)
.startedBy(userId)
.singleResult();
return processInstance != null;
}
}任务生命周期管理
任务状态管理
public enum TaskState {
CREATED("created"), // 已创建
ASSIGNED("assigned"), // 已分配
SUSPENDED("suspended"), // 已暂停
COMPLETED("completed"), // 已完成
DELEGATED("delegated"), // 已委派
ERROR("error"); // 错误状态
private String state;
TaskState(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
public class TaskLifecycleManager {
public void transitionTaskState(String taskId, TaskState fromState, TaskState toState) {
// 验证状态转换的合法性
if (!isValidTransition(fromState, toState)) {
throw new TaskException("非法的任务状态转换: " + fromState + " -> " + toState);
}
// 执行状态转换
updateTaskState(taskId, toState);
// 触发状态转换事件
fireEvent(new TaskStateTransitionEvent(taskId, fromState, toState));
}
private boolean isValidTransition(TaskState fromState, TaskState toState) {
// 定义合法的状态转换
switch (fromState) {
case CREATED:
return toState == ASSIGNED || toState == SUSPENDED || toState == COMPLETED;
case ASSIGNED:
return toState == COMPLETED || toState == DELEGATED || toState == SUSPENDED;
case SUSPENDED:
return toState == ASSIGNED || toState == COMPLETED;
case DELEGATED:
return toState == ASSIGNED || toState == COMPLETED;
default:
return false;
}
}
private void updateTaskState(String taskId, TaskState state) {
TaskEntityManager entityManager = Context.getCommandContext().getTaskEntityManager();
TaskEntity task = entityManager.findById(taskId);
if (task != null) {
task.setState(state.getState());
}
}
}任务创建与初始化
public class TaskCreationManager {
public TaskEntity createTask(ExecutionEntity execution, ActivityImpl activity) {
TaskEntity task = new TaskEntity();
// 设置基本属性
task.setId(IdGenerator.getNextId());
task.setName(activity.getName());
task.setDescription(activity.getDescription());
task.setPriority(activity.getPriority());
task.setCreateTime(new Date());
task.setProcessInstanceId(execution.getProcessInstanceId());
task.setExecutionId(execution.getId());
task.setProcessDefinitionId(execution.getProcessDefinitionId());
task.setTaskDefinitionKey(activity.getId());
// 设置租户信息
if (execution.getTenantId() != null) {
task.setTenantId(execution.getTenantId());
}
// 初始化任务状态
task.setState(TaskState.CREATED.getState());
// 应用任务分配策略
applyAssignmentStrategy(task, activity);
// 设置到期时间
setDueDate(task, activity);
// 设置表单信息
setFormKey(task, activity);
// 持久化任务
Context.getCommandContext().getTaskEntityManager().insert(task);
// 触发任务创建事件
fireEvent(new TaskCreatedEvent(task));
return task;
}
private void applyAssignmentStrategy(TaskEntity task, ActivityImpl activity) {
// 获取任务定义中的分配信息
UserTask userTask = (UserTask) activity.getActivityBehavior();
// 应用分配策略
AssignmentStrategy strategy = AssignmentStrategyFactory.getStrategy(userTask);
strategy.assignTask(task, userTask);
}
private void setDueDate(TaskEntity task, ActivityImpl activity) {
// 获取到期时间表达式
String dueDateExpression = activity.getProperty("dueDate");
if (dueDateExpression != null) {
// 解析表达式并设置到期时间
Date dueDate = parseDueDateExpression(dueDateExpression, task.getExecution());
task.setDueDate(dueDate);
}
}
private Date parseDueDateExpression(String expression, ExecutionEntity execution) {
// 使用表达式引擎解析到期时间
ExpressionManager expressionManager = processEngine.getProcessEngineConfiguration()
.getExpressionManager();
Expression expr = expressionManager.createExpression(expression);
Object result = expr.getValue(execution);
if (result instanceof Date) {
return (Date) result;
} else if (result instanceof String) {
// 解析日期字符串
return parseDateString((String) result);
}
return null;
}
}任务完成与清理
public class TaskCompletionManager {
public void completeTask(String taskId, Map<String, Object> variables) {
TaskService taskService = processEngine.getTaskService();
// 验证任务存在性
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new TaskException("任务不存在: " + taskId);
}
// 验证任务状态
if (!TaskState.ASSIGNED.getState().equals(task.getState())) {
throw new TaskException("任务状态不正确,无法完成: " + taskId);
}
// 执行任务完成前的验证
if (!validateTaskCompletion(taskId, variables)) {
throw new TaskException("任务完成验证失败: " + taskId);
}
// 完成任务
if (variables != null && !variables.isEmpty()) {
taskService.complete(taskId, variables);
} else {
taskService.complete(taskId);
}
// 执行任务完成后的清理工作
cleanupTask(taskId);
// 记录操作日志
auditLog("TASK_COMPLETE", taskId, getCurrentUserId(), "任务已完成");
}
private boolean validateTaskCompletion(String taskId, Map<String, Object> variables) {
// 获取任务定义
Task task = processEngine.getTaskService().createTaskQuery().taskId(taskId).singleResult();
String processDefinitionId = task.getProcessDefinitionId();
String taskDefinitionKey = task.getTaskDefinitionKey();
// 获取任务验证规则
TaskValidationRule validationRule = getTaskValidationRule(processDefinitionId, taskDefinitionKey);
if (validationRule != null) {
return validationRule.validate(variables);
}
// 默认验证通过
return true;
}
private void cleanupTask(String taskId) {
// 清理与任务相关的临时数据
// 例如:删除临时文件、清理缓存等
// 更新相关统计数据
updateTaskStatistics(taskId);
// 触发任务完成事件
fireEvent(new TaskCompletedEvent(taskId));
}
private void updateTaskStatistics(String taskId) {
// 更新任务统计信息
// 例如:平均处理时间、完成率等
TaskStatisticsManager statisticsManager = new TaskStatisticsManager();
statisticsManager.updateTaskCompletionStats(taskId);
}
}任务分配与路由
复杂分配策略
public class AdvancedAssignmentStrategy implements AssignmentStrategy {
@Override
public void assignTask(TaskEntity task, UserTask userTask) {
// 获取分配策略类型
String assignmentType = userTask.getAttribute("assignmentType");
switch (assignmentType) {
case "roundRobin":
assignByRoundRobin(task, userTask);
break;
case "loadBalanced":
assignByLoadBalance(task, userTask);
break;
case "skillBased":
assignBySkills(task, userTask);
break;
case "custom":
assignByCustomRule(task, userTask);
break;
default:
assignByDefault(task, userTask);
}
}
private void assignByRoundRobin(TaskEntity task, UserTask userTask) {
// 轮询分配策略
List<String> candidateUsers = userTask.getCandidateUsers();
if (candidateUsers != null && !candidateUsers.isEmpty()) {
String assignee = getNextAssignee(candidateUsers);
task.setAssignee(assignee);
}
}
private void assignByLoadBalance(TaskEntity task, UserTask userTask) {
// 负载均衡分配策略
List<String> candidateUsers = userTask.getCandidateUsers();
if (candidateUsers != null && !candidateUsers.isEmpty()) {
String assignee = getLeastLoadedUser(candidateUsers);
task.setAssignee(assignee);
}
}
private void assignBySkills(TaskEntity task, UserTask userTask) {
// 基于技能的分配策略
String requiredSkill = userTask.getAttribute("requiredSkill");
List<String> candidateUsers = userTask.getCandidateUsers();
if (requiredSkill != null && candidateUsers != null && !candidateUsers.isEmpty()) {
String assignee = findUserWithSkill(candidateUsers, requiredSkill);
task.setAssignee(assignee);
}
}
private void assignByCustomRule(TaskEntity task, UserTask userTask) {
// 自定义分配规则
String ruleName = userTask.getAttribute("assignmentRule");
AssignmentRule rule = AssignmentRuleRegistry.getRule(ruleName);
if (rule != null) {
String assignee = rule.determineAssignee(task, userTask);
task.setAssignee(assignee);
}
}
private String getNextAssignee(List<String> candidates) {
// 实现轮询逻辑
// 可以使用数据库或缓存记录上次分配的用户
return candidates.get(0); // 简化实现
}
private String getLeastLoadedUser(List<String> candidates) {
// 查询每个候选用户的当前任务负载
UserService userService = ServiceRegistry.getUserService();
return userService.findLeastLoadedUser(candidates);
}
private String findUserWithSkill(List<String> candidates, String skill) {
// 查询具有指定技能的用户
UserService userService = ServiceRegistry.getUserService();
return userService.findUserWithSkill(candidates, skill);
}
}任务路由机制
public class TaskRoutingManager {
public void routeTask(String taskId, String targetUserId) {
TaskService taskService = processEngine.getTaskService();
// 验证任务存在性
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new TaskException("任务不存在: " + taskId);
}
// 验证目标用户存在性
IdentityService identityService = processEngine.getIdentityService();
User targetUser = identityService.createUserQuery().userId(targetUserId).singleResult();
if (targetUser == null) {
throw new TaskException("目标用户不存在: " + targetUserId);
}
// 验证路由权限
if (!canRouteTask(getCurrentUserId(), taskId)) {
throw new SecurityException("用户无权路由任务: " + taskId);
}
// 执行路由操作
taskService.setAssignee(taskId, targetUserId);
// 发送通知
sendTaskRoutingNotification(taskId, targetUserId);
// 记录操作日志
auditLog("TASK_ROUTE", taskId, getCurrentUserId(),
"任务路由到用户: " + targetUserId);
}
public void routeTaskToGroup(String taskId, String targetGroupId) {
TaskService taskService = processEngine.getTaskService();
// 验证任务存在性
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
throw new TaskException("任务不存在: " + taskId);
}
// 验证目标用户组存在性
IdentityService identityService = processEngine.getIdentityService();
Group targetGroup = identityService.createGroupQuery().groupId(targetGroupId).singleResult();
if (targetGroup == null) {
throw new TaskException("目标用户组不存在: " + targetGroupId);
}
// 执行路由操作
taskService.addCandidateGroup(taskId, targetGroupId);
// 移除之前的分配(如果有的话)
if (task.getAssignee() != null) {
taskService.setAssignee(taskId, null);
}
// 发送通知
sendTaskRoutingNotificationToGroup(taskId, targetGroupId);
// 记录操作日志
auditLog("TASK_ROUTE_GROUP", taskId, getCurrentUserId(),
"任务路由到用户组: " + targetGroupId);
}
private boolean canRouteTask(String userId, String taskId) {
// 检查用户是否具有路由权限
// 可以基于角色、组织关系等进行判断
return hasRole(userId, "TASK_ROUTER") || isProcessAdministrator(userId, taskId);
}
private boolean isProcessAdministrator(String userId, String taskId) {
Task task = processEngine.getTaskService().createTaskQuery().taskId(taskId).singleResult();
String processInstanceId = task.getProcessInstanceId();
// 检查用户是否为流程实例的管理员
return isUserProcessAdmin(userId, processInstanceId);
}
}任务通知与提醒
通知机制
public class TaskNotificationManager {
public void sendTaskNotification(Task task, NotificationType type) {
// 获取任务处理者
String assignee = task.getAssignee();
if (assignee == null) {
// 如果没有指定处理者,通知候选用户
notifyCandidateUsers(task, type);
return;
}
// 获取用户通知偏好设置
UserNotificationPreference preference = getUserNotificationPreference(assignee);
// 根据偏好设置发送通知
if (preference.isEmailEnabled() && type.shouldSendEmail()) {
sendEmailNotification(assignee, task, type);
}
if (preference.isSmsEnabled() && type.shouldSendSms()) {
sendSmsNotification(assignee, task, type);
}
if (preference.isInAppEnabled() && type.shouldSendInApp()) {
sendInAppNotification(assignee, task, type);
}
}
private void notifyCandidateUsers(Task task, NotificationType type) {
TaskService taskService = processEngine.getTaskService();
// 获取候选用户
List<IdentityLink> candidates = taskService.getIdentityLinksForTask(task.getId());
for (IdentityLink candidate : candidates) {
if (IdentityLinkType.CANDIDATE.equals(candidate.getType())) {
if (candidate.getUserId() != null) {
// 通知候选用户
sendNotificationToUser(candidate.getUserId(), task, type);
} else if (candidate.getGroupId() != null) {
// 通知候选用户组的所有成员
notifyGroupMembers(candidate.getGroupId(), task, type);
}
}
}
}
private void sendEmailNotification(String userId, Task task, NotificationType type) {
User user = processEngine.getIdentityService().createUserQuery().userId(userId).singleResult();
if (user != null && user.getEmail() != null) {
EmailService emailService = ServiceRegistry.getEmailService();
EmailMessage email = buildEmailMessage(user, task, type);
emailService.send(email);
}
}
private EmailMessage buildEmailMessage(User user, Task task, NotificationType type) {
EmailMessage email = new EmailMessage();
email.setTo(user.getEmail());
email.setSubject(buildEmailSubject(task, type));
email.setContent(buildEmailContent(user, task, type));
return email;
}
private String buildEmailSubject(Task task, NotificationType type) {
switch (type) {
case TASK_ASSIGNED:
return "新任务分配: " + task.getName();
case TASK_DUE_SOON:
return "任务即将到期: " + task.getName();
case TASK_OVERDUE:
return "任务已逾期: " + task.getName();
default:
return "任务通知: " + task.getName();
}
}
private String buildEmailContent(User user, Task task, NotificationType type) {
StringBuilder content = new StringBuilder();
content.append("尊敬的 ").append(user.getFirstName()).append(",\n\n");
switch (type) {
case TASK_ASSIGNED:
content.append("您有一个新任务需要处理:\n");
content.append("任务名称: ").append(task.getName()).append("\n");
content.append("任务描述: ").append(task.getDescription()).append("\n");
content.append("创建时间: ").append(task.getCreateTime()).append("\n");
if (task.getDueDate() != null) {
content.append("到期时间: ").append(task.getDueDate()).append("\n");
}
break;
case TASK_DUE_SOON:
content.append("您有一个任务即将到期:\n");
content.append("任务名称: ").append(task.getName()).append("\n");
content.append("到期时间: ").append(task.getDueDate()).append("\n");
break;
case TASK_OVERDUE:
content.append("您有一个任务已逾期:\n");
content.append("任务名称: ").append(task.getName()).append("\n");
content.append("到期时间: ").append(task.getDueDate()).append("\n");
content.append("逾期时间: ").append(new Date()).append("\n");
break;
}
content.append("\n请尽快处理。\n\n");
content.append("此邮件由BPM系统自动发送,请勿回复。");
return content.toString();
}
}提醒机制
public class TaskReminderManager {
public void scheduleTaskReminders() {
// 查询即将到期的任务
List<Task> dueSoonTasks = findDueSoonTasks();
for (Task task : dueSoonTasks) {
sendDueSoonReminder(task);
}
// 查询已逾期的任务
List<Task> overdueTasks = findOverdueTasks();
for (Task task : overdueTasks) {
sendOverdueReminder(task);
}
}
private List<Task> findDueSoonTasks() {
Date now = new Date();
Date dueSoonThreshold = new Date(now.getTime() + 24 * 60 * 60 * 1000); // 24小时后
TaskService taskService = processEngine.getTaskService();
return taskService.createTaskQuery()
.taskDueBefore(dueSoonThreshold)
.taskDueAfter(now)
.list();
}
private List<Task> findOverdueTasks() {
TaskService taskService = processEngine.getTaskService();
return taskService.createTaskQuery()
.taskDueBefore(new Date())
.list();
}
private void sendDueSoonReminder(Task task) {
// 检查是否已经发送过提醒
if (hasSentReminder(task.getId(), "DUE_SOON")) {
return;
}
// 发送提醒通知
TaskNotificationManager notificationManager = new TaskNotificationManager();
notificationManager.sendTaskNotification(task, NotificationType.TASK_DUE_SOON);
// 记录提醒发送历史
recordReminderSent(task.getId(), "DUE_SOON");
}
private void sendOverdueReminder(Task task) {
// 检查是否已经发送过提醒
if (hasSentReminder(task.getId(), "OVERDUE")) {
return;
}
// 发送提醒通知
TaskNotificationManager notificationManager = new TaskNotificationManager();
notificationManager.sendTaskNotification(task, NotificationType.TASK_OVERDUE);
// 通知管理员
notifyAdministrators(task);
// 记录提醒发送历史
recordReminderSent(task.getId(), "OVERDUE");
}
private boolean hasSentReminder(String taskId, String reminderType) {
// 查询提醒发送历史
ReminderHistoryRepository repository = RepositoryRegistry.getReminderHistoryRepository();
return repository.hasSentReminder(taskId, reminderType);
}
private void recordReminderSent(String taskId, String reminderType) {
// 记录提醒发送历史
ReminderHistoryRepository repository = RepositoryRegistry.getReminderHistoryRepository();
ReminderHistory history = new ReminderHistory();
history.setTaskId(taskId);
history.setReminderType(reminderType);
history.setSendTime(new Date());
repository.save(history);
}
private void notifyAdministrators(Task task) {
// 获取流程管理员
List<String> administrators = getProcessAdministrators(task.getProcessInstanceId());
for (String adminId : administrators) {
sendOverdueAlertToAdmin(adminId, task);
}
}
}任务监控与统计
实时监控
public class TaskMonitoringService {
public TaskStatistics getTaskStatistics(String processDefinitionId) {
TaskStatistics statistics = new TaskStatistics();
// 查询任务总数
long totalTasks = processEngine.getTaskService().createTaskQuery()
.processDefinitionId(processDefinitionId)
.count();
statistics.setTotalTasks(totalTasks);
// 查询待处理任务数
long pendingTasks = processEngine.getTaskService().createTaskQuery()
.processDefinitionId(processDefinitionId)
.taskAssigneeNotNull()
.count();
statistics.setPendingTasks(pendingTasks);
// 查询未分配任务数
long unassignedTasks = processEngine.getTaskService().createTaskQuery()
.processDefinitionId(processDefinitionId)
.taskAssigneeNull()
.count();
statistics.setUnassignedTasks(unassignedTasks);
// 查询逾期任务数
long overdueTasks = processEngine.getTaskService().createTaskQuery()
.processDefinitionId(processDefinitionId)
.taskDueBefore(new Date())
.count();
statistics.setOverdueTasks(overdueTasks);
// 计算平均处理时间
double avgProcessingTime = calculateAverageProcessingTime(processDefinitionId);
statistics.setAverageProcessingTime(avgProcessingTime);
return statistics;
}
private double calculateAverageProcessingTime(String processDefinitionId) {
// 查询已完成任务的处理时间
List<HistoricTaskInstance> completedTasks = processEngine.getHistoryService()
.createHistoricTaskInstanceQuery()
.processDefinitionId(processDefinitionId)
.finished()
.list();
if (completedTasks.isEmpty()) {
return 0.0;
}
long totalTime = 0;
for (HistoricTaskInstance task : completedTasks) {
long duration = task.getEndTime().getTime() - task.getStartTime().getTime();
totalTime += duration;
}
return (double) totalTime / completedTasks.size();
}
public List<Task> getOverdueTasks(String processDefinitionId, int limit) {
return processEngine.getTaskService().createTaskQuery()
.processDefinitionId(processDefinitionId)
.taskDueBefore(new Date())
.orderByTaskDueDate()
.asc()
.listPage(0, limit);
}
public Map<String, Long> getTaskDistributionByUser(String processDefinitionId) {
Map<String, Long> distribution = new HashMap<>();
// 查询所有任务并按用户分组统计
List<Task> tasks = processEngine.getTaskService().createTaskQuery()
.processDefinitionId(processDefinitionId)
.list();
for (Task task : tasks) {
String assignee = task.getAssignee();
if (assignee != null) {
distribution.put(assignee, distribution.getOrDefault(assignee, 0L) + 1);
}
}
return distribution;
}
}性能统计
public class TaskPerformanceStatistics {
public TaskPerformanceReport generatePerformanceReport(String processDefinitionId,
Date startTime,
Date endTime) {
TaskPerformanceReport report = new TaskPerformanceReport();
// 获取任务执行数据
List<HistoricTaskInstance> tasks = processEngine.getHistoryService()
.createHistoricTaskInstanceQuery()
.processDefinitionId(processDefinitionId)
.taskCompletedAfter(startTime)
.taskCompletedBefore(endTime)
.list();
// 计算各项性能指标
report.setTotalCompletedTasks(tasks.size());
report.setAverageCompletionTime(calculateAverageCompletionTime(tasks));
report.setCompletionRate(calculateCompletionRate(tasks, startTime, endTime));
report.setOverdueRate(calculateOverdueRate(tasks));
// 按用户统计
report.setUserPerformanceStats(calculateUserPerformanceStats(tasks));
// 按任务类型统计
report.setTaskTypeStats(calculateTaskTypeStats(tasks));
return report;
}
private long calculateAverageCompletionTime(List<HistoricTaskInstance> tasks) {
if (tasks.isEmpty()) {
return 0;
}
long totalTime = 0;
for (HistoricTaskInstance task : tasks) {
if (task.getStartTime() != null && task.getEndTime() != null) {
totalTime += task.getEndTime().getTime() - task.getStartTime().getTime();
}
}
return totalTime / tasks.size();
}
private double calculateCompletionRate(List<HistoricTaskInstance> tasks,
Date startTime,
Date endTime) {
// 计算理论应完成任务数
long theoreticalTasks = calculateTheoreticalTaskCount(startTime, endTime);
if (theoreticalTasks == 0) {
return 0.0;
}
return (double) tasks.size() / theoreticalTasks * 100;
}
private double calculateOverdueRate(List<HistoricTaskInstance> tasks) {
if (tasks.isEmpty()) {
return 0.0;
}
long overdueCount = tasks.stream()
.filter(task -> task.getDueDate() != null &&
task.getEndTime().after(task.getDueDate()))
.count();
return (double) overdueCount / tasks.size() * 100;
}
private Map<String, UserPerformanceStats> calculateUserPerformanceStats(
List<HistoricTaskInstance> tasks) {
Map<String, UserPerformanceStats> stats = new HashMap<>();
for (HistoricTaskInstance task : tasks) {
String assignee = task.getAssignee();
if (assignee == null) continue;
UserPerformanceStats userStats = stats.computeIfAbsent(assignee,
k -> new UserPerformanceStats(assignee));
userStats.incrementCompletedTasks();
if (task.getStartTime() != null && task.getEndTime() != null) {
long duration = task.getEndTime().getTime() - task.getStartTime().getTime();
userStats.addTotalProcessingTime(duration);
}
if (task.getDueDate() != null && task.getEndTime().after(task.getDueDate())) {
userStats.incrementOverdueTasks();
}
}
// 计算平均处理时间
stats.values().forEach(UserPerformanceStats::calculateAverageProcessingTime);
return stats;
}
}案例分析
案例一:某制造企业的生产任务管理
某制造企业在生产管理中实现了复杂的任务管理体系:
业务场景
- 多类型任务:包括质检任务、设备维护任务、生产调度任务等
- 动态分配:根据生产线状态和人员技能动态分配任务
- 实时监控:实时监控所有生产任务的执行状态
- 异常处理:自动处理任务执行中的异常情况
技术实现
public class ProductionTaskManager {
public void createProductionTask(ProductionOrder order) {
// 创建质检任务
createQualityInspectionTask(order);
// 创建生产任务
createProductionExecutionTask(order);
// 创建设备维护任务
createEquipmentMaintenanceTask(order);
}
private void createQualityInspectionTask(ProductionOrder order) {
TaskService taskService = processEngine.getTaskService();
Task task = taskService.newTask();
task.setName("产品质量检验");
task.setDescription("对生产订单 " + order.getOrderNumber() + " 的产品进行质量检验");
task.setPriority(50);
task.setCategory("QUALITY_INSPECTION");
// 动态分配质检员
String assignee = assignQualityInspector(order);
task.setAssignee(assignee);
// 设置到期时间
task.setDueDate(calculateInspectionDueDate(order));
taskService.saveTask(task);
// 关联生产订单
linkTaskToOrder(task.getId(), order.getId());
// 发送通知
sendTaskNotification(task, NotificationType.TASK_ASSIGNED);
}
private String assignQualityInspector(ProductionOrder order) {
// 根据产品类型和质检员技能进行分配
QualityInspectorService inspectorService = ServiceRegistry.getQualityInspectorService();
return inspectorService.findSuitableInspector(order.getProductType());
}
private Date calculateInspectionDueDate(ProductionOrder order) {
// 根据生产计划计算质检到期时间
Calendar calendar = Calendar.getInstance();
calendar.setTime(order.getPlannedCompletionTime());
calendar.add(Calendar.HOUR, -2); // 提前2小时完成质检
return calendar.getTime();
}
public void handleProductionException(String taskId, Exception exception) {
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) {
return;
}
// 记录异常信息
taskService.setVariable(taskId, "exceptionMessage", exception.getMessage());
taskService.setVariable(taskId, "exceptionTime", new Date());
// 创建异常处理任务
createExceptionHandlingTask(task, exception);
// 通知相关人员
notifyProductionManager(task, exception);
}
}实施效果
- 生产任务处理效率提升35%
- 质检任务分配准确率提升至98%
- 异常处理时间缩短60%
- 生产计划达成率提升至95%
案例二:某金融机构的合规任务管理
某金融机构在合规管理中实现了严格的任务控制机制:
合规要求
- 权限控制:严格的任务访问和处理权限控制
- 审计追踪:完整记录所有任务操作历史
- 时间控制:严格的任务处理时间要求
- 质量保证:确保任务处理的准确性和合规性
技术方案
public class ComplianceTaskManager {
public void createComplianceTask(ComplianceCheck check) {
TaskService taskService = processEngine.getTaskService();
Task task = taskService.newTask();
task.setName("合规检查任务");
task.setDescription("执行合规检查: " + check.getCheckType());
task.setPriority(100); // 高优先级
task.setCategory("COMPLIANCE");
// 基于角色分配任务
String assignee = assignByComplianceRole(check);
task.setAssignee(assignee);
// 设置严格的到期时间
task.setDueDate(check.getDeadline());
taskService.saveTask(task);
// 设置合规检查点
setComplianceCheckpoints(task.getId(), check.getCheckpoints());
// 记录任务创建审计日志
auditLog("COMPLIANCE_TASK_CREATED", task.getId(), assignee,
"合规任务已创建: " + check.getCheckType());
}
private String assignByComplianceRole(ComplianceCheck check) {
// 根据合规检查类型和检查员资质进行分配
ComplianceOfficerService officerService = ServiceRegistry.getComplianceOfficerService();
return officerService.findQualifiedOfficer(check.getCheckType(), check.getRiskLevel());
}
public void completeComplianceTask(String taskId, Map<String, Object> results) {
// 验证任务处理者权限
if (!isAuthorizedComplianceOfficer(getCurrentUserId(), taskId)) {
throw new SecurityException("用户无权处理合规任务: " + taskId);
}
// 验证合规检查点完成情况
if (!validateComplianceCheckpoints(taskId, results)) {
throw new ComplianceException("合规检查点未全部完成");
}
// 验证处理结果的合规性
if (!validateComplianceResults(results)) {
throw new ComplianceException("处理结果不符合合规要求");
}
// 完成任务
TaskService taskService = processEngine.getTaskService();
taskService.complete(taskId, results);
// 触发合规报告生成
triggerComplianceReportGeneration(taskId, results);
// 记录任务完成审计日志
auditLog("COMPLIANCE_TASK_COMPLETED", taskId, getCurrentUserId(),
"合规任务已完成");
}
private boolean validateComplianceCheckpoints(String taskId, Map<String, Object> results) {
// 获取任务的合规检查点
List<ComplianceCheckpoint> checkpoints = getComplianceCheckpoints(taskId);
// 验证每个检查点是否已完成
for (ComplianceCheckpoint checkpoint : checkpoints) {
Object result = results.get("checkpoint_" + checkpoint.getId());
if (result == null || !checkpoint.isCompleted(result)) {
return false;
}
}
return true;
}
private boolean validateComplianceResults(Map<String, Object> results) {
// 应用合规规则验证处理结果
ComplianceRuleEngine ruleEngine = ServiceRegistry.getComplianceRuleEngine();
return ruleEngine.validate(results);
}
}业务效果
- 合规检查任务处理准确率提升至99.9%
- 合规审计通过率达到100%
- 合规风险事件减少80%
- 监管检查满意度提升40%
未来发展趋势
智能任务管理
AI技术正在改变任务管理的方式:
- 智能分配:基于机器学习自动分配最合适的处理者
- 预测性提醒:预测任务完成时间并提前提醒
- 自适应优化:根据历史数据自动优化任务管理策略
- 异常检测:智能检测任务执行异常并自动处理
无服务器化任务处理
Serverless架构为任务处理带来新的可能性:
- 事件驱动:基于事件触发任务处理
- 按需执行:只在需要时执行任务处理逻辑
- 自动扩缩容:根据负载自动调整处理能力
- 成本优化:只为实际使用的任务处理付费
边缘计算任务管理
边缘计算为任务管理提供分布式能力:
- 就近处理:在用户附近执行任务处理
- 断网处理:支持断网情况下的本地任务处理
- 数据同步:实现边缘和中心的任务状态同步
- 分布式管理:支持分布式的任务管理
结语
任务管理是企业级BPM平台的核心功能,它为业务流程的协调执行提供了强有力的技术支撑。通过深入理解用户任务、服务任务、脚本任务和人工任务等不同类型任务的特点,以及任务生命周期管理、分配路由、通知提醒、监控统计等关键技术,我们可以构建出功能完善、性能优越、安全可靠的任务管理系统。
在实际实施过程中,我们需要根据具体的业务需求和技术条件,选择合适的技术方案和实现策略,并持续优化和完善系统设计。同时,也要关注技术发展趋势,积极拥抱AI、Serverless、边缘计算等新技术,为企业的业务流程管理提供更加强大和灵活的技术支撑。
