huliguo
2 天以前 5d7b65670282a4fad015e37d567cfa171b162052
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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<String, Session> 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<Object> 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);
        }
    }
}