t-io websocket的聊天功能学习记录(二)

简介: t-io websocket的聊天功能学习记录(二)

对于t-io的消息处理主要通过下面的类来完成

其中

1、handshake 这个部分是握手,这里前端传入用户,根据用户进行tio的绑定与群组绑定;

2、onText 这个对于消息的处理,对心跳,正常消息等进行处理

代码如下:

@Component
public class TioWsMsgHandler implements IWsMsgHandler {
    private static final Logger log = LoggerFactory.getLogger(TioWsMsgHandler.class);
    public static TioConfig tioConfig;
    @Resource
    private IImUserService imUserService;
    @Resource
    private IImMessageService iImMessageService;
    
    @Resource
    private IImThirdService iImThirdService;
    /**
     * 握手时走这个方法,业务可以在这里获取cookie,request参数等
     *
     * @param request        request
     * @param httpResponse   httpResponse
     * @param channelContext channelContext
     * @return HttpResponse
     */
    @Override
    public HttpResponse handshake(HttpRequest request, HttpResponse httpResponse, ChannelContext channelContext) {
        tioConfig = channelContext.tioConfig;
        String userName = request.getParam("name");
        SysUser loginUser = iImThirdService.getUserByName(userName);
        if(Objects.isNull(loginUser)) {
            log.info("handshake:" + "无法获得登录用户信息!");
            return httpResponse;
        }
        //String userName = loginUser.getUsername();
        // 先关闭原先的连接
        Tio.closeUser(tioConfig, userName, null);
        // 绑定用户
        Tio.bindUser(channelContext, userName);
        // 在线用户绑定到上下文 用于发送在线消息
        WsOnlineContext.bindUser(userName, channelContext);
        // 绑定群组
        List<ImChatGroup> groups = imUserService.getChatGroups(userName);
        for (ImChatGroup group : groups) {
            Tio.bindGroup(channelContext, group.getId());
        }
        return httpResponse;
    }
    /**
     * @param httpRequest    httpRequest
     * @param httpResponse   httpResponse
     * @param channelContext channelContext
     * @throws Exception Exception
     * @author tanyaowu tanyaowu
     */
    @Override
    public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
    }
    /**
     * 字节消息(binaryType = arraybuffer)过来后会走这个方法
     */
    @Override
    public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        return null;
    }
    /**
     * 当客户端发close flag时,会走这个方法
     */
    @Override
    public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        Tio.remove(channelContext, "receive close flag");
        return null;
    }
    /**
     * 字符消息(binaryType = blob)过来后会走这个方法
     *
     * @param wsRequest      wsRequest
     * @param text           text
     * @param channelContext channelContext
     * @return obj
     */
    @Override
    public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            SendInfo sendInfo = objectMapper.readValue(text, SendInfo.class);
            System.out.println("onText " + text);
            //心跳检测包
            if (ChatUtils.MSG_PING.equals(sendInfo.getCode())) {
                WsResponse wsResponse = WsResponse.fromText(text, TioServerConfig.CHARSET);
                Tio.send(channelContext, wsResponse);
            }
            //真正的消息
            else if (ChatUtils.MSG_MESSAGE.equals(sendInfo.getCode())) {
                Message message = sendInfo.getMessage();
                message.setMine(false);
                WsResponse wsResponse = WsResponse.fromText(objectMapper.writeValueAsString(sendInfo), TioServerConfig.CHARSET);
                //单聊
                if (ChatUtils.MESSAGE_TYPE_FRIEND.equals(message.getType())) {
                    SetWithLock<ChannelContext> channelContextSetWithLock = Tio.getByUserid(channelContext.tioConfig, message.getId());
                    //用户没有登录,存储到离线文件
                    if (channelContextSetWithLock == null || channelContextSetWithLock.size() == 0) {
                        saveMessage(message, ChatUtils.READ_TYPE_UNREAD);
                    } else {
                        Tio.sendToUser(channelContext.tioConfig, message.getId(), wsResponse);
                        //入库操作
                        saveMessage(message, ChatUtils.READ_TYPE_READ);
                    }
                    if("admin".equals(message.getId())){
                        SendInfo sendInfo1 = ObjectUtil.cloneByStream (sendInfo);
                        Message message1 = sendInfo1.getMessage();
                        message1.setUsername("管理员");
                        message1.setAvatar("http://192.168.199.152:9010/nbcio/temp/nbcio_1660480947146.png");
                        message1.setMine(false);
                        message1.setId(message.getFromname());
                        message1.setFromname("admin");
                        message1.setContent("欢迎使用NBCIO 亿事达企业管理平台!");
                        sendInfo1.setMessage(message1);
                        WsResponse wsResponse1 = WsResponse.fromText(objectMapper.writeValueAsString(sendInfo1), TioServerConfig.CHARSET);
                        Tio.sendToUser(channelContext.tioConfig, message.getFromname(), wsResponse1);
                    }
                } else {
                    Tio.sendToGroup(channelContext.tioConfig, message.getId(), wsResponse);
                    //入库操作
                    saveMessage(message, ChatUtils.READ_TYPE_READ);
                }
            }
            //准备就绪,需要发送离线消息
            else if (ChatUtils.MSG_READY.equals(sendInfo.getCode())) {
                //未读消息
                sendOffLineMessage(channelContext, objectMapper);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        //返回值是要发送给客户端的内容,一般都是返回null
        return null;
    }
    /**
     * 未读消息
     *
     * @param channelContext channelContext
     * @param objectMapper   objectMapper
     * @throws IOException 抛出异常
     */
    private void sendOffLineMessage(ChannelContext channelContext, ObjectMapper objectMapper) throws IOException {
        List<ImMessage> imMessageList = iImMessageService.getUnReadMessage(channelContext.userid);
        for (ImMessage imMessage : imMessageList) {
            Message message = new Message();
            message.setId(imMessage.getToName());
            message.setMine(false);
            message.setType(imMessage.getType());
            SysUser imUser = imUserService.getByName(imMessage.getFromName());
            message.setUsername(imUser.getUsername());
            message.setCid(String.valueOf(imMessage.getId()));
            message.setContent(imMessage.getContent());
            message.setTimestamp(System.currentTimeMillis());
            message.setFromname(imMessage.getFromName());
            message.setAvatar(imUser.getAvatar());
            SendInfo sendInfo1 = new SendInfo();
            sendInfo1.setCode(ChatUtils.MSG_MESSAGE);
            sendInfo1.setMessage(message);
            WsResponse wsResponse = WsResponse.fromText(objectMapper.writeValueAsString(sendInfo1), TioServerConfig.CHARSET);
            Tio.sendToUser(channelContext.tioConfig, message.getId(), wsResponse);
        }
    }
    /**
     * 保存信息
     *
     * @param message    信息
     * @param readStatus 是否已读
     */
    private void saveMessage(Message message, String readStatus) {
        ImMessage imMessage = new ImMessage();
        imMessage.setToName(message.getUsername());
        imMessage.setFromName(message.getFromname());
        imMessage.setSendTime(System.currentTimeMillis());
        imMessage.setContent(message.getContent());
        imMessage.setReadStatus(readStatus);
        imMessage.setType(message.getType());
        iImMessageService.saveMessage(imMessage);
    }
}


相关文章
|
1月前
|
移动开发 前端开发 JavaScript
uniapp中IO模块(管理本地文件系统)的常用功能封装
uniapp中IO模块(管理本地文件系统)的常用功能封装
|
1月前
t-io websocket的聊天功能学习记录(一)
t-io websocket的聊天功能学习记录(一)
23 0
|
1月前
|
数据采集 人工智能 异构计算
LabVIEW编程LabVIEW开发 PXI-6259多功能IO模块 例程与相关资料
LabVIEW编程LabVIEW开发 PXI-6259多功能IO模块 例程与相关资料
26 0
|
1月前
|
缓存 监控 前端开发
【Go 语言专栏】Go 语言中的 WebSocket 与 Socket.IO 集成
【4月更文挑战第30天】本文介绍了在 Go 语言中集成 WebSocket 与 Socket.IO 的相关技术,WebSocket 是一种高效的双向通信协议,Socket.IO 是一个实时通信库,提供丰富的事件处理。集成两者能实现更强大的实时通信功能。文章讨论了 Go 中 WebSocket 的实现,Socket.IO 与 WebSocket 的关系,集成的意义及步骤,并提醒注意协议兼容性、消息格式等问题。此外,还提到了性能优化策略和应用案例,如实时聊天、数据监控和在线协作工具。通过集成,开发者可以构建出满足多样化需求的实时通信应用。
|
1月前
|
资源调度 JavaScript 前端开发
❤Nodejs 第十五章(简单websocket聊天实现)
【4月更文挑战第15天】本文介绍了在Node.js中实现简单WebSocket聊天的过程。首先通过`yarn`创建项目并安装`ws`和`express`依赖。接着,编写`WebSocketServer.js`建立WebSocket服务器,处理客户端连接、消息收发及错误。然后,用`server.js`创建一个静态文件服务器,提供`index.html`。`index.html`包含客户端的WebSocket连接和消息处理。启动两个服务器后,可以在浏览器中打开`index.html`进行聊天。最后,讨论了在Node.js 20+Vite环境下使用WebSocket时可能遇到的问题
29 0
|
19天前
|
Java
io读两个文件,生成list 排重后写本地文件(Java)
io读两个文件,生成list 排重后写本地文件(Java)
|
23天前
|
存储 Java API
Java语言IO(输入/输出)编程技术深度解析
Java语言IO(输入/输出)编程技术深度解析
252 1
|
27天前
|
存储 Java API
Java IO流
Java IO流
28 2
|
30天前
|
存储 Java
Java IO流:深入解析与技术应用
Java IO流:深入解析与技术应用
264 1
|
1月前
|
存储 Java API
【JAVA学习之路 | 进阶篇】IO流及流的分类
【JAVA学习之路 | 进阶篇】IO流及流的分类