package com.ruoyi.errand.utils; import io.jsonwebtoken.Claims; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import javax.annotation.Resource; import javax.websocket.CloseReason; import javax.websocket.OnClose; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.List; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @ServerEndpoint("/ws/delivery") @Component public class DeliveryWebSocket { private static ConcurrentHashMap deliveryPersonSessions = new ConcurrentHashMap<>(); private static RedisTemplate redisTemplate; @Autowired public void setRedisTemplate(RedisTemplate redisTemplate) { DeliveryWebSocket.redisTemplate = redisTemplate; } @OnOpen public void onOpen(Session session) { // 从查询参数获取token String token = session.getRequestParameterMap().get("token").stream().findFirst().orElse(null); // 验证token String userId=validateToken(token); if (null==userId) { try { session.close(new CloseReason(CloseReason.CloseCodes.VIOLATED_POLICY, "Invalid token")); } catch (IOException e) { e.printStackTrace(); } return; } deliveryPersonSessions.put(userId, session); checkPendingNotifications(userId); } private String validateToken(String token) { if (token == null || !token.startsWith("app:")) { return null; } try { //解析token 获取userid,再查询到AppUser String realToken = token.substring(4); Claims claims = JwtUtil.parseJWT(realToken); String userId = claims.get("userId").toString(); return userId; } catch (Exception e) { return null; } } @OnClose public void onClose(Session session) { String token = session.getRequestParameterMap().get("token").stream().findFirst().orElse(null); // 验证token String userId=validateToken(token); if (null==userId) { try { session.close(new CloseReason(CloseReason.CloseCodes.VIOLATED_POLICY, "Invalid token")); } catch (IOException e) { e.printStackTrace(); } return; } deliveryPersonSessions.remove(userId); } private void checkPendingNotifications(String userId) { String key = "delivery:notification:" + userId; List notifications = redisTemplate.opsForList().range(key, 0, -1); if (notifications != null && !notifications.isEmpty()) { for (Object notification : notifications) { sendNotification(userId, notification.toString()); } redisTemplate.delete(key); } } public void sendNotification(String userId, String message) { Session session = deliveryPersonSessions.get(userId); if (session != null && session.isOpen()) { try { session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } else { // 用户不在线,存入Redis String key = "delivery:notification:" + userId; redisTemplate.opsForList().rightPush(key, message); // 设置过期时间,比如1天 redisTemplate.expire(key, 1, TimeUnit.DAYS); } } }