# 通知

在步骤节点上可以配置流程流转时发送的各类通知。通知的类型分待办和办理两种;发送渠道有邮件、短信、交我办三种,默认渠道是邮件通知;发送时间可以配置即时或者延时;发送内容的格式可以是变量替换或者Freemarker。

# 通知类型

# 待办通知

待办通知指流程流转到某步骤后,对配置在该步骤上有权限的执行人发送通知。发送的时间可以在流程到达该步骤时(即时)就发,或者延后一段时间后再发,采用哪个时间发送可根据业务需求,一般对实时性要求不是很高的流程推荐延后发送,只有通知量不大且要求实时通知的才采用即时方式。

我们现在举例说明,还是我们的请假流程,要求部门审核节点发送待办通知,这个待办通知不要求实时,只需要发送邮件即可,我们配置通知如下图。

提示

当通知的标题和内容都不填的时候会采用发送渠道默认的标题和内容,渠道默认标题内容对于发送待办通知来说已经足够了,除非业务方有特殊的需求

一般对于实时性要求不是很高的待办通知我们都会延后到下一个工作日早8点或9点,这么做有两个好处:

  1. 如果这之前用户已经办理了也就不必发通知了,用户的收件箱里不会堆了大量过期的待办通知。
  2. 如果到第二天上班时这个任务还没办理,那就会发送通知,且如果用户有多个流程的待办通知需要发,那么会合并成一个邮件发送。

# 办理通知

办理通知总是实时发送的,并且是步骤节点办理完毕后发送。

# 通知内容

对于待办通知,如果不指定通知的标题和内容,那么会用发送渠道的默认标题和内容发送通知,而对于办理通知则必须指定通知的内容。待办通知我们推荐使用渠道默认模版,当然您也可以根据业务方需求自定义通知内容。通知内容的发送可采用平台配置通知发送和Messenger中调用通知API发送两种,其中平台发送通知内容的组装有变量替换、FreeMarker、Messenger中组装通知字段三种方式,以下会逐一举例讲解。

# 变量替换

现在我们的请假流程需要在人事审核完毕后通知申请人,流程已经通过审核,通知的内容里需要提及此次请假的日期和类型。为此我们需要配置通知内容,采用变量替换的格式。

首先配置通知内容如下图,其中${fieldApplicant_Name}是申请人的姓名,对于User、Organize、Code类型的数据直接引用${字段名}分别表示用户的账号、部门代码、代码值,而引用了${字段名_Name}分别表示了用户姓名、部门名称、代码名称。所以通知内容中的${fieldType_Name}就是请假类型的名称了。

配置通知对象为流程申请人

办理通知可以配置用户办理哪个动作时不发送办理通知,人事审核否决时不用发送这个通知,所以我们做如下图配置

按这样配置后我们收到的邮件如图

这并不是我们需要的内容,因为我们的日期数据类型是Unix时间戳 (opens new window),记录的是1970年1月1日0点一来的秒数,所以直接表单变量替换的话是无法达到要求的。

# Freemarker

Freemarker格式的通知内容可以实现一些复杂的逻辑,现在让我们把上面这个模板用Freemarkder格式重新实现一次。

这次在通知内容填下如下内容,我们先将我们的日期*1000转换成毫秒,然后用number_to_datetime方法转换成日期类型再用string来格式化

${fieldApplicant_Name}老师,您好。

  您提交的${(fieldBeginDate*1000)?number_to_datetime?string('yyyy年M月d日')}-${(fieldEndDate*1000)?number_to_datetime?string('yyyy年M月d日')}的${fieldType_Name}申请已审核通过,请在交我办待办事项中及时确认。

网络信息中心
1
2
3
4
5

我们收到的通知就会是这样的

终于日期正常显示了,现在感觉还不错,不过好像提示内容还是有待优化,如果开始日期和结束日期一致的情况下,是不是结束日期就可以不用显示了呢?Freemarker具有逻辑判断的能力,现在将通知内容修改如下,里面用到了if命令

${fieldApplicant_Name}老师,您好。

  您提交的${(fieldBeginDate*1000)?number_to_datetime?string('yyyy年M月d日')}<#if fieldBeginDate != fieldEndDate>-${(fieldEndDate*1000)?number_to_datetime?string('yyyy年M月d日')}</#if>的${fieldType_Name}申请已审核通过,请在交我办待办事项中及时确认。

网络信息中心
1
2
3
4
5

现在我们终于收到了完美的通知!

关于Freemarker更多文档可参考官网 (opens new window)

# Messenger中组装数据

如果通知内容有一定的组装逻辑,但是又不熟悉Freemarker语法的话可以考虑在Messenger的事件中组装通知内容到一个字段里,将通知内容配置为这个字段即可。

现在再添加一个办理通知如下图,格式选择为变量替换,内容就是字段${fieldNotificationContent},当然为此还需要在表单中增加字段

在Messenger中添加onStepHrApproveActionApproveDoing方法处理人事审核通过的DOING事件,当然还要记得工作流编辑器中将这个DOING事件勾上。以下代码的逻辑和前面Freemarker模板中的逻辑是一样的。

public InfoPlusResponse onStepHrApproveActionApproveDoing(InfoPlusEvent e) {
    Leave form = e.toBean(Leave.class);
    SimpleDateFormat df = new SimpleDateFormat("yyyy年M月d日");
    String content = String.format("%s老师,您好。\n\n" +
                    "  您提交的%s的%s申请已审核通过,请在交我办待办事项中及时确认。\n\n" +
                    "网络信息中心", form.getApplicant().getTrueName(),
            form.getBeginDate().equals(form.getEndDate()) ?
                    df.format(form.getBeginDate()) :
                    df.format(form.getBeginDate()) + "-" + df.format(form.getEndDate()),
            form.getType().getCodeName());
    form.setNotificationContent(content);
    return new InfoPlusResponse(e, form);
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 用内容变量控制是否发送通知

流程引擎发送通知时会判断发送内容是否真的有值,如果内容为空就不会发送通知了,所以当我们采用Messenger里组装通知内容的方式,那么当在某些条件下不需要发送通知的话只需要将这个字段赋值为空字串就可以了。

# Messenger中调用API发送通知

当流程有发送短信通知的需求时,由于计费问题我们可以直接调用通知API来发送通知(一般情况下请勿使用平台短信渠道发通知,请使用业务部门专用的短信账号发短信)。

现在让我们实现在Messenger中发送通知,首先加入sjtu-api的maven依赖配置

<dependency>
    <groupId>sjtu</groupId>
    <artifactId>sjtu-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
1
2
3
4
5

注册这个bean

<bean id="api" class="edu.sjtu.api.applicationToolkit.API">
    <property name="baseApiUri" value="https://api.sjtu.edu.cn"/>
</bean>
1
2
3

增加项目属性配置

<properties>
    <config.notification.clientId></config.notification.clientId>
    <config.notification.secret></config.notification.secret>
    <config.notification.account></config.notification.account>
    <config.notification.password></config.notification.password>
</properties>
1
2
3
4
5
6

config.properites

notify.client.id=${config.notification.clientId}
notify.client.secret=${config.notification.secret}
notify.account=${config.notification.account}
notify.account.password=${config.notification.password}
1
2
3
4

项目中增加发送通知工具类Notificator (opens new window)

使用Notificator发送通知,还是在onStepHrApproveActionApproveDoing方法中实现

public InfoPlusResponse onStepHrApproveActionApproveDoing(InfoPlusEvent e) {
    Leave form = e.toBean(Leave.class);
    SimpleDateFormat df = new SimpleDateFormat("yyyy年M月d日");
    String content = String.format("%s老师,您好。\n\n" +
                    "  您提交的%s的%s申请已审核通过,请在交我办待办事项中及时确认。\n\n" +
                    "网络信息中心", form.getApplicant().getTrueName(),
            form.getBeginDate().equals(form.getEndDate()) ?
                    df.format(form.getBeginDate()) :
                    df.format(form.getBeginDate()) + "-" + df.format(form.getEndDate()),
            form.getType().getCodeName());
    try {
        notificator.sendMailNotification(form.getApplicant().getAccount()+"@sjtu.edu.cn","您的请假审核已审核通过",content);
    } catch (Exception ex) {
        ex.printStackTrace();
        throw new InfoPlusException("发送通知失败,请联系管理员");
    }
    return null;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在Messenger中调用API发送通知脱离了平台固有的通知渠道,具有最大的灵活性。

总结通知发送的方式及优缺点如下

方式 优点 缺点
变量替换 配置简单 不能满足内容组装逻辑,字段的格式化可能遇到问题
Freemarker 可实现依逻辑组装内容,可格式化字段 语法稍显复杂
Messenger组装通知内容字段 可实现复杂逻辑 需要增加Messenger处理代码,表单需要增加一个通知内容字段
Messenger调用通知API 通知渠道具有灵活性,可实现复杂逻辑 代码和配置量较大

# 测试通知

由于平台只发送正式上线流程的通知,所以当采用平台渠道发送通知时,通知内容的正确性无法通过接收通知来测试。

不过对于测试上线的流程,平台会对配置了通知且不采用渠道默认模板的通知记录一条活动日志,这可以在Activity Monitor菜单的Notification项里观看通知的内容。

点击图中红圈中的放大镜就可以看到通知的内容了。

# 案例地址

download 流程链接
download Messenger代码