likes
comments
collection
share

【实践】Springboot引入消息推送

作者站长头像
站长
· 阅读数 15

消息推送

什么叫消息推送?

现在很多手机APP会不定时的给用户推送消息,例如一些新闻APP会给用户推送用户可能感兴趣的新闻,或者APP有更新了,会给用户推送是否选择更新的消息。点击这条消息就会跳转到对应的APP页面,不点还一直有“小红点”提示等等,这就是消息推送,有时候就会考虑这个推送消息的功能怎样能实现,现在可以通过对接第三方来简单的实现这一功能。

市面上很多推送平台,其中极光推送的对接过程如下:

JPush 是经过考验的大规模 App 推送平台,每天推送消息量级为数百亿条。 开发者集成 SDK 后,可以通过调用 API 推送消息。同时,JPush 提供可视化的 web 端控制台发送通知,统计分析推送效果。 JPush 全面支持 Android, iOS, Winphone 三大手机平台。

准备

  • 登录极光官网:www.jiguang.cn/
  • 注册账号
  • 选择开发者服务
  • 点极光推送,进入后创建一个应用
  • 选择创建的应用,获取AppKey和Master Secret

【实践】Springboot引入消息推送

整合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…