场景:小程序中有一场直播,需要在开播前十五分钟提醒订阅的用户距离开播还有十五分钟,在开播时提醒一条直播已开始的消息。
注意:
第一:在开始直播时通知的消息是主播在直播控制平台点击一个推送按钮,订阅的用户即可收到来自服务号的通知消息,这个消息是微信官方发送的。
第二:微信官方提供的发送订阅消息的API只能给某一个用户发送,如果想要给所有订阅的用户发送,需要循环调用方法。
第三:开播前十五分钟提醒所有用户,这个需要后端来处理,需要注意的是记录所有的用户的openId
思路:
第一:在前端弹出一个授权信息的弹框,让用户订阅这场直播
第二:后端需要将用户的openId记录下来,提供一个接口判断用户是否订阅了,并且订阅的时候是否在开播前十五分钟完成的,如果没有订阅,弹出授权订阅信息的弹框,如果订阅了,但是订阅的时间在距离开播的十五分钟之内,就不需要弹出弹框,如果订阅且订阅时间距离开播大于十五分钟则出发定时任务,在十五分钟时发送消息。
第三:在开播前十五分钟时设置一个定时任务发送订阅消息。
难点:记录用户的openId,提供两种方法(当然,会有其他方法,欢迎补充)
第一:直接在数据库建立一张表,存放所有的openId
第二:将用户的openId存放到redis中,这里也提供两种方法。
一种:使用序列化和反序列化,将用户的openId存到redis,使用string类型
代码如下:
public void setOpenIdToRedis(@PathVariable String openId) throws IOException {
String openIdsJson = (String)redisTemplate.opsForValue().get("openIds");
List<String> openIds = null;
if(TextUtils.isEmpty(openIdsJson)){
openIds = new ArrayList<>();
}else{
openIds = objectMapper.readValue(openIdsJson,new TypeReference<List<String>>() {});
}
if(!openIds.contains(openId)){
openIds.add(openId);
}
redisTemplate.opsForValue().set("openIds",objectMapper.writeValueAsString(openIds));
}
这里先反序列化一个字符串,转成对象,使用了一个内部匿名类将openIdsJson的JSONObject转化为list<string>对象。在存放时序列化,将对象转换成字符串存到redis中。
查看redis中openIds存储的类型:
二种:使用set集合(无序,不重复)
存放:
SetOperations<String, String> set = redisTemplate.opsForSet();
set.add("set1", openId);
redisTemplate.opsForSet().members("set1");
取出:
Set<String> resultSet =redisTemplate.opsForSet().members("set1");
for (String s:resultSet){
System.out.println(s);
}
判断是否存在redis:
Boolean flag = redisTemplate.opsForSet().isMember("openIds", openId);
在redis中查看:
其他的就没有什么难的,正常的业务处理就行。