消息推送、消息提醒、APP、短信、微信、邮件

实现统一的消息推送接口,包含PC消息、短信消息、邮件消息、微信消息等,无需让所有开发者了解消息是怎么发送出去的,只需了解消息发送接口即可。

所有推送消息均通过 MsgPushUtils 工具类发送。

注意此功能是专业版功能,只有专业版才能使用。

推送方式主要包括:

  • 实时推送:即时推送消息,调用及发送消息。
  • 定时推送:设定计划推送时间,定时推送消息。
  • 合并推送:不重要的通知进行汇总,30分钟或更长执行一次,将多条消息合并为一条消息延迟推送给用户,和定时消息不是一回事。

消息表

1、消息待推送表(js_sys_msg_push): 实时监测待推送的消息数据表,检测到消息后调用推送接口。

2、消息已推送表(js_sys_msg_pushed):推送完成后,存入到这个历史表里,作为日后查询消息推送历史用。

消息配置

  1. # 消息提醒中心(专业版)
  2. msg:
  3. enabled: true
  4. # 是否开启实时发送消息(保存消息后立即检查未读消息并发送),分布式部署下请单独配置消息发送服务,不建议开启此选项。
  5. realtime:
  6. # 是否开启
  7. enabled: true
  8. # 推送失败次数,如果推送次数超过了设定次数,仍不成功,则放弃并保存到历史
  9. pushFailNumber: 3
  10. # 邮件发送参数
  11. email:
  12. beanName: emailSendService
  13. fromAddress: jeesite_demo@163.com
  14. fromPassword: jeesite_xxxx
  15. fromHostName: smtp.163.com
  16. sslOnConnect: false
  17. sslSmtpPort: 994
  18. # 短信网关
  19. sms:
  20. beanName: smsSendService
  21. url: http://localhost:80/msg/sms/send
  22. data: username=jeesite&password=jeesite.com
  23. prefix: JeeSite
  24. suffix: ~

注意 “定时消息” 和 “合并推送” 必须从 “系统监控->作业监控” 菜单里开启消息推送服务才可使用。如果此服务开启,可关闭 “实时发送消息” 开关。

消息推送实现

目前JeeSite中只实现了PC和Email的推送服务,其余的推送服务(如:短信、微信、APP等)你需要自己去实现。

短信推送其实调用的是 com.jeesite.common.msg.SmsUtils.send(String content, String mobile) 静态方法(该类在jeesite-common项目中),你可以实现此方法。

下面还是以短信推送为例,自定一个推送类:

  1. package com.jeesite.modules.msg.send.impl;
  2. import java.util.Date;
  3. import java.util.Map;
  4. import org.springframework.stereotype.Service;
  5. import com.jeesite.common.lang.ExceptionUtils;
  6. import com.jeesite.common.lang.ObjectUtils;
  7. import com.jeesite.common.mapper.JsonMapper;
  8. import com.jeesite.common.msg.SmsUtils;
  9. import com.jeesite.common.service.BaseService;
  10. import com.jeesite.modules.msg.entity.MsgPush;
  11. import com.jeesite.modules.msg.entity.content.SmsMsgContent;
  12. import com.jeesite.modules.msg.send.MsgSendService;
  13. /**
  14. * SMS发送服务
  15. * @author ThinkGem
  16. * @version 2018年5月13日
  17. */
  18. @Service
  19. public class CustomSmsSendService extends BaseService implements MsgSendService{
  20. @Override
  21. public void sendMessage(MsgPush msgPush) {
  22. try{
  23. // 发送短信
  24. SmsMsgContent content = msgPush.parseMsgContent(SmsMsgContent.class);
  25. String result = SmsUtils.send(content.getContent(), msgPush.getReceiveCode());
  26. Map<String, Object> map = JsonMapper.fromJson(result, Map.class);
  27. // 发送成功
  28. if (ObjectUtils.toInteger(map.get("result")) == 0){
  29. msgPush.setPushStatus(MsgPush.PUSH_STATUS_SUCCESS);
  30. msgPush.addPushReturnContent(result);
  31. }
  32. // 发送失败
  33. else{
  34. throw new RuntimeException(result);
  35. }
  36. } catch (Exception ex) {
  37. logger.error("发送短信失败! ", ex);
  38. msgPush.setPushDate(new Date());
  39. msgPush.setPushStatus(MsgPush.PUSH_STATUS_FAIL);
  40. msgPush.addPushReturnContent(ExceptionUtils.getStackTraceAsString(ex));
  41. }
  42. }
  43. }

该类已通过 @Service 注册到了 Spring Bean 中,注册的 Bean 名称是 customSmsSendService

下面我们可去修改 jeeiste.yml 的配置如下,指定该 Bean 名称:

  1. # 消息提醒中心(专业版)
  2. msg:
  3. # 短信网关
  4. sms:
  5. beanName: customSmsSendService

这样消息推送服务实现就可以工作了。

工具使用例子

上面配置好了,那如何使用呢,我们可以打开 com.jeesite.test.MsgPushTest 单元测试类(该类在jeesite-module-core项目中),里面基本涵盖了所有的推送消息例子。

发送 PC 消息

  1. PcMsgContent msgContent = new PcMsgContent();
  2. msgContent.setTitle("提示信息");
  3. msgContent.setContent("您有1条新的任务");
  4. msgContent.addButton("办理", "/a/task/execute?id=123");
  5. // 即时推送消息
  6. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system");
  7. // 定时推送消息
  8. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", DateUtils.parseDate("2018-05-05 08:30"));
  9. // 合并推送消息
  10. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", new Date(), Global.YES);

发送 APP 消息

  1. AppMsgContent msgContent = new AppMsgContent();
  2. msgContent.setTitle("提示信息");
  3. msgContent.setContent("您有1条新的任务");
  4. // 即时推送消息
  5. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system");
  6. // 定时推送消息
  7. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", DateUtils.parseDate("2018-05-05 08:30"));
  8. // 合并推送消息
  9. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", new Date(), Global.YES);

发送短信

  1. SmsMsgContent msgContent = new SmsMsgContent();
  2. msgContent.setTitle("提示信息");
  3. msgContent.setContent("您好,您的验证码是:123456(请勿透露给其他人)感谢您的使用。");
  4. // 即时推送消息
  5. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system");
  6. // 定时推送消息
  7. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", DateUtils.parseDate("2018-05-05 08:30"));
  8. // 合并推送消息
  9. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", new Date(), Global.YES);

发送邮件

  1. EmailMsgContent msgContent = new EmailMsgContent();
  2. msgContent.setTitle("提示信息");
  3. msgContent.setContent("这是一条测试邮件内容");
  4. // 即时推送消息
  5. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system");
  6. // 定时推送消息
  7. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", DateUtils.parseDate("2018-05-05 08:30"));
  8. // 合并推送消息
  9. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system", new Date(), Global.YES);

根据消息模板发送消息

  1. // 创建消息模板
  2. MsgTemplate msgTemplate = new MsgTemplate();
  3. msgTemplate.setTplKey("mail_send_test");
  4. List<MsgTemplate> tplList = msgTemplateService.findList(msgTemplate);
  5. if (tplList.size() == 0){
  6. msgTemplate.setTplName("邮件提示信息");
  7. msgTemplate.setTplContent("你好,${keyword1},请于 ${keyword2},准时参加${keyword3}");
  8. msgTemplate.setTplType("email");
  9. msgTemplateService.save(msgTemplate);
  10. }
  11. // 根据模板发送消息
  12. EmailMsgContent msgContent = new EmailMsgContent();
  13. msgContent.setTitle("邮件提示信息");
  14. msgContent.setTplKey("mail_send_test");
  15. msgContent.addTplData("keyword1", "小王");
  16. msgContent.addTplData("keyword2", "2018-8-28 20:00");
  17. msgContent.addTplData("keyword3", "OA项目方案讨论视频会议");
  18. // 即时推送模板消息,模板内容:你好,${keyword1},请于 ${keyword2},准时参加${keyword3}
  19. MsgPushUtils.push(msgContent, "BizKey", "BizType", "system");

消息工具 API

com.jeesite.modules.msg.utils.MsgPushUtils

  1. /**
  2. * 推送消息(即时推送)
  3. * @param type 消息类型(MsgPush.TYPE_PC、TYPE_APP、TYPE_SMS、TYPE_EMAIL)
  4. * @param title 消息标题
  5. * @param content 消息内容
  6. * @param bizKey 关联业务主键
  7. * @param bizType 关联业务类型
  8. * @param receiveUserCodes 接受者用户编码
  9. * @author ThinkGem
  10. */
  11. public static MsgPush push(String type, String title, String content, String bizKey, String bizType, String receiveUserCodes){
  12. BaseMsgContent msgContent = null;
  13. if (MsgPush.TYPE_PC.equals(type)){
  14. msgContent = new PcMsgContent();
  15. }else if (MsgPush.TYPE_APP.equals(type)){
  16. msgContent = new AppMsgContent();
  17. }else if (MsgPush.TYPE_SMS.equals(type)){
  18. msgContent = new SmsMsgContent();
  19. }else if (MsgPush.TYPE_EMAIL.equals(type)){
  20. msgContent = new EmailMsgContent();
  21. }
  22. if (msgContent != null){
  23. msgContent.setTitle(title);
  24. msgContent.setContent(content);
  25. return push(msgContent, bizKey, bizType, receiveUserCodes, new Date(), Global.NO);
  26. }
  27. return null;
  28. }
  29. /**
  30. * 推送消息(即时推送)
  31. * @param msgContent 消息内容实体:PcMsgContent、AppMsgContent、SmsMsgContent、EmailMsgContent、WeicxinMsgContent
  32. * @param bizKey 关联业务主键
  33. * @param bizType 关联业务类型
  34. * @param receiveUserCodes 接受者用户编码
  35. * @author ThinkGem
  36. */
  37. public static MsgPush push(BaseMsgContent msgContent, String bizKey, String bizType, String receiveUserCodes){
  38. return push(msgContent, bizKey, bizType, receiveUserCodes, new Date(), Global.NO);
  39. }
  40. /**
  41. * 推送消息
  42. * @param msgContent 消息内容实体:PcMsgContent、AppMsgContent、SmsMsgContent、EmailMsgContent、WeicxinMsgContent
  43. * @param bizKey 关联业务主键
  44. * @param bizType 关联业务类型
  45. * @param receiveUserCodes 接受者用户编码,多个用逗号隔开,用[CODE]作为前缀,可直接指定接受者手机号或邮箱地址等
  46. * @param planPushDate 计划推送时间(指定推送时间,延迟推送)
  47. * @param isMergePush 是否是合并推送(将消息合并为一条,延迟推送,用于不重要的提醒),默认:Global.NO
  48. * @author ThinkGem
  49. */
  50. public static MsgPush push(BaseMsgContent msgContent, String bizKey, String bizType, String receiveUserCodes, Date planPushDate, String isMergePush) {
  51. boolean isNone = StringUtils.startsWith(receiveUserCodes, "[CODE]");
  52. if (isNone){
  53. receiveUserCodes = StringUtils.substringAfter(receiveUserCodes, "[CODE]");
  54. }
  55. MsgPush msgPush = null;
  56. for (String receiveUserCode : StringUtils.split(receiveUserCodes, ",")){
  57. msgPush = new MsgPush();
  58. msgPush.setMsgContentEntity(msgContent);
  59. msgPush.setBizKey(bizKey);
  60. msgPush.setBizType(bizType);
  61. if (isNone){
  62. msgPush.setReceiveCode(receiveUserCode);
  63. }else{
  64. msgPush.setReceiveUserCode(receiveUserCode);
  65. }
  66. msgPush.setPlanPushDate(planPushDate);
  67. msgPush.setIsMergePush(isMergePush);
  68. push(msgPush);
  69. }
  70. return msgPush;
  71. }
  72. /**
  73. * 推送消息
  74. * @param msgPush 推送对象
  75. * @example
  76. * MsgPush msgPush = new MsgPush();
  77. * SmsMsgContent msgContent = new SmsMsgContent();
  78. * msgContent.setTitle(title);
  79. * msgContent.setContent(content);
  80. * msgPush.setMsgContentEntity(msgContent);
  81. * msgPush.setBizKey(bizKey);
  82. * msgPush.setBizType(bizType);
  83. * msgPush.setReceiveUserCode(receiveUserCode);
  84. * msgPush.setPlanPushDate(planPushDate);
  85. * msgPush.setIsMergePush(isMergePush);
  86. * @author ThinkGem
  87. */
  88. public static void push(MsgPush msgPush) {
  89. Static.msgPushService.save(msgPush);
  90. }
  91. /**
  92. * 读取消息(业务处理完成后调用,自动处理对应业务的消息)
  93. * @param bizKey 业务主键
  94. * @param bizType 业务类型
  95. * @param receiveUserCode 接受者用户编码(必填)
  96. * @author ThinkGem
  97. */
  98. public static void readMsgByBiz(String bizKey, String bizType, String receiveUserCode) {
  99. MsgPush mp = new MsgPush();
  100. mp.setBizKey(bizKey);
  101. mp.setBizType(bizType);
  102. if(StringUtils.isBlank(receiveUserCode)){
  103. return;
  104. }
  105. mp.setReceiveUserCode(receiveUserCode);
  106. List<MsgPush> list = Static.msgPushService.findList(mp);
  107. for (MsgPush msgPush : list){
  108. msgPush.setReadDate(new Date());
  109. msgPush.setReadStatus(MsgPush.READ_STATUS_READ);
  110. Static.msgPushService.updateMsgPush(msgPush);
  111. }
  112. }