Camunda如何发送邮件及委托代码讲解

💖专栏简介

✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。

✔️文章中只包含演示核心代码及测试数据,完整代码可查看作者的开源项目snail-camunda

✔️请给snail-camunda 点颗星吧😘

💖什么是委托代码

委托代码是在流程执行过程中发生某些事件时执行外部Java代码、脚本或求值表达式。在Camunda中分为如下4种:

  • Java Delegate 【Java委托】
  • Delegate Variable Mapping 【委托变量映射】
  • Execution Listener 【执行监听器】
  • Task Listener 【任务监听器】

💖Java Delegate

要实现一个可以在流程执行期间调用的类,该类需要实现org.camunda.bpm.engine.delegate.JavaDelegate 接口,并在execute方法中提供所需的逻辑。当流程执行到达这个特定步骤时,它将执行在该方法中定义的逻辑,并以默认的BPMN 2.0方式离开活动。

接下来通过Send Task发送邮件来演示:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_19cqxxj" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.19.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.15.0">
  <bpmn:process id="Process_0cu2yds" isExecutable="true">
    <bpmn:startEvent id="StartEvent_1">
      <bpmn:outgoing>Flow_0yf2ndo</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:sequenceFlow id="Flow_0yf2ndo" sourceRef="StartEvent_1" targetRef="Activity_1jxjk7q" />
    <bpmn:userTask id="Activity_1jxjk7q" name="发起人" camunda:assignee="${initiator}">
      <bpmn:incoming>Flow_0yf2ndo</bpmn:incoming>
      <bpmn:outgoing>Flow_0ti4nj0</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:sequenceFlow id="Flow_0ti4nj0" sourceRef="Activity_1jxjk7q" targetRef="Activity_0g9hruk" />
    <bpmn:sendTask id="Activity_0g9hruk" name="戴宗报信" camunda:class="com.lonewalker.snail.delegate.SendEmailDelegate">
      <bpmn:incoming>Flow_0ti4nj0</bpmn:incoming>
      <bpmn:outgoing>Flow_0mub7f0</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:sequenceFlow id="Flow_0mub7f0" sourceRef="Activity_0g9hruk" targetRef="Activity_111hike" />
    <bpmn:userTask id="Activity_111hike" name="宋江" camunda:assignee="${head}">
      <bpmn:incoming>Flow_0mub7f0</bpmn:incoming>
      <bpmn:outgoing>Flow_1kv7i02</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:endEvent id="Event_037pynp">
      <bpmn:incoming>Flow_1kv7i02</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="Flow_1kv7i02" sourceRef="Activity_111hike" targetRef="Event_037pynp" />
  </bpmn:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0cu2yds">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="179" y="99" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_0mqjfh8_di" bpmnElement="Activity_1jxjk7q">
        <dc:Bounds x="270" y="77" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_1tg1kpv_di" bpmnElement="Activity_0g9hruk">
        <dc:Bounds x="430" y="77" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_1mr4xv3_di" bpmnElement="Activity_111hike">
        <dc:Bounds x="590" y="77" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_037pynp_di" bpmnElement="Event_037pynp">
        <dc:Bounds x="752" y="99" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Flow_0yf2ndo_di" bpmnElement="Flow_0yf2ndo">
        <di:waypoint x="215" y="117" />
        <di:waypoint x="270" y="117" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0ti4nj0_di" bpmnElement="Flow_0ti4nj0">
        <di:waypoint x="370" y="117" />
        <di:waypoint x="430" y="117" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_0mub7f0_di" bpmnElement="Flow_0mub7f0">
        <di:waypoint x="530" y="117" />
        <di:waypoint x="590" y="117" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1kv7i02_di" bpmnElement="Flow_1kv7i02">
        <di:waypoint x="690" y="117" />
        <di:waypoint x="752" y="117" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

还是一样的将类路径替换为自己的。

此外,通过field injection【字段注入】设置目标邮箱,字段注入的Name建议使用驼峰命名,因为我们在代码中需要使用。

关于邮箱的设置可查看此篇【Springboot发送邮件

在配置文件中新增邮件相关配置

###邮件相关配置
#邮箱服务器地址
spring.mail.host=smtp.163.com
#邮箱用户名
spring.mail.username=xxx@163.com
#邮箱密码(注意:qq邮箱应该使用独立密码,去qq邮箱设置里面获取 163邮箱使用设置的授权码)
#这里把授权码改为自己的
spring.mail.password=QJBFXYUNMQYRCGSU
##编码格式
spring.mail.default-encoding=UTF-8
##端口号   465或者994
spring.mail.port=465
spring.mail.protocol=smtps
##发送邮件地址
spring.mail.from=xxx@163.com

新增发送邮件的委托代码

@RequiredArgsConstructor
@Slf4j
@Component
public class SendEmailDelegate implements JavaDelegate {

    private final JavaMailSender mailSender;

    @Value("${spring.mail.from}")
    private String addresser;

    private Expression sendingTarget;

    @Override
    public void execute(DelegateExecution execution) throws Exception {
        String initiator = (String) execution.getVariable("initiator");
        String processInstanceId = execution.getProcessInstanceId();
        String content = initiator+"--发起的审批流程抄送给您["+processInstanceId+"]";

        //获取收件人,也可以在表单设计时存入数据库
        String recipient = String.valueOf(sendingTarget.getValue(execution));
        //改成自己的邮箱账号调试
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        //设置发件人
        mailMessage.setFrom(addresser);
        //设置收件人
        mailMessage.setTo(recipient);
        //设置主题
        mailMessage.setSubject("审批抄送");
        //设置内容
        mailMessage.setText(content);
        //发送邮件
        mailSender.send(mailMessage);
    }
}

测试结果:

在流程定义中引用的类(例如上述的com.lonewalker.demo.delegate.SendEmailDelegate)不会在部署期间实例化。只有当流程执行到达流程中第一次使用该类的点时才会创建该类的实例。如果找不到该类,将抛出ProcessEngineException。

每次执行委托类引用活动时,将创建该类的一个单独实例。这意味着每次执行一个活动时,都会使用类的另一个实例来调用execute(DelegateExecution)。

💖Field Injection

在上述流程定义设计时已经演示了如何使用Field Injection。实际上就是把我们需要的值注入到委托类的字段中。

如果可用,则通过委托类上的公共setter方法注入该值,遵循Java Bean命名约定。

不管在流程定义中声明的值的类型是什么,注入目标上的字段的类型应该始终是

org. camunda.bbpm .engine.delegate. expression

💖其他

委托变量映射很少用就略过了,而执行监听器和任务监听器是重点,放在下一篇详细讲解Camunda执行监听器与任务监听器-CSDN博客

  • 34
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个使用 Camunda 表单的具体场景和代码示例: 场景:一个电商公司需要管理订单处理的流程。订单处理的流程包括以下几个步骤: 1. 订单创建:顾客在网站上创建订单,输入订单信息,包括订单号、商品名称、数量等。 2. 订单审核:订单审核员审核订单信息,可以选择接受或者拒绝订单。 3. 订单处理:如果订单审核通过,订单处理员将会处理订单,并且将订单状态更新为“已处理”。 4. 订单提交:订单处理员将订单提交给物流部门,准备发货。 5. 物流处理:物流员处理订单的发货和物流信息,将订单状态更新为“已发货”。 6. 订单完成:顾客收到订单货物后,将订单状态更新为“已完成”。 在 Camunda 中,可以使用表单来管理订单信息,以下是具体的步骤: 1. 创建表单模板:使用 Camunda Modeler 或者自定义 HTML 和 JavaScript 代码创建表单模板,包括订单号、商品名称、数量等元素。 ```html <form role="form"> <div class="form-group"> <label for="orderNo">订单号</label> <input type="text" class="form-control" id="orderNo" name="orderNo" ng-model="orderNo"> </div> <div class="form-group"> <label for="productName">商品名称</label> <input type="text" class="form-control" id="productName" name="productName" ng-model="productName"> </div> <div class="form-group"> <label for="quantity">数量</label> <input type="number" class="form-control" id="quantity" name="quantity" ng-model="quantity"> </div> </form> ``` 2. 定义表单字段:将表单模板中的各个元素与流程变量相关联,定义表单字段。 ```xml <camunda:formField id="orderNo" label="订单号" type="string" /> <camunda:formField id="productName" label="商品名称" type="string" /> <camunda:formField id="quantity" label="数量" type="long" /> ``` 3. 部署表单:将表单模板和定义好的表单字段部署到 Camunda BPM 平台上。 4. 在业务流程中使用表单:在任务表单中引用部署好的表单,让订单审核员和订单处理员使用表单来查看订单信息,并且选择接受或者拒绝订单。 ```xml <camunda:formKey>embedded:app:forms/order-form.html</camunda:formKey> ``` 5. 提交表单数据:在运行时,参与流程的用户可以使用表单来输入数据和做出选择,提交表单数据后,将会更新相关的流程变量,触发后续的流程执行。 这样,使用 Camunda 表单可以方便地管理订单信息,同时提高订单处理的效率和准确性,提高顾客的服务体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LoneWalker、

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值