package com.qxueyou.scc.msg.service.impl; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; import org.springframework.stereotype.Service; import com.qxueyou.scc.base.model.Result; import com.qxueyou.scc.base.service.ICacheService; import com.qxueyou.scc.msg.model.MsgChatroomMsg; import com.qxueyou.scc.msg.service.IChatroomMsgService; @Service public class ChatroomMessageBean implements IChatroomMsgService { @Autowired ICacheService redis; private static final int PAGE_SIZE = 20; private static final String CACHEKEY_MSG_QUEUE = "msg_chatroom_msg_"; // 实时消息队列 private static final String CACHEKEY_MESSAGE_A_COUNT = "msg_chatroom_message_count_"; // A类消息总数 private static final String CACHEKEY_MESSAGE_HISTORY = "msg_chatroom_msg_history_"; //历史消息 private static final String CACHEKEY_ONLINE_COUNT = "msg_chatroom_online_count_"; // 在线人数 private static final String CACHEKEY_PRAISE_COUNT = "msg_chatroom_praise_count_"; // 点赞数 private static final String CACHEKEY_LOTTERY_COUNT = "msg_chatroom_lottery_count_"; // 签到数 private static final String CACHEKEY_VIEW_COUNT = "msg_chatroom_view_count_"; // 浏览数 private static final String CACHEKEY_LOTTERY_RESULT_COUNT = "msg_chatroom_lottery_result_count_"; //中奖结果 private static final String CACHEKEY_REWARD_COUNT = "msg_chatroom_reward_count_"; //打赏次数 private static final String CACHEKEY_CONSULT_COUNT = "msg_chatroom_consult_count_"; //咨询次数 private static final String CACHEKEY_REWARD_AMOUNT = "msg_chatroom_reward_amount_"; //打赏金额 /** * 发送消息 */ @Override public Result doSendMessage(String chatroomId, String senderId, String imgPath, String alias, String content, Integer type, String userType) { MsgChatroomMsg mes = new MsgChatroomMsg(); mes.setMsgId(redis.incr("ChatroomMsgId")); mes.setChatroomId(chatroomId); mes.setSenderId(senderId); mes.setContent(content); mes.setType(type); mes.setAlias(alias); mes.setUserType(userType); mes.setImgPath(imgPath); mes.setCreateTime(new Date()); //缓存消息 this.msgCache(chatroomId, mes); this.msgTypeCountCache(chatroomId, type); return new Result(true, null, mes); } /** * 聊天消息剪切, * * @param chatroomId */ @Deprecated private void msgListTrim(String key, String chatroomId){ List mesList = redis.lstRange(key, 0l, -1l); if(mesList != null && !mesList.isEmpty()){ if(mesList.size() <= PAGE_SIZE){ return; } long index = 0; long time = System.currentTimeMillis(); for(MsgChatroomMsg msg : mesList){ if(time - msg.getCreateTime().getTime()<= 10000){ break; } index ++; } //保留20条 redis.lstTrim(key, mesList.size() - index <= 20?mesList.size()-20:index, -1l); } } /** * 缓存消息 * * @param chatroomId * @param mes */ private void msgCache(String chatroomId, MsgChatroomMsg mes){ String key = CACHEKEY_MSG_QUEUE + chatroomId; //先获取10秒内的数据 // this.msgListTrim(key, chatroomId); // List mesList = redis.lstRange(key, 0l, -1l); //获取PAGE_SIZE条以内的消息 List mesList= redis.lstRange(key, 0l, PAGE_SIZE); //最近20消息过滤重复的点赞,进入,退出 if((MsgChatroomMsg.TYPE_PRAISE == mes.getType() || MsgChatroomMsg.TYPE_ENTER == mes.getType() || MsgChatroomMsg.TYPE_EXIT == mes.getType()) && mesList.contains(mes)){ return; } redis.lstRightPush(key, mes); redis.expire(key, 360, TimeUnit.DAYS); } /** * 计数器 * * @param chatroomId * @param type */ private void msgTypeCountCache(String chatroomId, Integer type){ if(type == MsgChatroomMsg.TYPE_ENTER){//在线人数加一 redis.incr(CACHEKEY_ONLINE_COUNT + chatroomId); redis.expire(CACHEKEY_ONLINE_COUNT + chatroomId, 360, TimeUnit.DAYS); } if(type == MsgChatroomMsg.TYPE_ENTER || type == MsgChatroomMsg.TYPE_PRAISE || type == MsgChatroomMsg.TYPE_LOTTERY || type == MsgChatroomMsg.TYPE_REWARD || type == MsgChatroomMsg.TYPE_CONSULT || type == MsgChatroomMsg.TYPE_LOTTERY_RESULT){ redis.incr(this.getKey(chatroomId, type)); redis.expire(this.getKey(chatroomId, type), 360, TimeUnit.DAYS); }else if(type == MsgChatroomMsg.TYPE_EXIT){//在线人数减一 String key = CACHEKEY_ONLINE_COUNT + chatroomId; Long value = redis.getIncrValue(key); if(value.compareTo(0l)>0){ redis.decr(key); } redis.expire(key, 360, TimeUnit.DAYS); }else if(type == MsgChatroomMsg.TYPE_NORMAL || type == MsgChatroomMsg.TYPE_LOTTERY_RESULT){//A类消息计数器 redis.incr(CACHEKEY_MESSAGE_A_COUNT + chatroomId); redis.expire(CACHEKEY_MESSAGE_A_COUNT + chatroomId, 360, TimeUnit.DAYS); } } //获取缓存key值 private String getKey(String chatroomId, Integer type){ String key = ""; switch(type){ case MsgChatroomMsg.TYPE_PRAISE: key = CACHEKEY_PRAISE_COUNT + chatroomId; break; case MsgChatroomMsg.TYPE_LOTTERY: key = CACHEKEY_LOTTERY_COUNT + chatroomId; break; case MsgChatroomMsg.TYPE_ENTER: key = CACHEKEY_VIEW_COUNT + chatroomId; break; case MsgChatroomMsg.TYPE_REWARD: key = CACHEKEY_REWARD_COUNT + chatroomId; break; case MsgChatroomMsg.TYPE_CONSULT: key = CACHEKEY_CONSULT_COUNT + chatroomId; break; case MsgChatroomMsg.TYPE_LOTTERY_RESULT: key = CACHEKEY_LOTTERY_RESULT_COUNT + chatroomId; break; default: key = ""; } return key; } /** * 轮询 * * @param chatroomId * @throws Exception */ @Override public Result latestMsg(String chatroomId) { List mesList = redis.lstRange(CACHEKEY_MSG_QUEUE + chatroomId, 0l, -1l); //奖金总数 Long rewardAmount = redis.getIncrValue(CACHEKEY_REWARD_AMOUNT + chatroomId); Map data = new HashMap(); //统计数据 Map statistics = this.reStatistics(chatroomId); Integer maxPage = this.getMaxPage(chatroomId, String.valueOf(statistics.get("historyMsgCount"))); data.put("maxPage", maxPage); data.put("currentPage", maxPage); data.put("onlineCount", statistics.get("onlineCount")); data.put("praiseCount", statistics.get("praiseCount")); data.put("viewCount", statistics.get("viewCount")); data.put("lotteryCount", statistics.get("lotteryCount")); data.put("rewardCount", statistics.get("rewardCount")); data.put("consultCount", statistics.get("consultCount")); data.put("rewardAmount", rewardAmount); data.put("dataList", mesList); data.put("serverTime", new Date()); return new Result(true, null, data); } /** * 获取浏览人次 * @param chatroomId * @throws Exception */ @Override public Long getViewCount(String chatroomId){ return redis.getIncrValue(CACHEKEY_VIEW_COUNT + chatroomId); } /** * 重新统计数据,读取数据库 * * @param type * @param statistics * @return */ private Map reStatistics(String chatroomId){ Long msgCount = nul2Zero(redis.getIncrValue(CACHEKEY_MESSAGE_A_COUNT + chatroomId)); Long onlineCount = nul2Zero(redis.getIncrValue(CACHEKEY_ONLINE_COUNT + chatroomId)); Long praiseCount = nul2Zero(redis.getIncrValue(CACHEKEY_PRAISE_COUNT + chatroomId)); Long lotteryCount = nul2Zero(redis.getIncrValue(CACHEKEY_LOTTERY_COUNT + chatroomId)); Long viewCount = nul2Zero(redis.getIncrValue(CACHEKEY_VIEW_COUNT + chatroomId)); Long rewardCount = nul2Zero(redis.getIncrValue(CACHEKEY_REWARD_COUNT + chatroomId)); Long lotteryResultCount = nul2Zero(redis.getIncrValue(CACHEKEY_LOTTERY_RESULT_COUNT + chatroomId)); Long consultCount = nul2Zero(redis.getIncrValue(CACHEKEY_CONSULT_COUNT + chatroomId)); Map result = new HashMap<>(); result.put("msgCount", msgCount); //历史消息数量,正常消息、中奖消息,打赏消息 result.put("historyMsgCount", msgCount+lotteryResultCount+rewardCount); result.put("onlineCount", onlineCount); result.put("praiseCount", praiseCount); result.put("lotteryCount", lotteryCount); result.put("viewCount", viewCount); result.put("rewardCount", rewardCount); result.put("consultCount", consultCount); return result; } private Long nul2Zero(Long value) { if(value==null) { return 0l; } return value; } /** * 按页获取历史消息 */ @Override public Result getHistoryMes(String chatroomId, Integer pageNo) { //统计数据 List mesList = redis.lstRange(CACHEKEY_MSG_QUEUE + chatroomId, 0l, -1l); Map statistics = this.reStatistics(chatroomId); Integer maxPage = getMaxPage(chatroomId, String.valueOf(statistics.get("historyMsgCount")+mesList.size())); String key = CACHEKEY_MESSAGE_HISTORY + chatroomId+ "_" + pageNo; if (StringUtils.isEmpty(chatroomId) || pageNo == null || pageNo > maxPage) { return new Result(false, "参数错误"); } List msgList = redis.lstAll(key); msgList = this.distinct(msgList, chatroomId); Map data = new HashMap<>(); data.put("currentPage", pageNo); data.put("maxPage", maxPage); data.put("dataList", msgList); return new Result(true, null, data); } /** * 去除重复消息 * * @return */ private List distinct(List historyMsgList, String chatroomId){ List lastMsgList = redis.lstRange(CACHEKEY_MSG_QUEUE + chatroomId, 0l, -1l); if(historyMsgList != null && !historyMsgList.isEmpty() && lastMsgList != null && !lastMsgList.isEmpty()){ for(int i=historyMsgList.size()-1;i>= 0;i--){ MsgChatroomMsg historyMsgChatroomMsg = historyMsgList.get(i); for(MsgChatroomMsg lastMsgChatroomMsg : lastMsgList){ if(historyMsgChatroomMsg.getMsgId().equals(lastMsgChatroomMsg.getMsgId())){ historyMsgList.remove(i); break; } } } } return historyMsgList; } /** * 获取A类消息最大页码 * * @param chatroomId * @return */ public Integer getMaxPage(String chatroomId, String msgCount) { Integer count = Integer.valueOf(msgCount); int maxPage = count % PAGE_SIZE == 0 ? count / PAGE_SIZE : count / PAGE_SIZE + 1; return maxPage; } }