消息推送和短信发送的实现方案
本文主要是将目前的消息模块做一个总结,分为短信发送、APP的消息推送两个部分。短信发送采用的是第三方的API(阿里大于短信平台),APP的消息推送采用的是极光的消息推送平台。只是介绍一个大概的流程,细节方面相对少一些。
消息发送流程:
- 有消息发送需求后,直接实例化msg或者sms,通过调用封装好的方法分别放到appMsgQueue和smsQueue。
//消息推送
@Autowired
@Qualifier("appMsgProcesser")
private MessageProcesser appMsgProcesser;
AppMsgMessage appMsgMessage = new AppMsgMessage(user, replaceMap, template);
appMsgProcesser.gather(appMsgMessage);
//短信
@Autowired
@Qualifier("smsProcesser")
private MessageProcesser smsProcesser;
SmsMessage smsMessage = new SmsMessage(moile, replaceStrs, template);
smsProcesser.gather(smsMessage);
//gather方法:
//appMsg
int result = Integer.parseInt(RedisUtils.lpush(MessageDefine.APPMSQUEUE, JSON.toJSONString(msgMessage)) + "");
//sms
int result = Integer.parseInt(RedisUtils.lpush(MessageDefine.SMSQUEUE, JSON.toJSONString(smsMessage)) + "");
- MsgHandler类,起一个线程随着系统启动而启动,sleep x秒,也就是每间隔x秒去检查队列中是否有数据,如果有将数据取出反序列化为信息实体,调用工具类中的send方法进行发送。
try {
// 检测副消息队列,是否有未发送的信息
Long num = RedisUtils.llen(MessageDefine.SMSQUENES);
SmsMessage smsMessage;
if (num > 0) {
String valueTemp;
for (int i = 0; i < num; i++) {
valueTemp = RedisUtils.rpop(MessageDefine.SMSQUENES);
if (StringUtils.isNotBlank(valueTemp)) {
// 反序列化成消息对象
smsMessage = JSON.parseObject(valueTemp, SmsMessage.class);
try {
smsProcesser.send(smsMessage);
} catch (Exception e) {
e.printStackTrace();
continue;
}
}
}
} else {// 尝试从主消息队列,获取短信进行发送
String value = RedisUtils.brpoplpush(MessageDefine.SMSQUENEM, MessageDefine.SMSQUENES, timeout);
if (StringUtils.isNotBlank(value)) {
// 反序列化成消息对象
smsMessage = JSON.parseObject(value, SmsMessage.class);
boolean result = smsProcesser.send(smsMessage);
// 发送消息成功 从副队列删除数据
if (result) {
RedisUtils.lrem(MessageDefine.SMSQUENES, -1, value);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
3.通过util中的方法,调用第三方API进行消息的推送和短信的发送。当然还要保存到本地发送记录等等。
这里采用启单独线程和Redis队列的方式来进行信息的发送,主要是为了避免大量的任务并发进来引起系统的崩溃,采用redis队列的方式可以一定程度上避免阻塞,线程池可创建多个线程来执行任务。