消息推送和短信发送的实现方案

时间:2024-04-06 12:27:35

消息推送和短信发送的实现方案


本文主要是将目前的消息模块做一个总结,分为短信发送、APP的消息推送两个部分。短信发送采用的是第三方的API(阿里大于短信平台),APP的消息推送采用的是极光的消息推送平台。只是介绍一个大概的流程,细节方面相对少一些。

消息发送流程:
消息推送和短信发送的实现方案

  1. 有消息发送需求后,直接实例化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)) + "");
  1. 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队列的方式可以一定程度上避免阻塞,线程池可创建多个线程来执行任务。