每日总结

package com.mentalhealth.service;

import com.mentalhealth.dto.WebSocketMessage;
import com.mentalhealth.entity.ConsultationSession;
import com.mentalhealth.entity.Message;
import com.mentalhealth.entity.MessageType;
import com.mentalhealth.entity.User;
import com.mentalhealth.entity.Consultant;
import com.mentalhealth.repository.ConsultationSessionRepository;
import com.mentalhealth.repository.UserRepository;
import com.mentalhealth.repository.ConsultantRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@Slf4j
@RequiredArgsConstructor
public class ConsultationWebSocketHandler extends TextWebSocketHandler {

private final MessageService messageService;
private final ConsultationSessionRepository sessionRepository;
private final UserRepository userRepository;
private final ConsultantRepository consultantRepository;
private final ObjectMapper objectMapper;

private final Map<Long, WebSocketSession> userSessions = new ConcurrentHashMap<>();

@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    Long userId = getUserIdFromSession(session);
    if (userId != null) {
        userSessions.put(userId, session);
        log.info("用户 {} WebSocket连接建立", userId);

        // 发送连接成功消息
        sendToUser(userId, createWebSocketMessage(
                WebSocketMessage.MessageType.CHAT,
                "WebSocket连接成功",
                null,
                userId,
                null
        ));
    } else {
        log.warn("WebSocket连接建立但无法识别用户,关闭连接");
        session.close(CloseStatus.NOT_ACCEPTABLE);
    }
}

@Override
protected void handleTextMessage(WebSocketSession session, TextMessage textMessage) throws Exception {
    Long currentUserId = getUserIdFromSession(session);
    if (currentUserId == null) {
        log.warn("收到消息但无法识别发送用户,关闭连接");
        session.close(CloseStatus.NOT_ACCEPTABLE);
        return;
    }

    try {
        String payload = textMessage.getPayload();
        log.debug("收到用户 {} 的消息: {}", currentUserId, payload);

        WebSocketMessage message = objectMapper.readValue(payload, WebSocketMessage.class);
        message.setFromUserId(currentUserId); // 确保发送者ID正确

        switch (message.getType()) {
            case CHAT:
                handleChatMessage(message);
                break;
            case JOIN:
                handleJoinSession(message);
                break;
            case TYPING:
                handleTypingIndicator(message);
                break;
            case READ_RECEIPT:
                handleReadReceipt(message);
                break;
            case LEAVE:
                handleLeaveSession(message);
                break;
            default:
                log.warn("用户 {} 发送了未知的消息类型: {}", currentUserId, message.getType());
        }
    } catch (Exception e) {
        log.error("处理用户 {} 的消息失败", currentUserId, e);
        sendToUser(currentUserId, createWebSocketMessage(
                WebSocketMessage.MessageType.CHAT,
                "消息处理失败: " + e.getMessage(),
                null,
                currentUserId,
                null
        ));
    }
}

private void handleChatMessage(WebSocketMessage message) {
    try {
        // 保存消息到数据库
        Message savedMessage = messageService.sendMessage(
                message.getFromUserId(),
                message.getToUserId(),
                message.getContent(),
                MessageType.TEXT  // 修正:直接使用 MessageType.TEXT
        );

        // 发送给接收方
        sendToUser(message.getToUserId(), createWebSocketMessage(
                WebSocketMessage.MessageType.CHAT,
                savedMessage.getContent(),
                savedMessage.getSenderId(),
                savedMessage.getReceiverId(),
                message.getSessionId()
        ));

        log.info("用户 {} 发送消息给用户 {}", message.getFromUserId(), message.getToUserId());
    } catch (Exception e) {
        log.error("处理聊天消息失败", e);
    }
}

private void handleJoinSession(WebSocketMessage message) {
    try {
        ConsultationSession session = sessionRepository.findById(message.getSessionId())
                .orElseThrow(() -> new RuntimeException("咨询会话不存在"));

        // 更新会话状态
        session.setStatus(ConsultationSession.SessionStatus.IN_PROGRESS);
        session.setActualStartTime(java.time.LocalDateTime.now());
        sessionRepository.save(session);

        // 获取用户和咨询师信息
        User user = userRepository.findById(session.getUserId())
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        Consultant consultant = consultantRepository.findById(session.getConsultantId())
                .orElseThrow(() -> new RuntimeException("咨询师不存在"));

        // 通知双方用户
        sendToUser(session.getUserId(), createWebSocketMessage(
                WebSocketMessage.MessageType.JOIN,
                "咨询会话已开始",
                session.getUserId(),
                consultant.getUser().getId(),
                message.getSessionId()
        ));

        sendToUser(consultant.getUser().getId(), createWebSocketMessage(
                WebSocketMessage.MessageType.JOIN,
                "咨询会话已开始",
                consultant.getUser().getId(),
                session.getUserId(),
                message.getSessionId()
        ));

        log.info("用户 {} 加入咨询会话 {}", message.getFromUserId(), message.getSessionId());
    } catch (Exception e) {
        log.error("处理加入会话失败", e);
    }
}

private void handleLeaveSession(WebSocketMessage message) {
    try {
        ConsultationSession session = sessionRepository.findById(message.getSessionId())
                .orElseThrow(() -> new RuntimeException("咨询会话不存在"));

        // 更新会话状态为已完成
        session.setStatus(ConsultationSession.SessionStatus.COMPLETED);
        session.setEndTime(java.time.LocalDateTime.now());
        sessionRepository.save(session);

        log.info("用户 {} 离开咨询会话 {}", message.getFromUserId(), message.getSessionId());
    } catch (Exception e) {
        log.error("处理离开会话失败", e);
    }
}

private void handleTypingIndicator(WebSocketMessage message) {
    sendToUser(message.getToUserId(), createWebSocketMessage(
            WebSocketMessage.MessageType.TYPING,
            "对方正在输入...",
            message.getFromUserId(),
            message.getToUserId(),
            message.getSessionId()
    ));
}

private void handleReadReceipt(WebSocketMessage message) {
    log.info("用户 {} 已读消息", message.getFromUserId());
}

private void sendToUser(Long userId, WebSocketMessage message) {
    WebSocketSession session = userSessions.get(userId);
    if (session != null && session.isOpen()) {
        try {
            String messageJson = objectMapper.writeValueAsString(message);
            session.sendMessage(new TextMessage(messageJson));
            log.debug("发送消息给用户 {}: {}", userId, message.getType());
        } catch (IOException e) {
            log.error("发送消息给用户 {} 失败", userId, e);
            userSessions.remove(userId);
        }
    } else {
        log.warn("用户 {} 的WebSocket连接不存在或已关闭", userId);
    }
}

private WebSocketMessage createWebSocketMessage(WebSocketMessage.MessageType type,
                                                String content, Long fromUserId, Long toUserId, Long sessionId) {
    WebSocketMessage message = new WebSocketMessage();
    message.setType(type);
    message.setContent(content);
    message.setFromUserId(fromUserId);
    message.setToUserId(toUserId);
    message.setSessionId(sessionId);
    message.setTimestamp(java.time.LocalDateTime.now().toString());
    return message;
}

private Long getUserIdFromSession(WebSocketSession session) {
    Map<String, Object> attributes = session.getAttributes();

    if (attributes.containsKey("userId")) {
        Object userIdObj = attributes.get("userId");
        if (userIdObj instanceof Long) {
            return (Long) userIdObj;
        } else if (userIdObj instanceof String) {
            try {
                return Long.parseLong((String) userIdObj);
            } catch (NumberFormatException e) {
                log.error("用户ID格式错误: {}", userIdObj);
            }
        }
    }

    log.warn("无法从WebSocket会话中获取用户ID");
    return null;
}

@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
    log.error("WebSocket传输错误", exception);
}

@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
    Long userId = getUserIdFromSession(session);
    if (userId != null) {
        userSessions.remove(userId);
        log.info("用户 {} WebSocket连接关闭,状态: {}", userId, closeStatus);
    }
}

/**
 * 广播消息给所有在线用户
 */
public void broadcastToAll(WebSocketMessage message) {
    for (Map.Entry<Long, WebSocketSession> entry : userSessions.entrySet()) {
        sendToUser(entry.getKey(), message);
    }
}

/**
 * 检查用户是否在线
 */
public boolean isUserOnline(Long userId) {
    WebSocketSession session = userSessions.get(userId);
    return session != null && session.isOpen();
}

/**
 * 获取在线用户数量
 */
public int getOnlineUserCount() {
    return userSessions.size();
}

}
image

posted @ 2025-11-04 21:13  李蕊lr  阅读(1)  评论(0)    收藏  举报