需求分析
- 发送邮件或消息需要的参数为:接收用户、邮件或消息内容
- 如何将发送任务设计成通用功能
- 如何处理不同流程的接收用户参数 和 发送内容参数名称不同的问题
需求设计
配置外部任务客户端
我们需要使用外部任务来处理发送任务,这里我们修改Camunda配置文件,添加一个外部任务处理的客户端,如下:
@Configuration
public class CamundaExternalTaskClientConfig {
@Bean
public ExternalTaskClient externalTaskClient() {
return ExternalTaskClient.create()
.baseUrl("http://localhost:9603/engine-rest")
.asyncResponseTimeout(10000)
.build();
}
}
添加外部任务主题服务
这里,我们将添加一些任务处理功能的主题,给外部任务客户端;
2.1 SendTaskService
@Service
public class SendTaskService {
protected final org.apache.commons.logging.Log logger = LogFactory.getLog(this.getClass());
@Autowired
private ExternalTaskClient externalTaskClient;
@PostConstruct
public void subscribeToExternalTask() {
// 发送邮件任务 topic
externalTaskClient.subscribe("send_email")
.handler((externalTask, externalTaskService) -> {
String receiver = (String) externalTask.getVariable("receiver");
String content = (String) externalTask.getVariable("content");
// 调用系统发送邮箱接口
logger.info("====发送给【"+receiver+"】,发送内容【"+ content +"】");
// 完成外部任务处理
Map<String, Object> variables = new HashMap<>();
String mesid= "Message_"+HttpRequestUtils.getRandomString(10);
variables.put("mesid", mesid);
externalTaskService.complete(externalTask, variables);
// logger.info("====mesid===="+mesid);
// 处理外部任务逻辑----end
})
.open();
// 发送消息任务 topic
externalTaskClient.subscribe("send_message")
.handler((externalTask, externalTaskService) -> {
String receiver = (String) externalTask.getVariable("receiver");
String content = (String) externalTask.getVariable("content");
// 调用系统发送消息接口
logger.info("====发送给【"+receiver+"】,发送内容【"+ content +"】");
// 完成外部任务处理
Map<String, Object> variables = new HashMap<>();
String mesid= "Message_"+HttpRequestUtils.getRandomString(10);
variables.put("mesid", mesid);
externalTaskService.complete(externalTask, variables);
// logger.info("====mesid===="+mesid);
// 处理外部任务逻辑----end
})
.open();
}
}
添加执行监听类
3.1 SendTaskStartListener
SendTaskStartListener ,是用来向流程实例的variables中,添加外部发送任务时需要的参数(*receiver*: 接收用户ID、*content*: 邮件消息内容);
因为不同的业务流程,提供的参数名称可能不一样,所有需要这个类来实现注入到相同的参数名称
这里我们需要继承JavaDelegate ,并实现execute方法功能代码;
我们还需求定义两个属性字段: *receiver、content*
(由于每次触发监听委托都会创建一个单独的类实例,因此每次都会重新进行注入字段操作,当字段值被代码更改时,这些值将在下次执行活动时重新注入。
出于同样的原因,字段注入通常不应该与Spring Bean一起使用,因为Spring Bean默认情况下是单例的。由于监听任务并发执行时Bean字段的并发修改,可能会遇到不一致的情况。)
//@Component("sendTaskStartListener")
public class SendTaskStartListener implements JavaDelegate {
private final Logger LOGGER = Logger.getLogger(SendTaskStartListener.class.getName());
// 发送内容
private Expression content;
// 接收人ID
private Expression receiver;
@Override
public void execute(DelegateExecution execution) throws Exception {
// 取出注入的字段值,放进 variables中
String contentValue = (String) content.getValue(execution);
String receiverValue = (String) receiver.getValue(execution);
String msg = "";
if (receiverValue == null || receiverValue.equals("")) {
msg = "没有获取到接收人信息";
}
if (contentValue == null || contentValue.equals("")) {
msg = msg == "" ? "没有获取到发送的内容" : "和要发送的内容";
}
if (!msg.equals("")){
execution.setVariable("Exception", msg + ",系统将无法发送");
}
execution.setVariable("receiver", receiverValue);
execution.setVariable("content", contentValue);
}
}
流程图设计
业务经理审批
设置任务处理用户变量为: ${assignee1}
包容网关
分支线路设置:
- 1-审批同意,流程条件表达式设置为: ${checkResult == 1}
- 2-审批同意,流程条件表达式设置为: ${checkResult == 1}
- 3-审批拒绝,流程条件表达式设置为: ${checkResult == -1}
发送邮件通知[总经理]
任务配置
执行监听配置
java class : sy.xmsaas.workflow.listen.SendTaskStartListener
注入字段:
-
receiver:接收人
-
- type: 表达式
- value: ${assignee2}
-
content:发送内容
-
- type: 表达式
- value: 订单${sb_order_no} 业务经理审批通过
总经理审批
设置任务处理用户变量为: ${assignee2}
5.发送消息通知[发起人]
任务配置
监听器配置
java class : sy.xmsaas.workflow.listen.SendTaskStartListener
注入字段:
-
receiver:接收人
-
- type: 表达式
- value: ${starter}
-
content:发送内容
-
- type: 表达式
- value: 订单 ${sb_order_no} 总经理审批 ${checkResult == 1 ? “通过” : “不通过”}