diff --git a/src/main/java/com/subsidy/common/configure/WebSocketConfig.java b/src/main/java/com/subsidy/common/configure/WebSocketConfig.java index 696db4b..277b1ba 100644 --- a/src/main/java/com/subsidy/common/configure/WebSocketConfig.java +++ b/src/main/java/com/subsidy/common/configure/WebSocketConfig.java @@ -3,10 +3,17 @@ package com.subsidy.common.configure; import com.subsidy.common.interceptor.WebSocketInterceptor; import com.subsidy.util.websocket.WebSocketUtil; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +import javax.servlet.http.HttpSession; +import javax.websocket.HandshakeResponse; +import javax.websocket.server.HandshakeRequest; +import javax.websocket.server.ServerEndpointConfig; /** *

@@ -18,7 +25,7 @@ import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry */ @Configuration @EnableWebSocket -public class WebSocketConfig implements WebSocketConfigurer { +public class WebSocketConfig extends ServerEndpointConfig.Configurator implements WebSocketConfigurer { @Autowired private WebSocketUtil webSocketUtil; @@ -33,4 +40,22 @@ public class WebSocketConfig implements WebSocketConfigurer { .addInterceptors(webSocketInterceptor) // 自定义验证规则 .setAllowedOrigins("*"); } + + + + @Override + public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { + HttpSession httpSession = (HttpSession)request.getHttpSession(); + if (httpSession != null) { + // 读取session域中存储的数据 + sec.getUserProperties().put(HttpSession.class.getName(),httpSession); + } + super.modifyHandshake(sec, request, response); + } + + @Bean + public ServerEndpointExporter serverEndpointExporter(){ + return new ServerEndpointExporter(); + } + } \ No newline at end of file diff --git a/src/main/java/com/subsidy/common/interceptor/AuthenticationInterceptor.java b/src/main/java/com/subsidy/common/interceptor/AuthenticationInterceptor.java index a86e689..f07d107 100644 --- a/src/main/java/com/subsidy/common/interceptor/AuthenticationInterceptor.java +++ b/src/main/java/com/subsidy/common/interceptor/AuthenticationInterceptor.java @@ -2,6 +2,7 @@ package com.subsidy.common.interceptor; import com.alibaba.fastjson.JSON; import com.auth0.jwt.interfaces.Claim; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.subsidy.common.ResponseData; import com.subsidy.common.ResponseVO; @@ -9,8 +10,10 @@ import com.subsidy.common.constant.Code; import com.subsidy.common.exception.HttpException; import com.subsidy.mapper.AdministerMapper; import com.subsidy.mapper.MemberMapper; +import com.subsidy.mapper.MemberTokensMapper; import com.subsidy.model.AdministerDO; import com.subsidy.model.MemberDO; +import com.subsidy.model.MemberTokensDO; import com.subsidy.util.ConstantUtils; import com.subsidy.util.JwtUtil; import com.subsidy.util.Localstorage; @@ -49,6 +52,9 @@ public class AuthenticationInterceptor implements HandlerInterceptor { @Autowired private MemberMapper memberMapper; + @Autowired + private MemberTokensMapper memberTokensMapper; + @Override @CrossOrigin() public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { @@ -60,14 +66,14 @@ public class AuthenticationInterceptor implements HandlerInterceptor { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); -// TimeRequired timeRequired = method.getAnnotation(TimeRequired.class); -// if (timeRequired !=null){ -// Calendar calendar = Calendar.getInstance(); -// int hour = calendar.get(Calendar.HOUR_OF_DAY); -// if (hour<6){ -// throw new HttpException(17001); -// } -// } + TimeRequired timeRequired = method.getAnnotation(TimeRequired.class); + if (timeRequired !=null){ + Calendar calendar = Calendar.getInstance(); + int hour = calendar.get(Calendar.HOUR_OF_DAY); + if (hour<6){ + throw new HttpException(17001); + } + } LoginRequired methodAnnotation = method.getAnnotation(LoginRequired.class); if (methodAnnotation != null) { @@ -98,6 +104,14 @@ public class AuthenticationInterceptor implements HandlerInterceptor { Localstorage.setUser(memberDO); return true; } + + int count = memberTokensMapper.selectCount(new QueryWrapper() + .lambda() + .eq(MemberTokensDO::getMemberId,memberDO.getId())); + if (count==0){ + throw new HttpException(1011); + } + /** * 学生端设置单设备登录 */ diff --git a/src/main/java/com/subsidy/controller/MemberController.java b/src/main/java/com/subsidy/controller/MemberController.java index cf76582..a2b841d 100644 --- a/src/main/java/com/subsidy/controller/MemberController.java +++ b/src/main/java/com/subsidy/controller/MemberController.java @@ -1,5 +1,6 @@ package com.subsidy.controller; +import com.alibaba.fastjson.JSON; import com.subsidy.common.ResponseData; import com.subsidy.common.ResponseVO; import com.subsidy.common.interceptor.LoginRequired; @@ -7,6 +8,7 @@ import com.subsidy.common.interceptor.TimeRequired; import com.subsidy.dto.administer.VerifyCodeDTO; import com.subsidy.dto.live.PolyvInfoDTO; import com.subsidy.dto.member.*; +import com.subsidy.dto.vod.InsertHistoryNewDTO; import com.subsidy.mapper.MemberMapper; import com.subsidy.model.ExerciseDoneResultDO; import com.subsidy.model.MemberDO; @@ -221,6 +223,13 @@ public class MemberController { return memberService.polyvInfo(userid,channelId,ts,token); } + @RequestMapping("logout") + @ApiOperation("登出 学生id") + @TimeRequired + public ResponseVO logout(@RequestBody String param){ + MemberDO memberDO = JSON.parseObject(param, MemberDO.class); + return ResponseData.generateCreatedResponse(0,memberService.logout(memberDO)); + } diff --git a/src/main/java/com/subsidy/controller/MemberTokensController.java b/src/main/java/com/subsidy/controller/MemberTokensController.java new file mode 100644 index 0000000..d83f0a0 --- /dev/null +++ b/src/main/java/com/subsidy/controller/MemberTokensController.java @@ -0,0 +1,22 @@ +package com.subsidy.controller; + + +import org.springframework.web.bind.annotation.RequestMapping; + +import org.springframework.web.bind.annotation.RestController; +import io.swagger.annotations.Api; + +/** + *

+ * 用户登录token 前端控制器 + *

+ * + * @author Tuyp + * @since 2023-01-06 + */ +@RestController +@Api(tags = "用户登录token") +@RequestMapping("/member-tokens-do") +public class MemberTokensController { + +} diff --git a/src/main/java/com/subsidy/mapper/MemberTokensMapper.java b/src/main/java/com/subsidy/mapper/MemberTokensMapper.java new file mode 100644 index 0000000..1b1c3ea --- /dev/null +++ b/src/main/java/com/subsidy/mapper/MemberTokensMapper.java @@ -0,0 +1,20 @@ +package com.subsidy.mapper; + +import com.subsidy.model.MemberTokensDO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +/** + *

+ * 用户登录token Mapper 接口 + *

+ * + * @author Tuyp + * @since 2023-01-06 + */ + @Repository +public interface MemberTokensMapper extends BaseMapper { + + void updateToken(Long memberId,String token); + +} diff --git a/src/main/java/com/subsidy/mapper/OprMemDictMapper.java b/src/main/java/com/subsidy/mapper/OprMemDictMapper.java index 9a11aeb..beb95d5 100644 --- a/src/main/java/com/subsidy/mapper/OprMemDictMapper.java +++ b/src/main/java/com/subsidy/mapper/OprMemDictMapper.java @@ -25,4 +25,6 @@ public interface OprMemDictMapper extends BaseMapper { OprMemDictDO getLatestLoginInfo(Long userId); + void deleteData(OprMemDictDO oprMemDictDO); + } diff --git a/src/main/java/com/subsidy/model/MemberTokensDO.java b/src/main/java/com/subsidy/model/MemberTokensDO.java new file mode 100644 index 0000000..5c9da32 --- /dev/null +++ b/src/main/java/com/subsidy/model/MemberTokensDO.java @@ -0,0 +1,36 @@ +package com.subsidy.model; + +import com.subsidy.util.BaseModel; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + *

+ * 用户登录token + *

+ * + * @author Tuyp + * @since 2023-01-06 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("member_tokens") +public class MemberTokensDO extends BaseModel { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + private Long memberId; + + /** + * 用户token + */ + private String token; + + +} diff --git a/src/main/java/com/subsidy/service/MemberService.java b/src/main/java/com/subsidy/service/MemberService.java index b73d0c1..a7c5a17 100644 --- a/src/main/java/com/subsidy/service/MemberService.java +++ b/src/main/java/com/subsidy/service/MemberService.java @@ -78,4 +78,6 @@ public interface MemberService extends IService { List memberLives(MemberDO memberDO); PolyvInfoVO polyvInfo(String userid,String channelId,String ts,String token); + + String logout(MemberDO memberDO); } diff --git a/src/main/java/com/subsidy/service/MemberTokensService.java b/src/main/java/com/subsidy/service/MemberTokensService.java new file mode 100644 index 0000000..cb9c2b6 --- /dev/null +++ b/src/main/java/com/subsidy/service/MemberTokensService.java @@ -0,0 +1,16 @@ +package com.subsidy.service; + +import com.subsidy.model.MemberTokensDO; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 用户登录token 服务类 + *

+ * + * @author Tuyp + * @since 2023-01-06 + */ +public interface MemberTokensService extends IService { + +} diff --git a/src/main/java/com/subsidy/service/impl/ImageCheckRecordServiceImpl.java b/src/main/java/com/subsidy/service/impl/ImageCheckRecordServiceImpl.java index 86bef7b..fc62438 100644 --- a/src/main/java/com/subsidy/service/impl/ImageCheckRecordServiceImpl.java +++ b/src/main/java/com/subsidy/service/impl/ImageCheckRecordServiceImpl.java @@ -254,7 +254,9 @@ public class ImageCheckRecordServiceImpl extends ServiceImpl() + .lambda() + .eq(ImageCheckRecordDO::getBizSeqNo,checkResultDTO.getId())); if (!StringUtils.isEmpty(resultVO.getSimilarity())) { BeanUtils.copyProperties(resultVO, imageCheckRecordDO); ActivityDetectionDO activityDetectionDO = new ActivityDetectionDO(); @@ -286,6 +288,7 @@ public class ImageCheckRecordServiceImpl extends ServiceImpl imple @Autowired private ActivityDetectionMapper activityDetectionMapper; + @Autowired + private MemberTokensMapper memberTokensMapper; + public IPage getAll(GetAllDTO getAllDTO) { Page pager = new Page(getAllDTO.getPageNum(), getAllDTO.getPageSize()); @@ -340,12 +343,15 @@ public class MemberServiceImpl extends ServiceImpl imple throw new HttpException(70010); } //审计日志 - OprMemDictDO oprMemDictDO = new OprMemDictDO(); - oprMemDictDO.setUserId(memberDO.getId()); - oprMemDictDO.setOprType("登录"); - oprMemDictDO.setResult(1); - oprMemDictDO.setIpAddress(IpAddressUtil.getIpAddress(request)); - oprMemDictMapper.insert(oprMemDictDO); + OprMemDictDO oprMemDictDO = oprMemDictMapper.getLatestLoginInfo(memberDO.getId()); + if (null == oprMemDictDO || !(oprMemDictDO.getResult() == 1 && "登录".equals(oprMemDictDO.getOprType()))) { + oprMemDictDO = new OprMemDictDO(); + oprMemDictDO.setUserId(memberDO.getId()); + oprMemDictDO.setOprType("登录"); + oprMemDictDO.setResult(1); + oprMemDictDO.setIpAddress(IpAddressUtil.getIpAddress(request)); + oprMemDictMapper.insert(oprMemDictDO); + } //mongoTemplate.insert(oprMemDictDO); userRoleVO.setCompanyId(companyDictDO.getId()); userRoleVO.setSuperviseName(companyDictDO.getSuperviseName()); @@ -390,12 +396,15 @@ public class MemberServiceImpl extends ServiceImpl imple memberVO.setCompanyId(companyDictDO.getId()); memberVO.setCompanyName(companyDictDO.getCompanyName()); memberVO.setQxyStatus(companyDictDO.getQxyStatus()); - OprMemDictDO oprMemDictDO = new OprMemDictDO(); - oprMemDictDO.setUserId(memberDO.getId()); - oprMemDictDO.setOprType("登录"); - oprMemDictDO.setResult(1); - oprMemDictDO.setIpAddress(IpAddressUtil.getIpAddress(request)); - oprMemDictMapper.insert(oprMemDictDO); + OprMemDictDO oprMemDictDO = oprMemDictMapper.getLatestLoginInfo(memberDO.getId()); + if (null == oprMemDictDO || !(oprMemDictDO.getResult() == 1 && "登录".equals(oprMemDictDO.getOprType()))) { + oprMemDictDO = new OprMemDictDO(); + oprMemDictDO.setUserId(memberDO.getId()); + oprMemDictDO.setOprType("登录"); + oprMemDictDO.setResult(1); + oprMemDictDO.setIpAddress(IpAddressUtil.getIpAddress(request)); + oprMemDictMapper.insert(oprMemDictDO); + } memberVO.setCompanyId(companyDictDO.getId()); memberVO.setSuperviseName(companyDictDO.getSuperviseName()); memberVO.setCompanyName(companyDictDO.getCompanyName()); @@ -406,6 +415,20 @@ public class MemberServiceImpl extends ServiceImpl imple memberVO.setRotationImgDictDOS(rotationImgDictDOS); String token = JwtUtil.generateToken(memberDO.getId(), ConstantUtils.MOBILE_TERMINATE); + + //更新token + int count = memberTokensMapper.selectCount(new QueryWrapper() + .lambda() + .eq(MemberTokensDO::getMemberId, memberDO.getId())); + if (count > 0) { + memberTokensMapper.updateToken(memberDO.getId(), token); + } else { + MemberTokensDO memberTokensDO = new MemberTokensDO(); + memberTokensDO.setMemberId(memberDO.getId()); + memberTokensDO.setToken(token); + memberTokensMapper.insert(memberTokensDO); + } + Localstorage.setUser(memberDO); memberVO.setToken(token); return memberVO; @@ -536,12 +559,15 @@ public class MemberServiceImpl extends ServiceImpl imple BeanUtils.copyProperties(memberDO, userRoleVO); //审计日志 - OprMemDictDO oprMemDictDO = new OprMemDictDO(); - oprMemDictDO.setUserId(memberDO.getId()); - oprMemDictDO.setOprType("登录"); - oprMemDictDO.setResult(1); - oprMemDictDO.setIpAddress(IpAddressUtil.getIpAddress(request)); - oprMemDictMapper.insert(oprMemDictDO); + OprMemDictDO oprMemDictDO = oprMemDictMapper.getLatestLoginInfo(memberDO.getId()); + if (null == oprMemDictDO || !(oprMemDictDO.getResult() == 1 && "登录".equals(oprMemDictDO.getOprType()))) { + oprMemDictDO = new OprMemDictDO(); + oprMemDictDO.setUserId(memberDO.getId()); + oprMemDictDO.setOprType("登录"); + oprMemDictDO.setResult(1); + oprMemDictDO.setIpAddress(IpAddressUtil.getIpAddress(request)); + oprMemDictMapper.insert(oprMemDictDO); + } userRoleVO.setCompanyId(companyDictDO.getId()); userRoleVO.setSuperviseName(companyDictDO.getSuperviseName()); userRoleVO.setCompanyName(companyDictDO.getCompanyName()); @@ -627,12 +653,15 @@ public class MemberServiceImpl extends ServiceImpl imple BeanUtils.copyProperties(memberDO, userRoleVO); //审计日志 - OprMemDictDO oprMemDictDO = new OprMemDictDO(); - oprMemDictDO.setUserId(memberDO.getId()); - oprMemDictDO.setOprType("登录"); - oprMemDictDO.setResult(1); - oprMemDictDO.setIpAddress(IpAddressUtil.getIpAddress(request)); - oprMemDictMapper.insert(oprMemDictDO); + OprMemDictDO oprMemDictDO = oprMemDictMapper.getLatestLoginInfo(memberDO.getId()); + if (null == oprMemDictDO || !(oprMemDictDO.getResult() == 1 && "登录".equals(oprMemDictDO.getOprType()))) { + oprMemDictDO = new OprMemDictDO(); + oprMemDictDO.setUserId(memberDO.getId()); + oprMemDictDO.setOprType("登录"); + oprMemDictDO.setResult(1); + oprMemDictDO.setIpAddress(IpAddressUtil.getIpAddress(request)); + oprMemDictMapper.insert(oprMemDictDO); + } userRoleVO.setCompanyId(companyDictDO.getId()); userRoleVO.setSuperviseName(companyDictDO.getSuperviseName()); userRoleVO.setCompanyName(companyDictDO.getCompanyName()); @@ -1128,5 +1157,20 @@ public class MemberServiceImpl extends ServiceImpl imple return polyvInfoVO; } + public String logout(MemberDO memberDO) { + memberTokensMapper.delete(new QueryWrapper() + .lambda() + .eq(MemberTokensDO::getMemberId, memberDO.getId())); + OprMemDictDO oprMemDictDO = oprMemDictMapper.getLatestLoginInfo(memberDO.getId()); + + if (oprMemDictDO.getResult() == 1 && "登出".equals(oprMemDictDO.getOprType())) { + oprMemDictMapper.deleteData(oprMemDictDO); + } + oprMemDictDO.setUserId(memberDO.getId()); + oprMemDictDO.setResult(1); + oprMemDictDO.setOprType("登出"); + oprMemDictMapper.insert(oprMemDictDO); + return ConstantUtils.ADD_SUCCESS; + } } diff --git a/src/main/java/com/subsidy/service/impl/MemberTokensServiceImpl.java b/src/main/java/com/subsidy/service/impl/MemberTokensServiceImpl.java new file mode 100644 index 0000000..92f447f --- /dev/null +++ b/src/main/java/com/subsidy/service/impl/MemberTokensServiceImpl.java @@ -0,0 +1,20 @@ +package com.subsidy.service.impl; + +import com.subsidy.model.MemberTokensDO; +import com.subsidy.mapper.MemberTokensMapper; +import com.subsidy.service.MemberTokensService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 用户登录token 服务实现类 + *

+ * + * @author Tuyp + * @since 2023-01-06 + */ +@Service +public class MemberTokensServiceImpl extends ServiceImpl implements MemberTokensService { + +} diff --git a/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java b/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java index 90c6f11..6c00456 100644 --- a/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java +++ b/src/main/java/com/subsidy/util/websocket/WebSocketUtil.java @@ -3,6 +3,7 @@ package com.subsidy.util.websocket; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.subsidy.common.ResponseData; +import com.subsidy.common.exception.HttpException; import com.subsidy.mapper.ClassDictMapper; import com.subsidy.mapper.MemberMapper; import com.subsidy.mapper.OprMemDictMapper; @@ -15,17 +16,15 @@ import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.socket.*; -import org.springframework.web.socket.handler.AbstractWebSocketHandler; import java.io.IOException; import java.util.List; import java.util.concurrent.*; /** - *

* WebSocket - *

- * https://zhuanlan.zhihu.com/p/531474864 + * https://zhuanlan.zhihu.com/p/531474864 + * * @author DengMin * @since 2022/7/13 */ @@ -44,7 +43,7 @@ public class WebSocketUtil implements WebSocketHandler { private int heartbeatMin = 1; // 断连最小心跳次数 private int heartbeatMax = 3; // 断连最大心跳次数 - private int reconnectionSeconds = 60; //每次断连间隔重新连接秒 + private int reconnectionSeconds = 30; //每次断连间隔重新连接秒 /** * 存放建立连接webSocket对象 Map @@ -60,42 +59,38 @@ public class WebSocketUtil implements WebSocketHandler { public void afterConnectionEstablished(WebSocketSession session) throws IOException { if (null != session) { String params = session.getUri().getQuery(); - Long id = Long.valueOf(params.split("=")[1]); - + //ws://www.youkehulian.cn/nginx/socket?userId=3340&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MzM0MCwidHlwZSI6Im1vYmlsZSIsImV4cCI6MTY3MzA1NjAzOSwiaWF0IjoxNjcyOTY5NjM5fQ.qx05-0AoWcaktgux30dJLmRE7AdtRuSWvk6cX7CNnao +// Long id = Long.valueOf(params.split("=")[1]); + String[] split = params.split("="); + Long id = Long.valueOf(split[1].split("&")[0]); + String token = split[2]; +// OprMemDictDO oprMemDictDO = oprMemDictMapper.getLatestLoginInfo(id); //最近一次登录 +// if (null != oprMemDictDO) { +// //如果最近一次不是登录成功,那么就是页面上刷新 +// if (!("登录".equals(oprMemDictDO.getOprType()) && 1 == oprMemDictDO.getResult())) { +// webSocketMap.put(id, session); +// webSocketMap.get(id).sendMessage(new TextMessage(JSONObject.toJSONString(ResponseData.generateCreatedResponse(1012)))); +// } +// } //webSocketMap的操作 if (null != webSocketMap && webSocketMap.get(id) != null) { if (webSocketMap.get(id).isOpen()) { /* 相同账户进行挤号,发送消息给WebSocket通知账户已在其他地方登录 */ webSocketMap.get(id).sendMessage(new TextMessage(JSONObject.toJSONString(ResponseData.generateCreatedResponse(1011)))); webSocketMap.get(id).close(); - } else { - /* - * 上次连接的WebSocket状态是关闭, - * 并且上一次记录时间大于 { heartbeatMax * reconnectionSeconds } 秒(心跳检测机制),则判断为这次登陆是免密码登陆的重新记录上线时间 - */ - OprMemDictDO oprMemDictDO = oprMemDictMapper.getLatestLoginInfo(id); //最近一次登录 - - if (oprMemDictDO.getOprType().equals("登出")) { - //登出过的话就写记录,否则不写 - oprMemDictDO.setUserId(id); - oprMemDictDO.setResult(1); - oprMemDictDO.setOprType("登录"); -// oprMemDictDO.setIpAddress(session.getRemoteAddress().getHostName()); - oprMemDictMapper.insert(oprMemDictDO); - } -// } } webSocketMap.remove(id); } webSocketMap.put(id, session); - // 数据操作 SystemSettings systemSettings = memberMapper.companySettings(id); //公司配置 List classSettings = classDictMapper.getClassSettings(id); systemSettings.setClassSettingsVOS(classSettings); if (CollectionUtils.isNotEmpty(classSettings)) { String data = JSONObject.toJSONString(ResponseData.generateCreatedResponse(0, systemSettings), SerializerFeature.WriteMapNullValue); - webSocketMap.get(id).sendMessage(new TextMessage(data)); + if (null != webSocketMap.get(id)) { + webSocketMap.get(id).sendMessage(new TextMessage(data)); + } } } } @@ -104,8 +99,8 @@ public class WebSocketUtil implements WebSocketHandler { * 接收WebSocket客户端Message */ @Override - public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception { - this.handleMessage(session,message); + public void handleMessage(WebSocketSession session, WebSocketMessage message) { + this.handleMessage(session, message); } /** @@ -116,9 +111,11 @@ public class WebSocketUtil implements WebSocketHandler { if (session.isOpen()) { session.close(); } - String params = session.getUri().getQuery(); - Long id = Long.valueOf(params.split("=")[1]); + String[] split = params.split("="); + Long id = Long.valueOf(split[1].split("&")[0]); +// String token = split[2]; +// Long id = Long.valueOf(params.split("=")[1]); webSocketMap.remove(id); } @@ -129,9 +126,12 @@ public class WebSocketUtil implements WebSocketHandler { public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { if (null != session) { if (null != webSocketMap) { - String params = session.getUri().getQuery(); - Long id = Long.valueOf(params.split("=")[1]); - heartbeat(webSocketMap.get(id)); +// String params = session.getUri().getQuery(); +// String[] split = params.split("="); +// Long id = Long.valueOf(split[1].split("&")[0]); +// String token = split[2]; +// Long id = Long.valueOf(params.split("=")[1]); +// heartbeat(webSocketMap.get(id)); } } } @@ -148,34 +148,55 @@ public class WebSocketUtil implements WebSocketHandler { * 断开连接后进行三次心跳验证判断是否重新连接了,如果没有连接成功则判断为下线 */ 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()) { - if (beatsNum > heartbeatMax) { //heartbeatMa:2 - String params = session.getUri().getQuery(); - Long id = Long.valueOf(params.split("=")[1]); - OprMemDictDO oprMemDictDO = new OprMemDictDO(); - oprMemDictDO.setUserId(id); - oprMemDictDO.setResult(1); - oprMemDictDO.setOprType("登出"); - oprMemDictMapper.insert(oprMemDictDO); - taskMap.get(session.getId()).cancel(true); -// break; - } - beatsNum++; - } else if (null != session && session.isOpen()) { - /* 时间段内重新连接了结束验证 */ - beatsNum = heartbeatMin; - taskMap.get(session.getId()).cancel(true); - } - } - }, 0, reconnectionSeconds, TimeUnit.SECONDS); - taskMap.put(session.getId(), scheduledFuture); +// ScheduledExecutorService service = Executors.newScheduledThreadPool(1); +// String params = session.getUri().getQuery(); +// String[] split = params.split("="); +// Long id = Long.valueOf(split[1].split("&")[0]); +// String token = split[2]; +// +// ScheduledFuture scheduledFuture = service.scheduleAtFixedRate(new Runnable() { +// int beatsNum = heartbeatMin; //至少一次 +// +// @SneakyThrows +// @Override +// public void run() { +// if (null != session && !session.isOpen()) { +// //判断这个session在不在map里 +// if (taskMap.containsKey(token)) { +// //在map里并且这个session还是断开的情况下,进行重连,超过次数就掉线 +// if (beatsNum > heartbeatMax) { // +// OprMemDictDO oprMemDictDO = new OprMemDictDO(); +// oprMemDictDO.setUserId(id); +// oprMemDictDO.setResult(1); +// oprMemDictDO.setOprType("登出"); +// oprMemDictMapper.insert(oprMemDictDO); +// //结束任务 +// taskMap.get(token).cancel(true); +// taskMap.remove(token); +// } +// beatsNum++; +// } +// } else if (null != session && session.isOpen()) { +// if (taskMap.containsKey(token)){ +// /* 时间段内重新连接了结束验证 */ +// beatsNum = heartbeatMin; //重连次数清零 +// taskMap.get(token).cancel(true); +// taskMap.remove(token); +// } +// +// } +// } +// }, 0, reconnectionSeconds, TimeUnit.SECONDS); +// taskMap.put(token, scheduledFuture); } + + public static void main(String[] args) { + String url = "ws://www.youkehulian.cn/nginx/socket?userId=3340&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MzM0MCwidHlwZSI6Im1vYmlsZSIsImV4cCI6MTY3MzA1NjAzOSwiaWF0IjoxNjcyOTY5NjM5fQ.qx05-0AoWcaktgux30dJLmRE7AdtRuSWvk6cX7CNnao"; + String[] split = url.split("="); + Long id = Long.valueOf(split[1].split("&")[0]); + String token = split[2]; + System.out.println(id); + System.out.println(token); + } } \ No newline at end of file diff --git a/src/main/resources/code.properties b/src/main/resources/code.properties index 16b0958..54021c1 100644 --- a/src/main/resources/code.properties +++ b/src/main/resources/code.properties @@ -2,6 +2,7 @@ meishu.code-message[0]=成功 meishu.code-message[1010]=无效的令牌 meishu.code-message[1011]=当前账户已在其他设备登录 +meishu.code-message[1012]=你已掉线,请重新登录 meishu.code-message[10003]=验证码错误 meishu.code-message[10004]=账号或密码错误 diff --git a/src/main/resources/mapper/MemberTokensMapper.xml b/src/main/resources/mapper/MemberTokensMapper.xml new file mode 100644 index 0000000..0e3c1a3 --- /dev/null +++ b/src/main/resources/mapper/MemberTokensMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + create_date, + update_date, + delete_date, + id, member_id, token + + + + UPDATE member_tokens t + SET t.token = #{token} + WHERE + t.delete_date IS NULL + AND t.member_id = #{memberId} + + + diff --git a/src/main/resources/mapper/OprMemDictMapper.xml b/src/main/resources/mapper/OprMemDictMapper.xml index c5588f3..5ebdae3 100644 --- a/src/main/resources/mapper/OprMemDictMapper.xml +++ b/src/main/resources/mapper/OprMemDictMapper.xml @@ -56,17 +56,28 @@ + + + DELETE + FROM + opr_mem_dict + WHERE + delete_date IS NULL + AND id = #{id} +