diff --git a/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java b/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java index f9d6cc5..ca5b097 100644 --- a/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java +++ b/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java @@ -40,6 +40,10 @@ public class WebSocketUtil implements WebSocketHandler { @Autowired private OprMemDictMapper oprMemDictMapper; + private int heartbeatMin = 1; // 断连最小心跳次数 + private int heartbeatMax = 3; // 断连最大心跳次数 + private int reconnectionSeconds = 60; //每次断连间隔重新连接秒 + /** * 存放建立连接webSocket对象 */ @@ -58,14 +62,13 @@ public class WebSocketUtil implements WebSocketHandler { Long id = Long.valueOf(params.split("=")[1]); if(null != webSocketMap && webSocketMap.get(id) != null) { if(webSocketMap.get(id).isOpen()) { - /* - 相同账户进行挤号,发送消息给前者WebSocket通知账户已在其他地方登录 - */ + /* 相同账户进行挤号,发送消息给WebSocket通知账户已在其他地方登录 */ webSocketMap.get(id).sendMessage(new TextMessage(JSONObject.toJSONString(ResponseData.generateCreatedResponse(1011)))); webSocketMap.get(id).close(); } else { /* - * 如果上次连接的WebSocket状态是关闭,并且上一次记录时间大于60秒的,则判断为这次登陆是免密码登陆的重新记录上线时间 + * 如果上次连接的WebSocket状态是关闭, + * 并且上一次记录时间大于 { heartbeatMax * reconnectionSeconds } 秒(心跳检测机制),则判断为这次登陆是免密码登陆的重新记录上线时间 */ List list = oprMemDictMapper.selectList(new QueryWrapper() .lambda() @@ -74,7 +77,7 @@ public class WebSocketUtil implements WebSocketHandler { Calendar calendar = Calendar.getInstance(); calendar.setTime(DateFormatUtil.localDateTimeToDate(list.get(0).getCreateDate())); - calendar.add(Calendar.SECOND,60); + calendar.add(Calendar.SECOND,heartbeatMax * reconnectionSeconds); if(calendar.getTime().after(DateFormatUtil.localDateTimeToDate(list.get(0).getCreateDate()))) { if(list.get(0).getOprType().equals("登出")) { OprMemDictDO oprMemDictDO = new OprMemDictDO(); @@ -127,9 +130,6 @@ public class WebSocketUtil implements WebSocketHandler { @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception{ if(null != session) { - /* - 断开连接后不会马上判断为下线状态,而是进入60秒的心跳检测机制,如果60秒内没有进行重连,则判断为下线,记录下线时间和状态 - */ if(null != webSocketMap) { String params = session.getUri().getQuery(); Long id = Long.valueOf(params.split("=")[1]); @@ -141,29 +141,36 @@ public class WebSocketUtil implements WebSocketHandler { } /** - * 断开连接后60秒后进行判断是否重新连接了,如果没有连接成功则判断为下线 + * 断开连接后进行三次心跳验证判断是否重新连接了,如果没有连接成功则判断为下线 * * @param session */ public void heartbeat(WebSocketSession session) { ScheduledExecutorService service = Executors.newScheduledThreadPool(1); ScheduledFuture scheduledFuture = service.scheduleAtFixedRate(new Runnable() { + int beatsNum = heartbeatMin; @SneakyThrows @Override public void run() { if(null != session && !session.isOpen()) { - String params = session.getUri().getQuery(); - Long id = Long.valueOf(params.split("=")[1]); - OprMemDictDO oprMemDictDO = new OprMemDictDO(); - oprMemDictDO.setUserId(id); - oprMemDictDO.setResult(1); - oprMemDictDO.setOprType("登出"); - oprMemDictDO.setIpAddress(session.getRemoteAddress().getHostName()); - oprMemDictMapper.insert(oprMemDictDO); + while (beatsNum > heartbeatMax) { + String params = session.getUri().getQuery(); + Long id = Long.valueOf(params.split("=")[1]); + OprMemDictDO oprMemDictDO = new OprMemDictDO(); + oprMemDictDO.setUserId(id); + oprMemDictDO.setResult(1); + oprMemDictDO.setOprType("登出"); + oprMemDictDO.setIpAddress(session.getRemoteAddress().getHostName()); + oprMemDictMapper.insert(oprMemDictDO); + taskMap.get(session.getId()).cancel(true); + } + beatsNum++; + } else if (null != session && session.isOpen()) { + /* 时间段内重新连接了结束验证 */ taskMap.get(session.getId()).cancel(true); } } - }, 1, 1, TimeUnit.MINUTES); + }, 0, reconnectionSeconds, TimeUnit.SECONDS); taskMap.put(session.getId(), scheduledFuture); }