消息推送、消息提醒、APP、短信、邮件、微信
实现统一的消息推送接口,包含PC消息、短信消息、邮件消息、微信消息等,无需让所有开发者了解消息是怎么发送出去的,只需了解消息发送接口即可。
所有推送消息均通过 MsgPushUtils
工具类发送。
注意此功能是专业版功能,只有专业版才能使用。
推送方式主要包括:
- 实时推送:即时推送消息,调用及发送消息。
- 定时推送:设定计划推送时间,定时推送消息。
- 合并推送:不重要的通知进行汇总,30分钟或更长执行一次,将多条消息合并为一条消息延迟推送给用户,和定时消息不是一回事。
# 消息表
1、消息待推送表(js_sys_msg_push): 实时监测待推送的消息数据表,检测到消息后调用推送接口。
2、消息已推送表(js_sys_msg_pushed):推送完成后,存入到这个历史表里,作为日后查询消息推送历史用。
# 消息配置
# 消息提醒中心(专业版)
msg:
enabled: true
# 是否开启实时发送消息(保存消息后立即检查未读消息并发送),分布式部署下请单独配置消息发送服务,不建议开启此选项。
realtime:
# 是否开启
enabled: true
# 推送失败次数,如果推送次数超过了设定次数,仍不成功,则放弃并保存到历史
pushFailNumber: 3
# 邮件发送参数
email:
beanName: emailSendService
fromAddress: jeesite_demo@163.com
fromPassword: jeesite_xxxx
fromHostName: smtp.163.com
sslOnConnect: false
sslSmtpPort: 994
# 短信网关
sms:
beanName: smsSendService
url: http://localhost:80/msg/sms/send
data: username=jeesite&password=jeesite.com
prefix: 【JeeSite】
suffix: ~
# 微信消息
weixin:
beanName: weixinSendService
# APP消息
app:
beanName: appSendService
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
注意:环境名称,不可设置为 test 它是单元测试专用的名称,否则会造成消息无法使用
spring.profiles.active: default
提示:“定时消息” 和 “合并推送” 必须从 “系统监控->作业监控” 菜单里开启消息推送服务才可使用。如果此服务开启,可关闭 “实时发送消息” 开关。
# 消息推送实现
目前JeeSite中只实现了PC和Email的推送服务,其余的推送服务(如:短信、微信、APP等)您需要自己去实现。
短信推送其实调用的是 com.jeesite.common.msg.SmsUtils.send(String content, String mobile)
静态方法(该类在jeesite-common项目中),您可以实现此方法。
下面还是以短信推送为例,自定一个推送类:
package com.jeesite.modules.msg.send.impl;
import java.util.Date;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.jeesite.common.lang.ExceptionUtils;
import com.jeesite.common.lang.ObjectUtils;
import com.jeesite.common.mapper.JsonMapper;
import com.jeesite.common.msg.SmsUtils;
import com.jeesite.common.service.BaseService;
import com.jeesite.modules.msg.entity.MsgPush;
import com.jeesite.modules.msg.entity.content.SmsMsgContent;
import com.jeesite.modules.msg.send.MsgSendService;
/**
* SMS发送服务
* @author ThinkGem
* @version 2018年5月13日
*/
@Service
public class CustomSmsSendService extends BaseService implements MsgSendService{
@Override
public void sendMessage(MsgPush msgPush) {
try{
// 发送短信
SmsMsgContent content = msgPush.parseMsgContent(SmsMsgContent.class);
String result = SmsUtils.send(content.getContent(), msgPush.getReceiveCode());
Map<String, Object> map = JsonMapper.fromJson(result, Map.class);
// 发送成功
if (ObjectUtils.toInteger(map.get("result")) == 0){
msgPush.setPushStatus(MsgPush.PUSH_STATUS_SUCCESS);
msgPush.addPushReturnContent(result);
}
// 发送失败
else{
throw new RuntimeException(result);
}
} catch (Exception ex) {
logger.error("发送短信失败! ", ex);
msgPush.setPushDate(new Date());
msgPush.setPushStatus(MsgPush.PUSH_STATUS_FAIL);
msgPush.addPushReturnContent(ExceptionUtils.getStackTraceAsString(ex));
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
该类已通过 @Service
注册到了 Spring Bean 中,注册的 Bean 名称是 customSmsSendService
。
下面我们可去修改 jeeiste.yml
的配置如下,指定该 Bean 名称:
# 消息提醒中心(专业版)
msg:
# 短信网关
sms:
beanName: customSmsSendService
2
3
4
5
这样消息推送服务实现就可以工作了。
# 工具使用例子
上面配置好了,那如何使用呢,我们可以打开 com.jeesite.test.MsgPushTest
单元测试类(该类在jeesite-module-core项目中),里面基本涵盖了所有的推送消息例子。
# 发送 PC 消息
PcMsgContent msgContent = new PcMsgContent();
msgContent.setTitle("提示信息");
msgContent.setContent("您有1条新的任务");
msgContent.addButton("办理", "/a/task/execute?id=123");
// 即时推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system");
// 定时推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", DateUtils.parseDate("2018-05-05 08:30"));
// 合并推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", new Date(), Global.YES);
2
3
4
5
6
7
8
9
10
# 发送 APP 消息
AppMsgContent msgContent = new AppMsgContent();
msgContent.setTitle("提示信息");
msgContent.setContent("您有1条新的任务");
// 即时推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system");
// 定时推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", DateUtils.parseDate("2018-05-05 08:30"));
// 合并推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", new Date(), Global.YES);
2
3
4
5
6
7
8
9
# 发送短信
SmsMsgContent msgContent = new SmsMsgContent();
msgContent.setTitle("提示信息");
msgContent.setContent("您好,您的验证码是:123456(请勿透露给其他人)感谢您的使用。");
// 即时推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system");
// 定时推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", DateUtils.parseDate("2018-05-05 08:30"));
// 合并推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", new Date(), Global.YES);
2
3
4
5
6
7
8
9
# 发送邮件
EmailMsgContent msgContent = new EmailMsgContent();
msgContent.setTitle("提示信息");
msgContent.setContent("这是一条测试邮件内容");
// 即时推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system");
// 定时推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", DateUtils.parseDate("2018-05-05 08:30"));
// 合并推送消息
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", new Date(), Global.YES);
2
3
4
5
6
7
8
9
# 根据消息模板发送消息
// 创建消息模板
MsgTemplate msgTemplate = new MsgTemplate();
msgTemplate.setTplKey("mail_send_test");
List<MsgTemplate> tplList = msgTemplateService.findList(msgTemplate);
if (tplList.size() == 0){
msgTemplate.setTplName("邮件提示信息");
msgTemplate.setTplContent("您好,${keyword1},请于 ${keyword2},准时参加${keyword3}");
msgTemplate.setTplType("email");
msgTemplateService.save(msgTemplate);
}
// 根据模板发送消息
EmailMsgContent msgContent = new EmailMsgContent();
msgContent.setTitle("邮件提示信息");
msgContent.setTplKey("mail_send_test");
msgContent.addTplData("keyword1", "小王");
msgContent.addTplData("keyword2", "2018-8-28 20:00");
msgContent.addTplData("keyword3", "OA项目方案讨论视频会议");
// 即时推送模板消息,模板内容:您好,${keyword1},请于 ${keyword2},准时参加${keyword3}
MsgPushUtils.push(msgContent, "BizKey", "BizType", "system");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 消息工具 API
com.jeesite.modules.msg.utils.MsgPushUtils
/**
* 推送消息(即时推送)
* @param type 消息类型(MsgPush.TYPE_PC、TYPE_APP、TYPE_SMS、TYPE_EMAIL)
* @param title 消息标题
* @param content 消息内容
* @param bizKey 关联业务主键
* @param bizType 关联业务类型
* @param receiveUserCodes 接受者用户编码
* @author ThinkGem
*/
public static MsgPush push(String type, String title, String content, String bizKey, String bizType, String receiveUserCodes){
BaseMsgContent msgContent = null;
if (MsgPush.TYPE_PC.equals(type)){
msgContent = new PcMsgContent();
}else if (MsgPush.TYPE_APP.equals(type)){
msgContent = new AppMsgContent();
}else if (MsgPush.TYPE_SMS.equals(type)){
msgContent = new SmsMsgContent();
}else if (MsgPush.TYPE_EMAIL.equals(type)){
msgContent = new EmailMsgContent();
}
if (msgContent != null){
msgContent.setTitle(title);
msgContent.setContent(content);
return push(msgContent, bizKey, bizType, receiveUserCodes, new Date(), Global.NO);
}
return null;
}
/**
* 推送消息(即时推送)
* @param msgContent 消息内容实体:PcMsgContent、AppMsgContent、SmsMsgContent、EmailMsgContent、WeicxinMsgContent
* @param bizKey 关联业务主键
* @param bizType 关联业务类型
* @param receiveUserCodes 接受者用户编码
* @author ThinkGem
*/
public static MsgPush push(BaseMsgContent msgContent, String bizKey, String bizType, String receiveUserCodes){
return push(msgContent, bizKey, bizType, receiveUserCodes, new Date(), Global.NO);
}
/**
* 推送消息
* @param msgContent 消息内容实体:PcMsgContent、AppMsgContent、SmsMsgContent、EmailMsgContent、WeicxinMsgContent
* @param bizKey 关联业务主键
* @param bizType 关联业务类型
* @param receiveUserCodes 接受者用户编码,多个用逗号隔开,用[CODE]作为前缀,可直接指定接受者手机号或邮箱地址等
* @param planPushDate 计划推送时间(指定推送时间,延迟推送)
* @param isMergePush 是否是合并推送(将消息合并为一条,延迟推送,用于不重要的提醒),默认:Global.NO
* @author ThinkGem
*/
public static MsgPush push(BaseMsgContent msgContent, String bizKey, String bizType, String receiveUserCodes, Date planPushDate, String isMergePush) {
boolean isNone = StringUtils.startsWith(receiveUserCodes, "[CODE]");
if (isNone){
receiveUserCodes = StringUtils.substringAfter(receiveUserCodes, "[CODE]");
}
MsgPush msgPush = null;
for (String receiveUserCode : StringUtils.split(receiveUserCodes, ",")){
msgPush = new MsgPush();
msgPush.setMsgContentEntity(msgContent);
msgPush.setBizKey(bizKey);
msgPush.setBizType(bizType);
if (isNone){
msgPush.setReceiveCode(receiveUserCode);
}else{
msgPush.setReceiveUserCode(receiveUserCode);
}
msgPush.setPlanPushDate(planPushDate);
msgPush.setIsMergePush(isMergePush);
push(msgPush);
}
return msgPush;
}
/**
* 推送消息
* @param msgPush 推送对象
* @example
* MsgPush msgPush = new MsgPush();
* SmsMsgContent msgContent = new SmsMsgContent();
* msgContent.setTitle(title);
* msgContent.setContent(content);
* msgPush.setMsgContentEntity(msgContent);
* msgPush.setBizKey(bizKey);
* msgPush.setBizType(bizType);
* msgPush.setReceiveUserCode(receiveUserCode);
* msgPush.setPlanPushDate(planPushDate);
* msgPush.setIsMergePush(isMergePush);
* @author ThinkGem
*/
public static void push(MsgPush msgPush) {
Static.msgPushService.save(msgPush);
}
/**
* 读取消息(业务处理完成后调用,自动处理对应业务的消息)
* 场景:用户先处理了对应的业务,如流程审批完成,但消息还是未读。
* 这时审批后可以通过此方法进行处理消息状态。
* @param bizKey 业务主键
* @param bizType 业务类型
* @param receiveUserCode 接受者用户编码(必填)
* @author ThinkGem
*/
public static void readMsgByBiz(String bizKey, String bizType, String receiveUserCode) {
MsgPush mp = new MsgPush();
mp.setBizKey(bizKey);
mp.setBizType(bizType);
if(StringUtils.isBlank(receiveUserCode)){
return;
}
mp.setReceiveUserCode(receiveUserCode);
List<MsgPush> list = Static.msgPushService.findList(mp);
for (MsgPush msgPush : list){
msgPush.setReadDate(new Date());
msgPush.setReadStatus(MsgPush.READ_STATUS_READ);
Static.msgPushService.updateMsgPush(msgPush);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# 微信消息推送
集成 WxJava 微信开发 Java SDK,支持微信支付、开放平台、公众号、企业号/企业微信、小程序等的后端开发。
该模块已实现:微信消息推送、微信公众号与 JeeSite 绑定登录、小程序与企业微信接口等
微信公众平台测试号:
# 集成微信模块
1、打开 web 的 pom.xml,加入如下模块依赖代码
<!-- 微信相关集成 -->
<dependency>
<groupId>com.jeesite</groupId>
<artifactId>jeesite-module-weixin</artifactId>
<version>${project.parent.version}</version>
</dependency>
2
3
4
5
6
注意:v4.1.8+ 专业版提供,此模块源代码,请向售后人员索取。
2、配置参数:
wx:
# 微信公众号(JeeSite 绑定微信使用)
mp:
enabled: true
configs:
- appId: 111
secret: 111
token: 111
aesKey: 111
# 登录授权回调地址
oauth:
redirect:
uri: http://demo.jeesite.com/js
# 微信消息推送(消息推送 WeixinMsgPushUtils 工具使用)
msg:
weixin:
beanName: weixinSendService
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 微信推送实例
/**
* 自定义菜单测试
* @author ThinkGem
* @version 2018-10-17
*/
@ActiveProfiles("test")
@SpringBootTest(classes=ApplicationTest.class)
@Rollback(false)
public class WeixinMsgPushTest extends BaseSpringContextTests {
@Test
public void send() {
WxMpTemplateMessage templateMessage = new WxMpTemplateMessage();
templateMessage.setTemplateId("KSZCB199kSp535kOa0AJ5wJQ_XMvMHL__FMYLl_N2Nc");
templateMessage.setUrl("http://demo.jeesite.com/js");
templateMessage.addData(new WxMpTemplateData("first", "这是任务标题", "#f00"));
templateMessage.addData(new WxMpTemplateData("keyword1", "ThinkGem"));
templateMessage.addData(new WxMpTemplateData("keyword2", "2020-2-20"));
templateMessage.addData(new WxMpTemplateData("keyword3", "这是消息的描述2"));
templateMessage.addData(new WxMpTemplateData("remark", "请尽快办理,谢谢!", "#173177"));
// 即时推送消息
WeixinMsgPushUtils.push(templateMessage, null, "BizKey", "BizType", "system");
// 定时推送消息
WeixinMsgPushUtils.push(templateMessage, null, "BizKey", "BizType", "system", DateUtils.parseDate("2020-2-20 09:50"));
// 延迟推送消息
WeixinMsgPushUtils.push(templateMessage, null, "BizKey", "BizType", "system", new Date(), Global.YES);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 微信消息工具 API
调用 WeixinMsgPushUtils 工具,方法如下:
/**
* 推送消息
* @param templateMessage 微信模板消息
* @param bizKey 关联业务主键
* @param bizType 关联业务类型
* @param receiveUserCode 接受者用户编码
* @author ThinkGem
*/
public static void push(WxMpTemplateMessage templateMessage, String title, String bizKey, String bizType, String receiveUserCode);
/**
* 推送消息
* @param templateMessage 微信模板消息
* @param bizKey 关联业务主键
* @param bizType 关联业务类型
* @param receiveUserCode 接受者用户编码
* @author ThinkGem
*/
public static void push(WxMpTemplateMessage templateMessage, String title, String bizKey, String bizType, String receiveUserCode, Date planPushDate);
/**
* 推送消息(即时推送)
* @param title 消息标题
* @param templateMessage 微信模板消息
* @param bizKey 关联业务主键
* @param bizType 关联业务类型
* @param receiveUserCode 接受者用户编码
* @param planPushDate 计划推送时间(指定推送时间,延迟推送)
* @param isMergePush 是否是合并推送(将消息合并为一条,延迟推送,用于不重要的提醒),默认:Global.NO
* @author ThinkGem
*/
public static void push(WxMpTemplateMessage templateMessage, String title, String bizKey, String bizType, String receiveUserCode, Date planPushDate, String isMergePush);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34