【实践】Springboot引入消息推送
消息推送
什么叫消息推送?
现在很多手机APP会不定时的给用户推送消息,例如一些新闻APP会给用户推送用户可能感兴趣的新闻,或者APP有更新了,会给用户推送是否选择更新的消息。点击这条消息就会跳转到对应的APP页面,不点还一直有“小红点”提示等等,这就是消息推送,有时候就会考虑这个推送消息的功能怎样能实现,现在可以通过对接第三方来简单的实现这一功能。
市面上很多推送平台,其中极光推送的对接过程如下:
JPush 是经过考验的大规模 App 推送平台,每天推送消息量级为数百亿条。 开发者集成 SDK 后,可以通过调用 API 推送消息。同时,JPush 提供可视化的 web 端控制台发送通知,统计分析推送效果。 JPush 全面支持 Android, iOS, Winphone 三大手机平台。
准备
- 登录极光官网:www.jiguang.cn/
- 注册账号
- 选择开发者服务
- 点极光推送,进入后创建一个应用
- 选择创建的应用,获取AppKey和Master Secret
整合SpringBoot
maven依赖
引入极光依赖
<!-- 极光推送依赖 -->
<dependency>
<groupId>cn.jpush.api</groupId>
<artifactId>jpush-client</artifactId>
<version>3.3.10</version>
</dependency>
<dependency>
<groupId>cn.jpush.api</groupId>
<artifactId>jiguang-common</artifactId>
<version>1.1.4</version>
</dependency>
工具类
创建JPushUtil类,该类中给出了使用与Android和ios的方法,以及两者都适用的方法,代码如下
@Slf4j
@Component
public class JPushUtil {
@Value(value="${jpush.appKey}")
private String appKey;
@Value(value="${jpush.masterSecret}")
private String masterSecret;
@Resource
private JpushFeign jpushFeign;
@Value(value = "${jpush.send.titleLimit:75}")
private Integer titleLimit;
@Value(value = "${jpush.send.contentLimit:150}")
private Integer contentLimit;
@Async
public void appSendPushWithCallback( List<String> registrationIds, MessageBodyVO2 request, String messageId, int sendno) {
try {
if (CollectionUtils.isEmpty(registrationIds)) {
log.info("推送registrationId集合为空!");
return;
}
PushModel pushModel = this.buildPushObject(registrationIds, request, messageId, sendno);
String authString = ServiceHelper.getBasicAuthorization(appKey, masterSecret);
log.info("推送:" + JSONObject.toJSONString(pushModel));
Map<String, Object> resultModel = jpushFeign.push(authString, JSONObject.parseObject(JSONObject.toJSONString(pushModel)));
log.info("回参: {}", JSONObject.toJSONString(resultModel));
}catch (Exception e){
log.error("消息发送失败!", e);
}
}
/**
*
* @param registrationIds 注册ID数组
* @param request 传入参数
* @param messageId 本地消息ID
* @param sendno 极光发送ID
*/
private PushModel buildPushObject(List<String> registrationIds, MessageBody request, String messageId, int sendno){
PushModel pushModel = new PushModel();
pushModel.setPlatform(Arrays.asList(PushConstans.JPUSH_PLATFORM_ALL));
//推送目标
AudienceModel audience = new AudienceModel();
audience.setRegistration_id(registrationIds);
pushModel.setAudience(audience);
AndroidModel android = new AndroidModel();
//安卓平台参数
android.setAlert(request.getLimitContent(contentLimit));
android.setTitle(request.getLimitTitle(titleLimit));
// 设置安卓跳转节点
Optional.ofNullable(((Map)(request.getPayload().get("android"))).get("uri_activity")).ifPresent(u->
android.setUri_activity(u.toString()));
Optional.ofNullable(((Map)(request.getPayload().get("android"))).get("uri_action")).ifPresent(u->
android.setUri_action(u.toString()));
//安卓扩展字段
JSONObject androidExtras = new JSONObject();
androidExtras.put("payload_protocol", MapUtils.getString(request.getPayload_protocol(), "type"));
androidExtras.put("message_id", messageId);
androidExtras.put("link_type", String.valueOf(request.getLink_type()));
androidExtras.put("uri", request.getUri());
android.setExtras(androidExtras);
//IOS平台参数
IosModel ios = new IosModel();
JSONObject alert = new JSONObject();
alert.put("title", request.getLimitTitle(titleLimit));
alert.put("body", request.getLimitContent(contentLimit));
ios.setAlert(alert);
ios.setBadge(1);
//ios扩展字段
JSONObject iosExtras = new JSONObject();
iosExtras.put("payload_protocol", MapUtils.getString(request.getPayload_protocol(), "type"));
iosExtras.put("message_id", messageId);
iosExtras.put("link_type", String.valueOf(request.getLink_type()));
iosExtras.put("uri", request.getUri());
ios.setExtras(iosExtras);
//消息通知
NotificationModel notification = new NotificationModel();
notification.setAndroid(android);
notification.setIos(ios);
pushModel.setNotification(notification);
//可选参数
OptionsModel options = new OptionsModel();
options.setSendno(sendno);
pushModel.setOptions(options);
return pushModel;
}
}
消息参数封装
@Getter
@Setter
public class MessageBody {
@NotBlank(message = "消息唯一标识不能为空!")
@ApiParam(value = "消息唯一标识", required = true)
private String sid;
@NotBlank(message = "推送平台不能为空!")
@ApiParam(value = "推送平台", required = true)
private String platform;
@NotBlank(message = "应用id不能为空!")
@ApiParam(value = "应用id", required = true)
private String appid;
@NotBlank(message = "项目名不能为空!")
@ApiParam(value = "项目名", required = true)
private String source;
@NotNull(message = "数据体协议不能为空!")
@ApiParam(value = "数据体协议", required = true)
private Map<String,Object> payload_protocol;
@NotNull(message = "发送方式不能为空!")
@ApiParam(value = "发送方式", required = true)
private Integer recipient_type;
@ApiParam(value = "用户", required = true)
private List<String> recipient;
@NotBlank(message = "应用id不能为空!")
@ApiParam(value = "标题", required = true)
private String title;
@NotBlank(message = "消息内容不能为空!")
@ApiParam(value = "消息内容", required = true)
private String content;
@ApiParam(value = "图片url", required = false)
private String picPath;
@ApiParam(value = "链接类型", required = true)
private Integer link_type;
@ApiParam(value = "App具体业务连接地址", required = true)
private String uri;
@ApiParam(value = "PC具体业务连接地址", required = true)
private String uri_pc;
@ApiParam(value = "自定义消息体", required = true)
private Map<String,Object> payload;
@ApiParam(value = "设置", required = false)
private Map<String,Object> options;
@ApiParam(value = "回调URL", required = false)
private String callback;
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {App.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TestJPush {
@Autowired
private JPushUtil jpushRestUtil;
@Test
public void test() {
List users = new ArrayList();
MessageBody request = new MessageBody();
request.setSid("56318723912");
request.setAppid("dqw1233132");
request.setContent("么么么么");
request.setTitle("标题");
request.setPicPath("img...");
jpushRestUtil.appSendPushWithCallback(users, request, "1", 1);
}
}
注意:title和content需要有内容,不然极光推送会失败
参数说明
关键字 | 选项 | 含义 |
---|---|---|
platform | 必填 | 推送平台设置 |
audience | 必填 | 推送设备指定 |
notification | 可选 | 通知内容体。是被推送到客户端的内容。与 message 一起二者必须有其一,可以二者并存 |
message | 可选 | 消息内容体。是被推送到客户端的内容。与 notification 一起二者必须有其一,可以二者并存 |
notification_3rd | 可选 | 自定义消息转厂商通知内容体。与 message 一起使用 |
sms_message | 可选 | 短信渠道补充送达内容体 |
options | 可选 | 推送参数 |
callback | 可选 | 回调参数 |
cid | 可选 | 用于防止 api 调用端重试造成服务端的重复推送而定义的一个标识符。 |
参考
极光推送文档:docs.jiguang.cn/jpush/serve…
转载自:https://juejin.cn/post/7020756233460285471