1.接口设计:主要是消息的接收体和必要的校验参数;
2.数模设计(MySQL):
建表语句如下:
CREATE TABLE `app_msg` (
`msg_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键:消息编号',
`msg_content` text NOT NULL COMMENT '消息内容',
`create_date_time` datetime NOT NULL COMMENT '消息创建时间',
`creater` bigint(20) unsigned NOT NULL COMMENT '消息创建人',
`modify_date_time` datetime DEFAULT NULL COMMENT '消息修改时间',
`modifier` bigint(20) unsigned DEFAULT NULL COMMENT '消息修改人ID',
`effective_start_time` datetime NOT NULL COMMENT '消息有效开始时间',
`effective_end_time` datetime NOT NULL COMMENT '消息有效结束时间',
`show_times` int(11) unsigned DEFAULT '0' COMMENT '通知时间间隔(单位:小时)',
`msg_title` varchar(32) NOT NULL DEFAULT '' COMMENT '消息标题名称',
`msg_type` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '消息通知类型:1 有效期内通知一次; 2 有效期内每次启动都通知;3 有效期内每隔n时间通知一次;',
PRIMARY KEY (`msg_id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='APP端弹窗消息体具体内容';
CREATE TABLE `app_msg_device_relation` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键:消息推送关系编号',
`msg_id` bigint(20) unsigned NOT NULL COMMENT '消息编号',
`device_id` varchar(64) NOT NULL COMMENT '推送设备编号',
`user_id` bigint(20) unsigned DEFAULT NULL COMMENT '推送用户编号',
`last_msg_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上次通知时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COMMENT='平台端设置的消息体推送到app端与用户及设备之间的关系';
3.接口代码实现:
-
AppMsgController逻辑:
/** * @Description: app端获取重要的通知信息 * @author * @date 2018年06月05日 14:31:38 * @param param * @return * */ @NoAuth @NoSignCheck @ResponseBody @RequestMapping(value = "getNoticeList", method = RequestMethod.POST) public Object getNoticeList(@RequestParam HashMap<String, Object> param) { Map<String, Object> returnMap=new HashMap<>(); List<Map<String, Object>> msgList=new ArrayList<Map<String, Object>>(); String errorMsg = ""; try { // 校验传参 if (StringUtil.isNullOrEmpty((String) param.get("userId")) || StringUtil.isNullOrEmpty((String) param.get("deviceId")) || StringUtil.isNullOrEmpty((String) param.get("cityName"))) { return MspAppResult.setFailedModelMap("参数传递错误", HttpCode.MOBILE_STATUS_PARAM_ERROR); } Long userId=Long.valueOf((String) param.get("userId")); String deviceId=(String) param.get("deviceId"); String cityName=(String) param.get("cityName"); //有效期内的通知消息列表处理 msgList=appMsgSerive.solveAppMsgList(userId,deviceId,cityName); } catch (BusinessException e) { log.error(e.getMessage(), e); return MspAppResult.setFailedModelMap(e.getMessage(), e.getHttpCode()); } catch (Exception e) { errorMsg = "查询通知消息异常"; log.error(errorMsg, e); return MspAppResult.setFailedModelMap(errorMsg, HttpCode.MOBILE_STATUS_EXCEPTION); } log.info("getNoticeList接口调用成功" ); //包装map returnMap.put("list",msgList); return MspAppResult.setSuccessModelMap(returnMap); }
-
AppMsgServiceImpl实现逻辑:
/** * @Description: 处理app通知消息逻辑 * @author * @date 2018年06月07日 19:05:08 * @param userId * @param deviceId * @return * */ @Override public List<Map<String, Object>> solveAppMsgList(Long userId, String deviceId,String cityName) { List<Map<String, Object>> returnList=new ArrayList<Map<String, Object>>(); List<AppMsgBO> addAppMsgBOList=new ArrayList<AppMsgBO>(); //1.查询有效期内的消息列表(不存在消息则直接返回空) AppMsgQueryBO queryBO=new AppMsgQueryBO(); queryBO.setNowDateTime(new Date()); List<AppMsgBO> appMsgLists=appMsgDao.queryEffictiveList(queryBO); if(null==appMsgLists){ log.error("查询有效期内的消息列表为空"); return returnList; } //拆分三种类型的消息列表 List<AppMsgBO> twoTypeList=getTypeList(CommonConstants.APP_MSG_TYPE_2,appMsgLists); List<AppMsgBO> threeTypeList=getTypeList(CommonConstants.APP_MSG_TYPE_3,appMsgLists); List<AppMsgBO> oneTypeList=getTypeList(CommonConstants.APP_MSG_TYPE_1,appMsgLists); //与设备相关,则查询该设备有效期内已通知的消息列表 List<AppMsgBO> deviceAppMsgLists=new ArrayList<AppMsgBO>(); if(!threeTypeList.isEmpty()||!oneTypeList.isEmpty()){ AppMsgQueryBO queryEfBo=new AppMsgQueryBO(); //如果是多条同时通知,则根据msgId来查询 if(appMsgLists.size()>1){ List<Long>msgIds=new ArrayList<>(appMsgLists.size()); for(AppMsgBO ao:appMsgLists){ msgIds.add(ao.getMsgId()); } queryEfBo.setMsgIds(msgIds); } queryEfBo.setNowDateTime(new Date()); queryEfBo.setDeviceId(deviceId); deviceAppMsgLists=appMsgDao.queryDeviceEffictiveList(queryEfBo); } //2.有效期内每次启动都通知;(跟设备无关系) if(!twoTypeList.isEmpty()){ //未通知消息集合 List<AppMsgBO> unMsgList=getUnMsgList(twoTypeList,null,CommonConstants.APP_MSG_TYPE_2); //批量返回消息通知 returnList.addAll(getReturnAppMsg(unMsgList)); } //3.有效期内每隔n时间通知一次;(跟设备有关系,与时间间隔也有关系) if(!threeTypeList.isEmpty()){ List<AppMsgBO> threeDeviceTypeList=new ArrayList<>(); if(null!=deviceAppMsgLists&&deviceAppMsgLists.size()>0){ threeDeviceTypeList=getTypeList(CommonConstants.APP_MSG_TYPE_3,deviceAppMsgLists); } //未通知消息集合 List<AppMsgBO> unMsgList=getUnMsgList(threeTypeList,threeDeviceTypeList,CommonConstants.APP_MSG_TYPE_3); //批量返回消息通知(包括修改的部分) returnList.addAll(getReturnAppMsg(unMsgList)); //循环删除不需要通知的对象(去掉修改的部分) for(AppMsgBO bo:threeDeviceTypeList){ for(int i=unMsgList.size()-1;i>=0;i--){ if(Objects.equals(unMsgList.get(i).getMsgId(), bo.getMsgId())){ unMsgList.remove(unMsgList.get(i)); } } } //批量新增消息通知(已去掉修改的部分) addAppMsgBOList.addAll(unMsgList); } //4.有效期内通知一次;(与设备及其通知次数有关系) if(!oneTypeList.isEmpty()){ List<AppMsgBO> oneDeviceTypeList=null; if(null!=deviceAppMsgLists&&deviceAppMsgLists.size()>0){ oneDeviceTypeList=getTypeList(CommonConstants.APP_MSG_TYPE_1,deviceAppMsgLists); } //未通知消息集合 List<AppMsgBO> unMsgList=getUnMsgList(oneTypeList,oneDeviceTypeList,CommonConstants.APP_MSG_TYPE_1); //批量返回消息通知 returnList.addAll(getReturnAppMsg(unMsgList)); //批量新增消息通知 addAppMsgBOList.addAll(unMsgList); } //5.处理批量新增的消息 if(null!=addAppMsgBOList&&addAppMsgBOList.size()>0){ List<AppMsgDeviceRelation> adList=new ArrayList<AppMsgDeviceRelation>(addAppMsgBOList.size()); AppMsgDeviceRelation ar; for(AppMsgBO bo:addAppMsgBOList){ ar=new AppMsgDeviceRelation(); ar.setMsgId(bo.getMsgId()); ar.setDeviceId(deviceId); ar.setUserId(userId); ar.setLastMsgTime(new Date()); adList.add(ar); } appMsgDeviceRelationDao.insertBatchEntity(adList); } return returnList; }
/**
* @Description: 获取某个类型的list
* @author
* @date 2018年06月08日 15:13:11
* @param type
* @param list
* @return
*
*/
public List<AppMsgBO> getTypeList(Byte type,List<AppMsgBO> list){
List<AppMsgBO> newList=new ArrayList<>(list.size());
for (AppMsgBO bo:list){
if(Objects.equals(bo.getMsgType(),type)){
newList.add(bo);
}
}
return newList;
}
/**
* @Description: 获取未通知的信息列表
* @author
* @date 2018年06月08日 16:30:20
* @param allList 全部通知集合
* @param yesList 已通知集合
* @param msgType 通知类型
* @return
*
*/
public List<AppMsgBO> getUnMsgList(List<AppMsgBO> allList,List<AppMsgBO> yesList,Byte msgType){
//1.已通知集合为空,则全部为未通知
if(null==yesList){
return allList;
}
//2.获取未通知部分
List<AppMsgBO> addList=new ArrayList<>(yesList.size());//收集新增消息体集合
List<AppMsgBO> updateList=new ArrayList<>(yesList.size());//收集修改消息体集合
for (AppMsgBO all:allList){
for(AppMsgBO yes:yesList){
if(Objects.equals(yes.getMsgId(), all.getMsgId())){
addList.add(all);
updateList.add(yes);
}
}
}
if(!addList.isEmpty()){
//msgType=1时,获得未通知的部分
if(Objects.equals(msgType, CommonConstants.APP_MSG_TYPE_1)){
allList.removeAll(addList);
}
//msgType=3时获得已通知的部分即updateList(此处需批量修改间隔时间,注意:对间隔时间的部分要进行计算再决定是否通知)
if(Objects.equals(msgType, CommonConstants.APP_MSG_TYPE_3) &&!updateList.isEmpty()){
List<AppMsgDeviceRelation> upList=new ArrayList<AppMsgDeviceRelation>(updateList.size());
AppMsgDeviceRelation ar;
for(AppMsgBO bo:updateList){
if(System.currentTimeMillis()-bo.getLastMsgTime().getTime()>=bo.getShowTimes()*60*60*1000){
ar=new AppMsgDeviceRelation();
ar.setId(bo.getId());
ar.setLastMsgTime(new Date());
upList.add(ar);
}else{
//循环删除不需要通知的对象
for(int i=allList.size()-1;i>=0;i--){
if(Objects.equals(allList.get(i).getMsgId(), bo.getMsgId())){
allList.remove(allList.get(i));
}
}
}
}
//批量更新时间
if(!upList.isEmpty()){
appMsgDeviceRelationDao.updateBatchEntity(upList);
}
}
}
return allList;
}
/**
* @Description: 封装返回结果
* @author
* @date 2018年06月08日 16:17:06
* @param list
* @return
*
*/
public List<Map<String, Object>> getReturnAppMsg(List<AppMsgBO> list){
List<Map<String, Object>> returnList=new ArrayList<Map<String, Object>>();
Map<String, Object> returnMap;
for(AppMsgBO bo:list){
returnMap=new HashMap<>(3);
returnMap.put("title",bo.getMsgTitle());
returnMap.put("content",bo.getMsgContent());
returnMap.put("noticeId",bo.getMsgId());
returnList.add(returnMap);
}
return returnList;
}
4.mybatis对应的文件:
- AppMsgDeviceRelationMapper.xml文件部分:
<!-- 批量更新实体的部分字段 --> <update id="updateBatchEntity" parameterType="java.util.List"> update app_msg_device_relation <trim prefix="set" suffixOverrides=","> <trim prefix="last_msg_time =case" suffix="end,"> <foreach collection="list" item="item" index="index"> when id=#{item.id} then #{item.lastMsgTime} </foreach> </trim> </trim> where id in <foreach collection="list" index="index" item="item" separator="," open="(" close=")"> #{item.id,jdbcType=BIGINT} </foreach> </update> <!-- 批量新增实体关系 --> <insert id="insertBatchEntity" parameterType="list"> INSERT INTO app_msg_device_relation (msg_id, device_id, user_id, last_msg_time) VALUES <foreach collection="list" item="re" index="index" separator=","> (#{re.msgId,jdbcType=BIGINT}, #{re.deviceId,jdbcType=VARCHAR}, #{re.userId,jdbcType=BIGINT}, #{re.lastMsgTime,jdbcType=TIMESTAMP}) </foreach> </insert>
- AppMsgMapper.xml部分内容:
<!--根据条件查询当前有效期内的消息通知列表(目前只取最新的一条)--> <select id="queryEffictiveList" parameterType="com.hikvision.bo.AppMsgQueryBO" resultType="com.hikvision.bo.AppMsgBO"> SELECT <include refid="Base_Column_List"/> , <include refid="Blob_Column_List"/> FROM app_msg WHERE #{nowDateTime} BETWEEN effective_start_time AND effective_end_time ORDER BY create_date_time DESC,effective_end_time DESC LIMIT 1 </select> <!--根据条件查询设备有效期内的消息通知列表--> <select id="queryDeviceEffictiveList" parameterType="com.hikvision.bo.AppMsgQueryBO" resultType="com.hikvision.bo.AppMsgBO"> SELECT a.id,a.device_id,a.user_id,a.last_msg_time, b.msg_id,b.effective_start_time,b.effective_end_time,b.msg_title,b.msg_content,b.msg_type,b.show_times FROM app_msg_device_relation a,app_msg b WHERE a.msg_id=b.msg_id AND #{nowDateTime} BETWEEN b.effective_start_time AND b.effective_end_time AND a.device_id = #{deviceId,jdbcType=VARCHAR} <if test="msgIds != null and msgIds.size()>0 "> AND a.msg_id in <foreach collection="msgIds" index="index" item="item" separator="," open="(" close=")"> #{item,jdbcType=BIGINT} </foreach> </if> ORDER BY b.create_date_time DESC,b.effective_end_time DESC </select>
5.web端配置效果图: