package com.izouma.meta.websocket; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.izouma.meta.config.Constants; import com.izouma.meta.domain.MetaEmail; import com.izouma.meta.domain.MetaEmailRecord; import com.izouma.meta.domain.MetaSwitch; import com.izouma.meta.dto.PublicScreenChatExceptionMsg; import com.izouma.meta.repo.MetaEmailRecordRepo; import com.izouma.meta.repo.MetaEmailRepo; import com.izouma.meta.repo.MetaSwitchRepo; import com.izouma.meta.repo.MetaZouMaLightRepo; import com.izouma.meta.utils.ApplicationContextUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Service; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @Service @ServerEndpoint(value = "/websocket/{userId}") @Slf4j public class WebSocket { /** * 当前在线的客户端map */ private static final Map clients = new ConcurrentHashMap(); private WebsocketCommon websocketCommon; private MetaEmailRepo metaEmailRepo; private MetaEmailRecordRepo metaEmailRecordRepo; private MetaZouMaLightRepo metaZouMaLightRepo; private MetaSwitchRepo metaSwitchRepo; private void init() { if (Objects.isNull(websocketCommon)) { websocketCommon = (WebsocketCommon) ApplicationContextUtil.getBean("websocketCommon"); } if (Objects.isNull(metaEmailRepo)) { metaEmailRepo = (MetaEmailRepo) ApplicationContextUtil.getBean("metaEmailRepo"); } if (Objects.isNull(metaEmailRecordRepo)) { metaEmailRecordRepo = (MetaEmailRecordRepo) ApplicationContextUtil.getBean("metaEmailRecordRepo"); } if (Objects.isNull(metaZouMaLightRepo)) { metaZouMaLightRepo = (MetaZouMaLightRepo) ApplicationContextUtil.getBean("metaZouMaLightRepo"); } if (Objects.isNull(metaSwitchRepo)) { metaSwitchRepo = (MetaSwitchRepo) ApplicationContextUtil.getBean("metaSwitchRepo"); } } @OnOpen public void onOpen(@PathParam("userId") String userId, Session session) { init(); // 判断当前玩家是否在其他地方登陆 if (clients.containsKey(userId)) { String msg = String.format("已在别处登陆,sessionId为[%S],正在为您关闭本连接", session.getId()); exceptionHandle(userId, new PublicScreenChatExceptionMsg(1, msg)); try { log.info("关闭session连接"); clients.get(userId).close(); } catch (Exception e) { exceptionHandle(userId, new PublicScreenChatExceptionMsg(1, String.format("session close throw exception[%S]", e))); return; } } log.info("现在来连接的sessionId:" + session.getId() + "玩家id:" + userId); clients.put(userId, session); MetaSwitch metaSwitchFire = metaSwitchRepo.findByNameAndDel(Constants.META_WEBSOCKET_NOTICE_FIRE, false); if (Objects.isNull(metaSwitchFire)) { return; } if (metaSwitchFire.isStatus()) { websocketCommon.sendMessageTo(clients, Constants.META_WEBSOCKET_NOTICE_FIRE_OPEN, userId); } MetaSwitch metaSwitchLive = metaSwitchRepo.findByNameAndDel(Constants.META_WEBSOCKET_NOTICE_LIVE, false); if (Objects.isNull(metaSwitchLive)) { return; } if (metaSwitchLive.isStatus()) { websocketCommon.sendMessageTo(clients, Constants.META_WEBSOCKET_NOTICE_LIVE_OPEN, userId); } } @OnError public void onError(Session session, Throwable error) { // 异常处理 error.printStackTrace(); log.error(String.format("sessionId[%S]的服务端发生了错误:[%S]", session.getId(), error)); } @OnClose public void onClose(@PathParam("userId") String userId, Session session) { log.info(String.format("关闭session[%S]连接", session.getId())); clients.remove(userId); } @OnMessage public void onMessage(@PathParam("userId") String userId, String message, Session session) { init(); if (StringUtils.isBlank(message)) { log.error("Illegal parameter : message can not be null"); return; } if (Constants.HEART_RECEIVE.equals(message)) { log.info(String.format("sessionId:[%S] userId:[%S] 连接正常", session.getId(), userId)); websocketCommon.sendMessageTo(clients, Constants.HEART_RETURN, userId); return; } JSONObject jsonObject = JSON.parseObject(message); String type = jsonObject.getString("type"); log.info("来自客户端消息:" + message + "客户端的id是:" + session.getId()); switch (type) { case Constants.META_WEBSOCKET_NOTICE_EMAIL_NOTICE: log.info("新邮件通知"); websocketCommon.sendMessageToOther(clients, Constants.META_WEBSOCKET_NOTICE_EMAIL_NOTICE, userId); break; case Constants.META_WEBSOCKET_NOTICE_EMAIL: log.info("查询邮件"); try { List metaEmails = queryEmail(Long.parseLong(userId)); websocketCommon.sendMessageTo(clients, CollectionUtils.isNotEmpty(metaEmails) ? JSON.toJSONString(metaEmails) : JSON.toJSONString(new ArrayList<>()), userId); } catch (Exception e) { log.error(String.format("查询邮件失败,错误信息[%S]", e.getMessage())); } break; case Constants.META_WEBSOCKET_NOTICE_EMAIL_READ: log.info("读取邮件"); try { Long emailId = Long.parseLong(jsonObject.getString("value")); metaEmailRecordRepo.save(new MetaEmailRecord(Long.parseLong(userId), emailId, false, true)); } catch (Exception e) { log.error(String.format("读取邮件失败,错误信息[%S]", e.getMessage())); } break; case Constants.META_WEBSOCKET_NOTICE_EMAIL_DEL: log.info("删除邮件"); try { Long emailId = Long.parseLong(jsonObject.getString("value")); delEmail(Long.parseLong(userId), emailId); } catch (Exception e) { log.error(String.format("读取邮件失败,错误信息[%S]", e.getMessage())); } break; case Constants.META_WEBSOCKET_NOTICE_ZOU_MA_LIGHT_NOTICE: log.info("走马灯更新通知"); websocketCommon.sendMessageToOther(clients, Constants.META_WEBSOCKET_NOTICE_ZOU_MA_LIGHT_NOTICE, userId); break; case Constants.META_WEBSOCKET_NOTICE_ZOU_MA_LIGHT: log.info("查询走马灯"); String description = metaZouMaLightRepo.findDescriptionByPublishAndDel(true, false); if (StringUtils.isNotBlank(description)) { websocketCommon.sendMessageToOther(clients, description, userId); } break; case Constants.META_WEBSOCKET_NOTICE_FIRE_OPEN: log.info("烟花开启"); websocketCommon.sendMessageToOther(clients, Constants.META_WEBSOCKET_NOTICE_FIRE_OPEN, userId); break; case Constants.META_WEBSOCKET_NOTICE_FIRE_CLOSE: log.info("烟花关闭"); websocketCommon.sendMessageToOther(clients, Constants.META_WEBSOCKET_NOTICE_FIRE_CLOSE, userId); break; case Constants.META_WEBSOCKET_NOTICE_LIVE_OPEN: log.info("直播开启"); websocketCommon.sendMessageToOther(clients, Constants.META_WEBSOCKET_NOTICE_LIVE_OPEN, userId); break; case Constants.META_WEBSOCKET_NOTICE_LIVE_CLOSE: log.info("直播关闭"); websocketCommon.sendMessageToOther(clients, Constants.META_WEBSOCKET_NOTICE_LIVE_CLOSE, userId); break; default: log.error(String.format("不支持的类型[%S]", type)); } } /** * 查询未删除邮件 * * @param userId 用户id * @return 未删除邮件 */ private List queryEmail(Long userId) { init(); List delIds = metaEmailRecordRepo.findEmailIdByDel(userId, true); List metaEmails; metaEmails = CollectionUtils.isEmpty(delIds) ? metaEmailRepo.findAllByPublishAndDel(true, false) : metaEmailRepo.findAllByPublishAndDelAndIdNotIn(true, false, delIds); if (CollectionUtils.isEmpty(metaEmails)) { return metaEmails; } List readIds = metaEmailRecordRepo.findEmailIdRead(userId, true); if (CollectionUtils.isEmpty(readIds)) { return metaEmails; } metaEmails.forEach(metaEmail -> { if (readIds.contains(metaEmail.getId())) { metaEmail.setRead(true); } }); return metaEmails; } /** * 删除邮件 * * @param userId 用户id * @param emailId 邮件id */ private void delEmail(Long userId, Long emailId) { MetaEmailRecord metaEmailRecord = metaEmailRecordRepo.findByUserIdAndEmailId(userId, emailId); if (Objects.isNull(metaEmailRecord)) { metaEmailRecordRepo.save(new MetaEmailRecord(userId, emailId, true, true)); return; } metaEmailRecord.setEmailDel(true); metaEmailRecordRepo.save(metaEmailRecord); } private void exceptionHandle(String userId, PublicScreenChatExceptionMsg msg) { log.error(JSON.toJSONString(msg)); // 推送消息给该玩家 websocketCommon.sendMessageTo(clients, JSON.toJSONString(msg), userId); } }