lzy 2 weeks ago
parent
commit
3bd07eb6d1

+ 1 - 1
src/main/java/com/zhentao/groups/ImApplication.java → src/main/java/com/zhentao/groups/IMApplication.java

@@ -2,7 +2,7 @@ package com.zhentao.groups;
 
 import com.zhentao.groups.im.ImServer;
 
-public class ImApplication {
+public class IMApplication {
     public static void main(String[] args) {
         ImServer.start();
     }

+ 1 - 1
src/main/java/com/zhentao/groups/dto/AddGroupsDto.java

@@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-
+import lombok.ToString;
 
 
 @Data

+ 1 - 1
src/main/java/com/zhentao/groups/service/GroupsService.java

@@ -1,8 +1,8 @@
 package com.zhentao.groups.service;
 
 import com.zhentao.groups.dto.AddGroupMembers;
-import com.zhentao.groups.dto.AddGroupsDto;
 import com.zhentao.groups.dto.DelGroupMembers;
+import com.zhentao.groups.dto.OutGroupsDto;
 import com.zhentao.groups.pojo.Groupss;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.zhentao.vo.Result;

+ 70 - 70
src/main/java/com/zhentao/information/cache/ChannelCache.java

@@ -1,70 +1,70 @@
-package com.zhentao.information.cache;
-
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelHandlerContext;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Channel缓存管理类
- * 用于管理用户Channel
- */
-@Slf4j
-@Component
-public class ChannelCache {
-    
-    /**
-     * 用户ID和Channel的映射关系
-     * key: 用户ID
-     * value: Channel上下文
-     */
-    private static final Map<String, ChannelHandlerContext> USER_CHANNEL_MAP = new ConcurrentHashMap<>();
-
-    /**
-     * 添加用户Channel映射
-     * @param userId 用户ID
-     * @param ctx Channel上下文
-     */
-    public void addCache(String userId, ChannelHandlerContext ctx) {
-        USER_CHANNEL_MAP.put(userId, ctx);
-        log.info("用户 {} 的Channel已添加到缓存", userId);
-    }
-
-    /**
-     * 获取用户的Channel
-     * @param userId 用户ID
-     * @return Channel上下文
-     */
-    public ChannelHandlerContext getCache(String userId) {
-        return USER_CHANNEL_MAP.get(userId);
-    }
-
-    /**
-     * 移除用户Channel映射
-     * @param userId 用户ID
-     */
-    public void removeCache(String userId) {
-        USER_CHANNEL_MAP.remove(userId);
-        log.info("用户 {} 的Channel已从缓存移除", userId);
-    }
-
-    /**
-     * 获取所有用户Channel映射
-     * @return 用户Channel映射Map
-     */
-    public Map<String, ChannelHandlerContext> getAllCache() {
-        return USER_CHANNEL_MAP;
-    }
-
-    /**
-     * 判断用户是否在线
-     * @param userId 用户ID
-     * @return 是否在线
-     */
-    public boolean isOnline(String userId) {
-        return USER_CHANNEL_MAP.containsKey(userId);
-    }
-} 
+//package com.zhentao.information.cache;
+//
+//import io.netty.channel.Channel;
+//import io.netty.channel.ChannelHandlerContext;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.stereotype.Component;
+//
+//import java.util.Map;
+//import java.util.concurrent.ConcurrentHashMap;
+//
+///**
+// * Channel缓存管理类
+// * 用于管理用户Channel
+// */
+//@Slf4j
+//@Component
+//public class ChannelCache {
+//
+//    /**
+//     * 用户ID和Channel的映射关系
+//     * key: 用户ID
+//     * value: Channel上下文
+//     */
+//    private static final Map<String, ChannelHandlerContext> USER_CHANNEL_MAP = new ConcurrentHashMap<>();
+//
+//    /**
+//     * 添加用户Channel映射
+//     * @param userId 用户ID
+//     * @param ctx Channel上下文
+//     */
+//    public void addCache(String userId, ChannelHandlerContext ctx) {
+//        USER_CHANNEL_MAP.put(userId, ctx);
+//        log.info("用户 {} 的Channel已添加到缓存", userId);
+//    }
+//
+//    /**
+//     * 获取用户的Channel
+//     * @param userId 用户ID
+//     * @return Channel上下文
+//     */
+//    public ChannelHandlerContext getCache(String userId) {
+//        return USER_CHANNEL_MAP.get(userId);
+//    }
+//
+//    /**
+//     * 移除用户Channel映射
+//     * @param userId 用户ID
+//     */
+//    public void removeCache(String userId) {
+//        USER_CHANNEL_MAP.remove(userId);
+//        log.info("用户 {} 的Channel已从缓存移除", userId);
+//    }
+//
+//    /**
+//     * 获取所有用户Channel映射
+//     * @return 用户Channel映射Map
+//     */
+//    public Map<String, ChannelHandlerContext> getAllCache() {
+//        return USER_CHANNEL_MAP;
+//    }
+//
+//    /**
+//     * 判断用户是否在线
+//     * @param userId 用户ID
+//     * @return 是否在线
+//     */
+//    public boolean isOnline(String userId) {
+//        return USER_CHANNEL_MAP.containsKey(userId);
+//    }
+//}

+ 99 - 99
src/main/java/com/zhentao/information/config/NettyConfig.java

@@ -1,99 +1,99 @@
-package com.zhentao.information.config;
-
-import com.zhentao.information.handler.WebSocketHandler;
-import io.netty.bootstrap.ServerBootstrap;
-import io.netty.channel.ChannelInitializer;
-import io.netty.channel.ChannelOption;
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.channel.socket.SocketChannel;
-import io.netty.channel.socket.nio.NioServerSocketChannel;
-import io.netty.handler.codec.http.HttpObjectAggregator;
-import io.netty.handler.codec.http.HttpServerCodec;
-import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
-import io.netty.handler.stream.ChunkedWriteHandler;
-import io.netty.handler.timeout.IdleStateHandler;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import javax.annotation.Resource;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Netty服务器配置类
- * 配置WebSocket服务器的启动参数和处理器链
- */
-@Slf4j
-@Configuration
-public class NettyConfig {
-
-    /**
-     * WebSocket服务器端口
-     */
-    @Value("${netty.websocket.port}")
-    private int port;
-
-    /**
-     * WebSocket消息处理器
-     */
-    @Resource
-    private WebSocketHandler webSocketHandler;
-
-    /**
-     * 配置并启动Netty服务器
-     * @return ServerBootstrap实例
-     */
-    @Bean
-    public ServerBootstrap serverBootstrap() {
-        // 创建主从线程组
-        // bossGroup用于接收客户端连接
-        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
-        // workerGroup用于处理客户端数据
-        EventLoopGroup workerGroup = new NioEventLoopGroup();
-        
-        // 创建服务器启动对象
-        ServerBootstrap bootstrap = new ServerBootstrap();
-        bootstrap.group(bossGroup, workerGroup)
-                // 设置服务器通道实现
-                .channel(NioServerSocketChannel.class)
-                // 设置线程队列等待连接个数
-                .option(ChannelOption.SO_BACKLOG, 128)
-                // 设置保持活动连接状态
-                .childOption(ChannelOption.SO_KEEPALIVE, true)
-                // 禁用Nagle算法,减少延迟
-                .childOption(ChannelOption.TCP_NODELAY, true)
-                // 设置处理器
-                .childHandler(new ChannelInitializer<SocketChannel>() {
-                    @Override
-                    protected void initChannel(SocketChannel ch) {
-                        // 获取管道
-                        ch.pipeline()
-                                // HTTP编解码器
-                                .addLast(new HttpServerCodec())
-                                // 支持大数据流
-                                .addLast(new ChunkedWriteHandler())
-                                // HTTP消息聚合器
-                                .addLast(new HttpObjectAggregator(65536))
-                                // 心跳检测,60秒没有收到消息就触发
-                                .addLast(new IdleStateHandler(60, 0, 0, TimeUnit.SECONDS))
-                                // WebSocket协议处理器
-                                .addLast(new WebSocketServerProtocolHandler("/ws", null, true))
-                                // 自定义消息处理器
-                                .addLast(webSocketHandler);
-                    }
-                });
-        
-        try {
-            // 绑定端口并启动服务器
-            bootstrap.bind(port).sync();
-            log.info("Netty WebSocket服务器启动成功,端口:{}", port);
-        } catch (InterruptedException e) {
-            log.error("Netty WebSocket服务器启动失败", e);
-            Thread.currentThread().interrupt();
-        }
-        
-        return bootstrap;
-    }
-} 
+//package com.zhentao.information.config;
+//
+//import com.zhentao.information.handler.WebSocketHandler;
+//import io.netty.bootstrap.ServerBootstrap;
+//import io.netty.channel.ChannelInitializer;
+//import io.netty.channel.ChannelOption;
+//import io.netty.channel.EventLoopGroup;
+//import io.netty.channel.nio.NioEventLoopGroup;
+//import io.netty.channel.socket.SocketChannel;
+//import io.netty.channel.socket.nio.NioServerSocketChannel;
+//import io.netty.handler.codec.http.HttpObjectAggregator;
+//import io.netty.handler.codec.http.HttpServerCodec;
+//import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
+//import io.netty.handler.stream.ChunkedWriteHandler;
+//import io.netty.handler.timeout.IdleStateHandler;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//
+//import javax.annotation.Resource;
+//import java.util.concurrent.TimeUnit;
+//
+///**
+// * Netty服务器配置类
+// * 配置WebSocket服务器的启动参数和处理器链
+// */
+//@Slf4j
+//@Configuration
+//public class NettyConfig {
+//
+//    /**
+//     * WebSocket服务器端口
+//     */
+//    @Value("${netty.websocket.port}")
+//    private int port;
+//
+//    /**
+//     * WebSocket消息处理器
+//     */
+//    @Resource
+//    private WebSocketHandler webSocketHandler;
+//
+//    /**
+//     * 配置并启动Netty服务器
+//     * @return ServerBootstrap实例
+//     */
+//    @Bean
+//    public ServerBootstrap serverBootstrap() {
+//        // 创建主从线程组
+//        // bossGroup用于接收客户端连接
+//        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
+//        // workerGroup用于处理客户端数据
+//        EventLoopGroup workerGroup = new NioEventLoopGroup();
+//
+//        // 创建服务器启动对象
+//        ServerBootstrap bootstrap = new ServerBootstrap();
+//        bootstrap.group(bossGroup, workerGroup)
+//                // 设置服务器通道实现
+//                .channel(NioServerSocketChannel.class)
+//                // 设置线程队列等待连接个数
+//                .option(ChannelOption.SO_BACKLOG, 128)
+//                // 设置保持活动连接状态
+//                .childOption(ChannelOption.SO_KEEPALIVE, true)
+//                // 禁用Nagle算法,减少延迟
+//                .childOption(ChannelOption.TCP_NODELAY, true)
+//                // 设置处理器
+//                .childHandler(new ChannelInitializer<SocketChannel>() {
+//                    @Override
+//                    protected void initChannel(SocketChannel ch) {
+//                        // 获取管道
+//                        ch.pipeline()
+//                                // HTTP编解码器
+//                                .addLast(new HttpServerCodec())
+//                                // 支持大数据流
+//                                .addLast(new ChunkedWriteHandler())
+//                                // HTTP消息聚合器
+//                                .addLast(new HttpObjectAggregator(65536))
+//                                // 心跳检测,60秒没有收到消息就触发
+//                                .addLast(new IdleStateHandler(60, 0, 0, TimeUnit.SECONDS))
+//                                // WebSocket协议处理器
+//                                .addLast(new WebSocketServerProtocolHandler("/ws", null, true))
+//                                // 自定义消息处理器
+//                                .addLast(webSocketHandler);
+//                    }
+//                });
+//
+//        try {
+//            // 绑定端口并启动服务器
+//            bootstrap.bind(port).sync();
+//            log.info("Netty WebSocket服务器启动成功,端口:{}", port);
+//        } catch (InterruptedException e) {
+//            log.error("Netty WebSocket服务器启动失败", e);
+//            Thread.currentThread().interrupt();
+//        }
+//
+//        return bootstrap;
+//    }
+//}

+ 42 - 42
src/main/java/com/zhentao/information/config/WebSocketHandshakeInterceptor.java

@@ -1,42 +1,42 @@
-package com.zhentao.information.config;
-
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.handler.codec.http.FullHttpRequest;
-import io.netty.util.AttributeKey;
-import java.net.URI;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-
-public class WebSocketHandshakeInterceptor extends ChannelInboundHandlerAdapter {
-    public static final AttributeKey<String> PEER_ID_KEY = AttributeKey.valueOf("peerId");
-    public static final AttributeKey<String> TOKEN_KEY = AttributeKey.valueOf("token");
-
-    @Override
-    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
-        if (msg instanceof FullHttpRequest) {
-            FullHttpRequest req = (FullHttpRequest) msg;
-            URI uri = new URI(req.uri());
-            String query = uri.getQuery();
-            if (query != null) {
-                Map<String, String> params = new HashMap<>();
-                for (String param : query.split("&")) {
-                    String[] pair = param.split("=");
-                    if (pair.length == 2) {
-                        params.put(URLDecoder.decode(pair[0], String.valueOf(StandardCharsets.UTF_8)),
-                                   URLDecoder.decode(pair[1], String.valueOf(StandardCharsets.UTF_8)));
-                    }
-                }
-                if (params.containsKey("peerId")) {
-                    ctx.channel().attr(PEER_ID_KEY).set(params.get("peerId"));
-                }
-                if (params.containsKey("token")) {
-                    ctx.channel().attr(TOKEN_KEY).set(params.get("token"));
-                }
-            }
-        }
-        super.channelRead(ctx, msg);
-    }
-}
+//package com.zhentao.information.config;
+//
+//import io.netty.channel.ChannelHandlerContext;
+//import io.netty.channel.ChannelInboundHandlerAdapter;
+//import io.netty.handler.codec.http.FullHttpRequest;
+//import io.netty.util.AttributeKey;
+//import java.net.URI;
+//import java.net.URLDecoder;
+//import java.nio.charset.StandardCharsets;
+//import java.util.HashMap;
+//import java.util.Map;
+//
+//public class WebSocketHandshakeInterceptor extends ChannelInboundHandlerAdapter {
+//    public static final AttributeKey<String> PEER_ID_KEY = AttributeKey.valueOf("peerId");
+//    public static final AttributeKey<String> TOKEN_KEY = AttributeKey.valueOf("token");
+//
+//    @Override
+//    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+//        if (msg instanceof FullHttpRequest) {
+//            FullHttpRequest req = (FullHttpRequest) msg;
+//            URI uri = new URI(req.uri());
+//            String query = uri.getQuery();
+//            if (query != null) {
+//                Map<String, String> params = new HashMap<>();
+//                for (String param : query.split("&")) {
+//                    String[] pair = param.split("=");
+//                    if (pair.length == 2) {
+//                        params.put(URLDecoder.decode(pair[0], String.valueOf(StandardCharsets.UTF_8)),
+//                                   URLDecoder.decode(pair[1], String.valueOf(StandardCharsets.UTF_8)));
+//                    }
+//                }
+//                if (params.containsKey("peerId")) {
+//                    ctx.channel().attr(PEER_ID_KEY).set(params.get("peerId"));
+//                }
+//                if (params.containsKey("token")) {
+//                    ctx.channel().attr(TOKEN_KEY).set(params.get("token"));
+//                }
+//            }
+//        }
+//        super.channelRead(ctx, msg);
+//    }
+//}

+ 100 - 101
src/main/java/com/zhentao/information/controller/MessageController.java

@@ -1,101 +1,100 @@
-package com.zhentao.information.controller;
-
-
-import com.alibaba.fastjson2.JSON;
-import com.zhentao.config.NullLogin;
-import com.alibaba.fastjson.JSON;
-import com.zhentao.information.cache.ChannelCache;
-import com.zhentao.information.entity.ChatMessage;
-import com.zhentao.information.entity.Message;
-import com.zhentao.information.repository.ChatMessageRepository;
-import com.zhentao.tool.TokenUtils;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 消息控制器
- */
-@Slf4j
-@RestController
-@RequestMapping("/api/message")
-public class MessageController {
-
-    @Resource
-    private ChannelCache channelCache;
-
-    @Resource
-    private ChatMessageRepository chatMessageRepository;
-
-    /**
-     * 发送消息接口
-     */
-    @PostMapping("/send")
-    @NullLogin
-    public String sendMessage(@RequestBody Message message) {
-        log.info("收到消息:发送者={}, 接收者={}, 内容={}",
-                message.getFromUserId(),
-                message.getToUserId(),
-                message.getContent());
-
-        // 生成聊天ID(确保两个用户之间的聊天ID唯一)
-        String chatId = generateChatId(message.getFromUserId(), message.getToUserId());
-
-        // 创建MongoDB消息对象
-        ChatMessage chatMessage = new ChatMessage();
-        chatMessage.setFromUserId(message.getFromUserId());
-        chatMessage.setToUserId(message.getToUserId());
-        chatMessage.setContent(message.getContent());
-        chatMessage.setType(String.valueOf(message.getType()));
-        chatMessage.setTimestamp(System.currentTimeMillis());
-        chatMessage.setIsRead(false);
-        chatMessage.setChatId(chatId);
-
-        // 保存消息到MongoDB
-        chatMessageRepository.save(chatMessage);
-
-        // 获取接收者的Channel
-        ChannelHandlerContext toUserCtx = channelCache.getCache(message.getToUserId());
-
-        if (toUserCtx != null) {
-            // 发送消息给接收者
-            toUserCtx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(message)));
-            return "消息已发送";
-        } else {
-            return "消息已保存,等待接收者上线";
-        }
-    }
-
-    /**
-     * 获取两个用户之间的聊天记录
-     */
-    @GetMapping("/history")
-    public List<ChatMessage> getChatHistory(@RequestHeader("token") String token, @RequestParam String userId2) {
-        String userIdFromToken = TokenUtils.getUserIdFromToken(token);
-        String chatId = generateChatId(userIdFromToken, userId2);
-        return chatMessageRepository.findByChatId(chatId);
-    }
-
-    /**
-     * 获取用户的未读消息
-     */
-    @GetMapping("/unread")
-    public List<ChatMessage> getUnreadMessages(@RequestParam String userId) {
-        return chatMessageRepository.findByToUserIdAndIsReadFalse(userId);
-    }
-
-    /**
-     * 生成聊天ID
-     */
-    private String generateChatId(String userId1, String userId2) {
-        // 确保两个用户之间的聊天ID唯一,且与顺序无关
-        return userId1.compareTo(userId2) < 0 ?
-                userId1 + "_" + userId2 :
-                userId2 + "_" + userId1;
-    }
-}
+//package com.zhentao.information.controller;
+//
+//
+//import com.alibaba.fastjson2.JSON;
+//import com.zhentao.config.NullLogin;
+//import com.zhentao.information.cache.ChannelCache;
+//import com.zhentao.information.entity.ChatMessage;
+//import com.zhentao.information.entity.Message;
+//import com.zhentao.information.repository.ChatMessageRepository;
+//import com.zhentao.tool.TokenUtils;
+//import io.netty.channel.ChannelHandlerContext;
+//import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.web.bind.annotation.*;
+//
+//import javax.annotation.Resource;
+//import java.util.List;
+//import java.util.Map;
+//
+///**
+// * 消息控制器
+// */
+//@Slf4j
+//@RestController
+//@RequestMapping("/api/message")
+//public class MessageController {
+//
+//    @Resource
+//    private ChannelCache channelCache;
+//
+//    @Resource
+//    private ChatMessageRepository chatMessageRepository;
+//
+//    /**
+//     * 发送消息接口
+//     */
+//    @PostMapping("/send")
+//    @NullLogin
+//    public String sendMessage(@RequestBody Message message) {
+//        log.info("收到消息:发送者={}, 接收者={}, 内容={}",
+//                message.getFromUserId(),
+//                message.getToUserId(),
+//                message.getContent());
+//
+//        // 生成聊天ID(确保两个用户之间的聊天ID唯一)
+//        String chatId = generateChatId(message.getFromUserId(), message.getToUserId());
+//
+//        // 创建MongoDB消息对象
+//        ChatMessage chatMessage = new ChatMessage();
+//        chatMessage.setFromUserId(message.getFromUserId());
+//        chatMessage.setToUserId(message.getToUserId());
+//        chatMessage.setContent(message.getContent());
+//        chatMessage.setType(String.valueOf(message.getType()));
+//        chatMessage.setTimestamp(System.currentTimeMillis());
+//        chatMessage.setIsRead(false);
+//        chatMessage.setChatId(chatId);
+//
+//        // 保存消息到MongoDB
+//        chatMessageRepository.save(chatMessage);
+//
+//        // 获取接收者的Channel
+//        ChannelHandlerContext toUserCtx = channelCache.getCache(message.getToUserId());
+//
+//        if (toUserCtx != null) {
+//            // 发送消息给接收者
+//            toUserCtx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(message)));
+//            return "消息已发送";
+//        } else {
+//            return "消息已保存,等待接收者上线";
+//        }
+//    }
+//
+//    /**
+//     * 获取两个用户之间的聊天记录
+//     */
+//    @GetMapping("/history")
+//    public List<ChatMessage> getChatHistory(@RequestHeader("token") String token, @RequestParam String userId2) {
+//        String userIdFromToken = TokenUtils.getUserIdFromToken(token);
+//        String chatId = generateChatId(userIdFromToken, userId2);
+//        return chatMessageRepository.findByChatId(chatId);
+//    }
+//
+//    /**
+//     * 获取用户的未读消息
+//     */
+//    @GetMapping("/unread")
+//    public List<ChatMessage> getUnreadMessages(@RequestParam String userId) {
+//        return chatMessageRepository.findByToUserIdAndIsReadFalse(userId);
+//    }
+//
+//    /**
+//     * 生成聊天ID
+//     */
+//    private String generateChatId(String userId1, String userId2) {
+//        // 确保两个用户之间的聊天ID唯一,且与顺序无关
+//        return userId1.compareTo(userId2) < 0 ?
+//                userId1 + "_" + userId2 :
+//                userId2 + "_" + userId1;
+//    }
+//}

+ 35 - 35
src/main/java/com/zhentao/information/entity/ChatMessage.java

@@ -1,35 +1,35 @@
-package com.zhentao.information.entity;
-
-import lombok.Data;
-import org.springframework.data.annotation.Id;
-import org.springframework.data.mongodb.core.mapping.Document;
-import org.springframework.data.mongodb.core.index.Indexed;
-
-/**
- * 聊天消息实体类(MongoDB)
- */
-@Data
-@Document(collection = "chat_messages")
-public class ChatMessage {
-
-    @Id
-    private String id;
-
-    @Indexed
-    private String fromUserId;
-
-    @Indexed
-    private String toUserId;
-
-    private String content;
-
-    private String type;
-
-    private Long timestamp;
-
-    private Boolean isRead;
-
-    // 复合索引:用于查询两个用户之间的聊天记录
-    @Indexed
-    private String chatId;
-}
+//package com.zhentao.information.entity;
+//
+//import lombok.Data;
+//import org.springframework.data.annotation.Id;
+//import org.springframework.data.mongodb.core.mapping.Document;
+//import org.springframework.data.mongodb.core.index.Indexed;
+//
+///**
+// * 聊天消息实体类(MongoDB)
+// */
+//@Data
+//@Document(collection = "chat_messages")
+//public class ChatMessage {
+//
+//    @Id
+//    private String id;
+//
+//    @Indexed
+//    private String fromUserId;
+//
+//    @Indexed
+//    private String toUserId;
+//
+//    private String content;
+//
+//    private String type;
+//
+//    private Long timestamp;
+//
+//    private Boolean isRead;
+//
+//    // 复合索引:用于查询两个用户之间的聊天记录
+//    @Indexed
+//    private String chatId;
+//}

+ 38 - 38
src/main/java/com/zhentao/information/entity/Message.java

@@ -1,38 +1,38 @@
-package com.zhentao.information.entity;
-
-import lombok.Data;
-
-/**
- * WebSocket消息实体类
- */
-@Data
-public class Message {
-    /**
-     * 消息类型
-     * connect: 连接消息
-     * text: 文本消息
-     * image: 图片消息
-     * voice: 语音消息
-     */
-    private String type;
-    
-    /**
-     * 发送者ID
-     */
-    private String fromUserId;
-    
-    /**
-     * 接收者ID
-     */
-    private String toUserId;
-    
-    /**
-     * 消息内容
-     */
-    private String content;
-    
-    /**
-     * 消息时间戳
-     */
-    private Long timestamp;
-}
+//package com.zhentao.information.entity;
+//
+//import lombok.Data;
+//
+///**
+// * WebSocket消息实体类
+// */
+//@Data
+//public class Message {
+//    /**
+//     * 消息类型
+//     * connect: 连接消息
+//     * text: 文本消息
+//     * image: 图片消息
+//     * voice: 语音消息
+//     */
+//    private String type;
+//
+//    /**
+//     * 发送者ID
+//     */
+//    private String fromUserId;
+//
+//    /**
+//     * 接收者ID
+//     */
+//    private String toUserId;
+//
+//    /**
+//     * 消息内容
+//     */
+//    private String content;
+//
+//    /**
+//     * 消息时间戳
+//     */
+//    private Long timestamp;
+//}

+ 40 - 40
src/main/java/com/zhentao/information/handler/HeartbeatHandler.java

@@ -1,40 +1,40 @@
-package com.zhentao.information.handler;
-
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandlerAdapter;
-import io.netty.handler.timeout.IdleState;
-import io.netty.handler.timeout.IdleStateEvent;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-/**
- * 心跳处理器
- * 处理客户端的心跳检测
- */
-@Slf4j
-@Component
-@ChannelHandler.Sharable
-public class HeartbeatHandler extends ChannelInboundHandlerAdapter {
-
-    /**
-     * 处理用户事件
-     * 当触发IdleStateEvent时调用
-     * @param ctx Channel上下文
-     * @param evt 事件对象
-     */
-    @Override
-    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
-        if (evt instanceof IdleStateEvent) {
-            IdleStateEvent event = (IdleStateEvent) evt;
-            
-            // 如果是读空闲事件
-            if (event.state() == IdleState.READER_IDLE) {
-                log.info("读空闲,关闭连接:{}", ctx.channel().id().asLongText());
-                ctx.close();
-            }
-        } else {
-            super.userEventTriggered(ctx, evt);
-        }
-    }
-} 
+//package com.zhentao.information.handler;
+//
+//import io.netty.channel.ChannelHandler;
+//import io.netty.channel.ChannelHandlerContext;
+//import io.netty.channel.ChannelInboundHandlerAdapter;
+//import io.netty.handler.timeout.IdleState;
+//import io.netty.handler.timeout.IdleStateEvent;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.stereotype.Component;
+//
+///**
+// * 心跳处理器
+// * 处理客户端的心跳检测
+// */
+//@Slf4j
+//@Component
+//@ChannelHandler.Sharable
+//public class HeartbeatHandler extends ChannelInboundHandlerAdapter {
+//
+//    /**
+//     * 处理用户事件
+//     * 当触发IdleStateEvent时调用
+//     * @param ctx Channel上下文
+//     * @param evt 事件对象
+//     */
+//    @Override
+//    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+//        if (evt instanceof IdleStateEvent) {
+//            IdleStateEvent event = (IdleStateEvent) evt;
+//
+//            // 如果是读空闲事件
+//            if (event.state() == IdleState.READER_IDLE) {
+//                log.info("读空闲,关闭连接:{}", ctx.channel().id().asLongText());
+//                ctx.close();
+//            }
+//        } else {
+//            super.userEventTriggered(ctx, evt);
+//        }
+//    }
+//}

+ 120 - 119
src/main/java/com/zhentao/information/handler/WebSocketHandler.java

@@ -1,119 +1,120 @@
-package com.zhentao.information.handler;
-
-import com.alibaba.fastjson.JSON;
-import com.zhentao.information.entity.ChatMessage;
-import com.zhentao.information.entity.Message;
-import com.zhentao.information.repository.ChatMessageRepository;
-import com.zhentao.information.service.WebSocketService;
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.SimpleChannelInboundHandler;
-import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-
-/**
- * WebSocket消息处理器
- * 处理WebSocket连接、消息接收和发送
- */
-@Slf4j
-@Component
-@ChannelHandler.Sharable
-public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
-
-    @Resource
-    private ChatMessageRepository chatMessageRepository;
-
-    @Resource
-    private WebSocketService webSocketService;
-
-    /**
-     * 处理接收到的WebSocket消息
-     */
-    @Override
-    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
-        String text = msg.text();
-        log.info("收到消息:{}", text);
-        try {
-            Message message = JSON.parseObject(text, Message.class);
-
-            // 如果是连接消息,处理token
-            if ("connect".equals(message.getType())) {
-                webSocketService.handleUserLogin(message.getContent(), ctx);
-                return;
-            }
-
-            // 处理普通消息
-            handleMessage(message);
-
-        } catch (Exception e) {
-            log.error("处理消息失败", e);
-        }
-    }
-
-    /**
-     * 处理普通消息
-     */
-    private void handleMessage(Message message) {
-        // 生成聊天ID
-        String chatId = generateChatId(message.getFromUserId(), message.getToUserId());
-
-        // 创建MongoDB消息对象
-        ChatMessage chatMessage = new ChatMessage();
-        chatMessage.setFromUserId(message.getFromUserId());
-        chatMessage.setToUserId(message.getToUserId());
-        chatMessage.setContent(message.getContent());
-        chatMessage.setType(String.valueOf(message.getType()));
-        chatMessage.setTimestamp(System.currentTimeMillis());
-        chatMessage.setIsRead(false);
-        chatMessage.setChatId(chatId);
-
-        // 保存消息到MongoDB
-        chatMessageRepository.save(chatMessage);
-
-        // 发送消息给接收者
-        boolean sent = webSocketService.sendMessageToUser(message.getToUserId(), message);
-        System.err.println("判断对方用户是否在线"+sent);
-        if (sent) {
-            log.info("消息已发送给用户: {}, 内容: {}", message.getToUserId(), message.getContent());
-        } else {
-            log.info("用户 {} 不在线,消息已保存到MongoDB", message.getToUserId());
-        }
-    }
-
-    /**
-     * 当新的WebSocket连接建立时调用
-     */
-    @Override
-    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
-        log.info("新的连接:{}", ctx.channel().id().asLongText());
-    }
-
-    /**
-     * 当WebSocket连接断开时调用
-     */
-    @Override
-    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
-        log.info("连接断开:{}", ctx.channel().id().asLongText());
-    }
-
-    /**
-     * 处理异常情况
-     */
-    @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-        log.error("WebSocket异常", cause);
-        ctx.close();
-    }
-
-    /**
-     * 生成聊天ID
-     */
-    private String generateChatId(String userId1, String userId2) {
-        return userId1.compareTo(userId2) < 0 ?
-                userId1 + "_" + userId2 :
-                userId2 + "_" + userId1;
-    }
-}
+//package com.zhentao.information.handler;
+//
+//
+//import com.alibaba.fastjson2.JSON;
+//import com.zhentao.information.entity.ChatMessage;
+//import com.zhentao.information.entity.Message;
+//import com.zhentao.information.repository.ChatMessageRepository;
+//import com.zhentao.information.service.WebSocketService;
+//import io.netty.channel.ChannelHandler;
+//import io.netty.channel.ChannelHandlerContext;
+//import io.netty.channel.SimpleChannelInboundHandler;
+//import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.stereotype.Component;
+//
+//import javax.annotation.Resource;
+//
+///**
+// * WebSocket消息处理器
+// * 处理WebSocket连接、消息接收和发送
+// */
+//@Slf4j
+//@Component
+//@ChannelHandler.Sharable
+//public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
+//
+//    @Resource
+//    private ChatMessageRepository chatMessageRepository;
+//
+//    @Resource
+//    private WebSocketService webSocketService;
+//
+//    /**
+//     * 处理接收到的WebSocket消息
+//     */
+//    @Override
+//    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
+//        String text = msg.text();
+//        log.info("收到消息:{}", text);
+//        try {
+//            Message message = JSON.parseObject(text, Message.class);
+//
+//            // 如果是连接消息,处理token
+//            if ("connect".equals(message.getType())) {
+//                webSocketService.handleUserLogin(message.getContent(), ctx);
+//                return;
+//            }
+//
+//            // 处理普通消息
+//            handleMessage(message);
+//
+//        } catch (Exception e) {
+//            log.error("处理消息失败", e);
+//        }
+//    }
+//
+//    /**
+//     * 处理普通消息
+//     */
+//    private void handleMessage(Message message) {
+//        // 生成聊天ID
+//        String chatId = generateChatId(message.getFromUserId(), message.getToUserId());
+//
+//        // 创建MongoDB消息对象
+//        ChatMessage chatMessage = new ChatMessage();
+//        chatMessage.setFromUserId(message.getFromUserId());
+//        chatMessage.setToUserId(message.getToUserId());
+//        chatMessage.setContent(message.getContent());
+//        chatMessage.setType(String.valueOf(message.getType()));
+//        chatMessage.setTimestamp(System.currentTimeMillis());
+//        chatMessage.setIsRead(false);
+//        chatMessage.setChatId(chatId);
+//
+//        // 保存消息到MongoDB
+//        chatMessageRepository.save(chatMessage);
+//
+//        // 发送消息给接收者
+//        boolean sent = webSocketService.sendMessageToUser(message.getToUserId(), message);
+//        System.err.println("判断对方用户是否在线"+sent);
+//        if (sent) {
+//            log.info("消息已发送给用户: {}, 内容: {}", message.getToUserId(), message.getContent());
+//        } else {
+//            log.info("用户 {} 不在线,消息已保存到MongoDB", message.getToUserId());
+//        }
+//    }
+//
+//    /**
+//     * 当新的WebSocket连接建立时调用
+//     */
+//    @Override
+//    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
+//        log.info("新的连接:{}", ctx.channel().id().asLongText());
+//    }
+//
+//    /**
+//     * 当WebSocket连接断开时调用
+//     */
+//    @Override
+//    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+//        log.info("连接断开:{}", ctx.channel().id().asLongText());
+//    }
+//
+//    /**
+//     * 处理异常情况
+//     */
+//    @Override
+//    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+//        log.error("WebSocket异常", cause);
+//        ctx.close();
+//    }
+//
+//    /**
+//     * 生成聊天ID
+//     */
+//    private String generateChatId(String userId1, String userId2) {
+//        return userId1.compareTo(userId2) < 0 ?
+//                userId1 + "_" + userId2 :
+//                userId2 + "_" + userId1;
+//    }
+//}

+ 24 - 24
src/main/java/com/zhentao/information/repository/ChatMessageRepository.java

@@ -1,24 +1,24 @@
-package com.zhentao.information.repository;
-
-import com.zhentao.information.entity.ChatMessage;
-import org.springframework.data.mongodb.repository.MongoRepository;
-import org.springframework.stereotype.Repository;
-
-import java.util.List;
-
-/**
- * 聊天消息仓库
- */
-@Repository
-public interface ChatMessageRepository extends MongoRepository<ChatMessage, String> {
-
-    /**
-     * 查询两个用户之间的聊天记录
-     */
-    List<ChatMessage> findByChatId(String chatId);
-
-    /**
-     * 查询用户的所有未读消息
-     */
-    List<ChatMessage> findByToUserIdAndIsReadFalse(String toUserId);
-}
+//package com.zhentao.information.repository;
+//
+//import com.zhentao.information.entity.ChatMessage;
+//import org.springframework.data.mongodb.repository.MongoRepository;
+//import org.springframework.stereotype.Repository;
+//
+//import java.util.List;
+//
+///**
+// * 聊天消息仓库
+// */
+//@Repository
+//public interface ChatMessageRepository extends MongoRepository<ChatMessage, String> {
+//
+//    /**
+//     * 查询两个用户之间的聊天记录
+//     */
+//    List<ChatMessage> findByChatId(String chatId);
+//
+//    /**
+//     * 查询用户的所有未读消息
+//     */
+//    List<ChatMessage> findByToUserIdAndIsReadFalse(String toUserId);
+//}

+ 112 - 112
src/main/java/com/zhentao/information/service/WebSocketService.java

@@ -1,112 +1,112 @@
-package com.zhentao.information.service;
-
-import com.alibaba.fastjson.JSON;
-import com.zhentao.information.cache.ChannelCache;
-import com.zhentao.information.entity.Message;
-import com.zhentao.tool.TokenUtils;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * WebSocket服务类
- * 处理WebSocket连接、消息发送等业务逻辑
- */
-@Slf4j
-@Service
-public class WebSocketService {
-
-    @Resource
-    private ChannelCache channelCache;
-
-    // 存储用户token的Map
-    private final Map<String, String> userTokenMap = new ConcurrentHashMap<>();
-
-    /**
-     * 存储用户token
-     * @param userId 用户ID
-     * @param token 用户token
-     */
-    public void storeUserToken(String userId, String token) {
-        userTokenMap.put(userId, token);
-        log.info("用户 {} 的token已存储", userId);
-    }
-
-    /**
-     * 获取用户token
-     * @param userId 用户ID
-     * @return 用户token
-     */
-    public String getUserToken(String userId) {
-        return userTokenMap.get(userId);
-    }
-
-    /**
-     * 处理用户登录
-     * @param token 用户token
-     * @param ctx Channel上下文
-     */
-    public void handleUserLogin(String token, ChannelHandlerContext ctx) {
-        String userId = TokenUtils.getUserIdFromToken(token);
-        if (userId != null) {
-            // 验证token是否与存储的token匹配
-            String storedToken = userTokenMap.get(userId);
-            if (storedToken != null && storedToken.equals(token)) {
-                // 将用户ID和Channel绑定
-                channelCache.addCache(userId, ctx);
-                log.info("用户 {} 连接成功", userId);
-                
-                // 发送连接成功消息
-                Message response = new Message();
-                response.setType("connect_success");
-                response.setContent("连接成功");
-                ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(response)));
-            } else {
-                log.error("用户 {} 的token验证失败", userId);
-                ctx.close();
-            }
-        } else {
-            log.error("无效的token");
-            ctx.close();
-        }
-    }
-
-    /**
-     * 发送消息给指定用户
-     * @param userId 接收者用户ID
-     * @param message 消息内容
-     * @return 是否发送成功
-     */
-    public boolean sendMessageToUser(String userId, Message message) {
-        ChannelHandlerContext ctx = channelCache.getCache(userId);
-        if (ctx != null) {
-            ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(message)));
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * 广播消息给所有在线用户
-     * @param message 消息内容
-     */
-    public void broadcastMessage(Message message) {
-        channelCache.getAllCache().forEach((userId, ctx) -> {
-            ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(message)));
-        });
-    }
-
-    /**
-     * 检查用户是否在线
-     * @param userId 用户ID
-     * @return 是否在线
-     */
-    public boolean isUserOnline(String userId) {
-        return channelCache.getCache(userId) != null;
-    }
-} 
+//package com.zhentao.information.service;
+//
+//import com.alibaba.fastjson.JSON;
+//import com.zhentao.information.cache.ChannelCache;
+//import com.zhentao.information.entity.Message;
+//import com.zhentao.tool.TokenUtils;
+//import io.netty.channel.ChannelHandlerContext;
+//import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
+//import lombok.extern.slf4j.Slf4j;
+//import org.springframework.stereotype.Service;
+//
+//import javax.annotation.Resource;
+//import java.util.Map;
+//import java.util.concurrent.ConcurrentHashMap;
+//
+///**
+// * WebSocket服务类
+// * 处理WebSocket连接、消息发送等业务逻辑
+// */
+//@Slf4j
+//@Service
+//public class WebSocketService {
+//
+//    @Resource
+//    private ChannelCache channelCache;
+//
+//    // 存储用户token的Map
+//    private final Map<String, String> userTokenMap = new ConcurrentHashMap<>();
+//
+//    /**
+//     * 存储用户token
+//     * @param userId 用户ID
+//     * @param token 用户token
+//     */
+//    public void storeUserToken(String userId, String token) {
+//        userTokenMap.put(userId, token);
+//        log.info("用户 {} 的token已存储", userId);
+//    }
+//
+//    /**
+//     * 获取用户token
+//     * @param userId 用户ID
+//     * @return 用户token
+//     */
+//    public String getUserToken(String userId) {
+//        return userTokenMap.get(userId);
+//    }
+//
+//    /**
+//     * 处理用户登录
+//     * @param token 用户token
+//     * @param ctx Channel上下文
+//     */
+//    public void handleUserLogin(String token, ChannelHandlerContext ctx) {
+//        String userId = TokenUtils.getUserIdFromToken(token);
+//        if (userId != null) {
+//            // 验证token是否与存储的token匹配
+//            String storedToken = userTokenMap.get(userId);
+//            if (storedToken != null && storedToken.equals(token)) {
+//                // 将用户ID和Channel绑定
+//                channelCache.addCache(userId, ctx);
+//                log.info("用户 {} 连接成功", userId);
+//
+//                // 发送连接成功消息
+//                Message response = new Message();
+//                response.setType("connect_success");
+//                response.setContent("连接成功");
+//                ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(response)));
+//            } else {
+//                log.error("用户 {} 的token验证失败", userId);
+//                ctx.close();
+//            }
+//        } else {
+//            log.error("无效的token");
+//            ctx.close();
+//        }
+//    }
+//
+//    /**
+//     * 发送消息给指定用户
+//     * @param userId 接收者用户ID
+//     * @param message 消息内容
+//     * @return 是否发送成功
+//     */
+//    public boolean sendMessageToUser(String userId, Message message) {
+//        ChannelHandlerContext ctx = channelCache.getCache(userId);
+//        if (ctx != null) {
+//            ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(message)));
+//            return true;
+//        }
+//        return false;
+//    }
+//
+//    /**
+//     * 广播消息给所有在线用户
+//     * @param message 消息内容
+//     */
+//    public void broadcastMessage(Message message) {
+//        channelCache.getAllCache().forEach((userId, ctx) -> {
+//            ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(message)));
+//        });
+//    }
+//
+//    /**
+//     * 检查用户是否在线
+//     * @param userId 用户ID
+//     * @return 是否在线
+//     */
+//    public boolean isUserOnline(String userId) {
+//        return channelCache.getCache(userId) != null;
+//    }
+//}

+ 1 - 4
src/main/java/com/zhentao/user/controller/UserController.java

@@ -1,10 +1,7 @@
 package com.zhentao.user.controller;
 
-import com.aliyun.oss.OSS;
-import com.aliyun.oss.OSSClientBuilder;
-import com.aliyun.oss.model.PutObjectRequest;
+
 import com.zhentao.config.NullLogin;
-import com.zhentao.information.service.WebSocketService;
 import com.zhentao.osspicture.OssUtil;
 import com.zhentao.tool.TokenUtils;
 import com.zhentao.user.domain.UserLogin;

+ 4 - 4
src/main/java/com/zhentao/user/service/impl/UserLoginServiceImpl.java

@@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zhentao.enums.ApiServerException;
 import com.zhentao.exception.AsynException;
 
-import com.zhentao.information.service.WebSocketService;
+
 import com.zhentao.tool.TokenUtils;
 import com.zhentao.user.domain.UserLogin;
 import com.zhentao.user.dto.*;
@@ -38,8 +38,8 @@ public class UserLoginServiceImpl extends ServiceImpl<UserLoginMapper, UserLogin
     private RedissonClient redissonClient;
     @Autowired
     private StringRedisTemplate stringRedisTemplate;
-    @Autowired
-    public WebSocketService webSocketService;
+//    @Autowired
+//    public WebSocketService webSocketService;
 
     //注册
     @Override
@@ -219,7 +219,7 @@ public class UserLoginServiceImpl extends ServiceImpl<UserLoginMapper, UserLogin
                 // 返回登录成功结果和JWT令牌
 
                 // 将用户ID和token存储到WebSocketService中
-                webSocketService.storeUserToken(one.getId()+"", jwtToken);
+//                webSocketService.storeUserToken(one.getId()+"", jwtToken);
 
 
                 return Result.OK("登录成功",jwtToken);