重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
这期内容当中小编将会给大家带来有关怎么在spring boot中实现消息推送系统设计,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
专注于为中小企业提供网站设计、成都网站制作服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业赵县免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了数千家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
推送系统作为通用的组件,存在的价值主要有以下几点
会被多个业务项目使用,推送系统独立维护可降低维护成本
推送系统一般都是调用三方api进行推送,三方api一般会有调用频率/次数限制,被推送的消息需要走队列来合理调用三方api,控制调用的频率和次数
业务无关,一般推送系统设计成不需要关心业务逻辑
核心技术
消息队列
三方服务api调用
安卓app推送
苹果app推送
微信小程序推送
邮件推送
钉钉推送
短信推送
消息队列选用阿里云提供的rocketmq,官方文档:https://help.aliyun.com/document_detail/55385.html
推送时序图
右键新窗口打开可以查看高清大图
可以看到消息推送系统接入的第三方服务比较多,三方推送的质量很难统一,就需要考虑消息的推送的重试了
思路流程
为了控制并发,所有的推送都先发到rocketmq队列里,每次推送的个数通过控制队列的消费的客户端的数量来实现
安卓和苹果都可以使用信鸽的推送服务
信鸽推送需要客户端进行集成,客户端sdk参考: https://xg.qq.com/xg/ctr_index/download
目前信鸽个人开发者仍然是可以申请的,账号建立后,创建andorid和ios项目
记录下这里的 APP ID和SECRET KEY,服务端进行推送时需要这两个参数
推送异常处理,推送异常时,需要重试,重试可以利用消息队列本身的重试机制,也可以自行实现重试逻辑
安卓app推送
官方文档: https://xg.qq.com/docs/android_access/jcenter.html
代码库: https://github.com/xingePush/xinge-api-java
com.github.xingePush xinge 1.2.1
核心代码如下
MapmessagePayload = new HashMap (1); messagePayload.put("user_id", 1); messagePayload.put("msg_title", "消息标题"); messagePayload.put("msg_content", "消息内容"); messagePayload.put("msg_type", 1); messagePayload.put("data", Lists.newHashMap("order_id", 1)); XingeApp xinge = new XingeApp(androidAccessId, androidSecretKey); MessageAndroid message = new MessageAndroid(); ClickAction action = new ClickAction(); action.setActionType(ClickAction.TYPE_ACTIVITY); message.setAction(action); message.setContent(JsonUtil.toJsonString(messagePayload)); message.setType(MessageAndroid.TYPE_MESSAGE); message.setExpireTime(86400); message.setCustom(new HashMap (1)); JSONObject response = xinge.pushSingleDevice("用户的PushToken", message); if (response.getInt(RET_CODE) != 0) { // 推送异常了,进行日志记录等 }
苹果app推送
使用pushy库进行推送
com.turo pushy 0.13.3
Mapaps = new HashMap (1); aps.put("alert", "推送内容"); aps.put("sound", "default"); aps.put("badge", 1); Map data = new HashMap (1); data.put("msgTitle", "推送标题"); data.put("msgContent", "推送内容"); data.put("msgType", "1"); data.put("userId", "13288888888"); data.put("data", Lists.newHashMap("order_id", 1)); Map messagePayload = new HashMap (1); messagePayload.put("aps", aps); messagePayload.put("data", data); ApnsClient apnsClient = new ApnsClientBuilder() .setApnsServer(ApnsClientBuilder.PRODUCTION_APNS_HOST) .setClientCredentials(this.getClass().getClassLoader().getResourceAsStream("推送证书相对resources目录的路径"), "") .build(); String payload = JsonUtil.toJsonString(messagePayload); String token = TokenUtil.sanitizeTokenString("app用户的pushToken"); SimpleApnsPushNotification pushNotification = new SimpleApnsPushNotification(token, "com.suxiaolin.app1", payload); PushNotificationFuture > sendNotificationFuture = apnsClient.sendNotification(pushNotification); final PushNotificationResponse pushNotificationResponse = sendNotificationFuture.get(); if (pushNotificationResponse.isAccepted()) { System.out.println("Push notification accepted by APNs gateway."); } else { System.out.println("Notification rejected by the APNs gateway: " + pushNotificationResponse.getRejectionReason()); if (pushNotificationResponse.getTokenInvalidationTimestamp() != null) { System.out.println("\t…and the token is invalid as of " + pushNotificationResponse.getTokenInvalidationTimestamp()); } }
使用信鸽库进行推送
当然也可以使用信鸽提供的ios推送,逻辑和安卓app的推送差不多
ios的信鸽客户端可以和android的客户端共用,不需要引入新的jar包了
JSONObject messagePayload = new JSONObject(); Mapcustom = new HashMap (); messagePayload.put("title", "推送标题"); messagePayload.put("body", "推送内容"); messagePayload.put("user_id", 1); messagePayload.put("msg_type", 1); messagePayload.put("data", Lists.newArrayList("orderId", 1)); XingeApp xinge = new XingeApp(iosAccessId, iosSecretKey); MessageIOS message = new MessageIOS(); message.setType(MessageIOS.TYPE_APNS_NOTIFICATION); message.setExpireTime(86400); message.setAlert(content); message.setBadge(1); message.setCategory("INVITE_CATEGORY"); message.setCustom(messagePayload); response = xinge.pushSingleDevice("app用户的pushToken", message, XingeApp.IOSENV_PROD); if (response.getInt(RET_CODE) != 0) { // 推送异常了 }
钉钉推送
public static boolean send(String content, String title, Setreceivers) { try { HttpUtil.ResponseWrap result = HttpUtil.postWrap(ddUrl, "{\n" + " \"msgtype\": \"text\",\n" + " \"text\": {\"content\":\"" + title + "\r\n" + content + "\n|" + receivers.stream().map(r -> "@" + r).collect(Collectors.joining(" ")) + "\"},\n" + " \"at\": {\n" + " \"atMobiles\": [" + receivers.stream().map(r -> "\"" + r + "\"").collect(Collectors.joining(",")) + "], \n" + " \"isAtAll\": false\n" + " }\n" + " }"); return result.getStatusCode() == 200; } catch (Exception e) { return false; } }
完整代码参考DingTalkUtil.java
使用http请求就可以请求了
邮件推送
发送邮件可以使用java的javax.mail库,smtp协议发送邮件
javax.mail 1.4.7
示例代码参考: EmailSender.java
短信推送
短信服务商众多,邮件一般有统一的smtp协议可以使用,短信没有协议,但是一般使用http发送短信 比如以下的短信服务商
253云通讯:zz.253.com/api_doc/kai…
短信服务- 又拍云: https://www.upyun.com/products/sms
消息&短信_MSGSMS_云通信_短信- 华为云: https://www.huaweicloud.com/product/msgsms.html
消息队列的特性
消息队列消费异常后会自动进行重试
一些注意的点
微信小程序每次支付可以生成一个推送码,需要保存到数据库或者缓存里,并且每个码只能推送3条消息
因为消息队列的消费在消息量大的时候具有一定的延时,这就为取消消息推送提供了可能,可以为每条消息生成一个唯一的uuid,取消的时候把这个uuid设计进redis里,推送时检查这个uuid是否在redis里决定推送与否
虽然推送存在不可控制的异常,比如三方推送服务出现了异常,但是也存在调用方传递参数异常,可以推送接口调用的返回值判断是否调用推送系统成功,也可以记录到日志里,这样在调查异常原因时就比较容易
上述就是小编为大家分享的怎么在spring boot中实现消息推送系统设计了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注创新互联行业资讯频道。