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);
    }
}


相关文章
|
2月前
|
前端开发 JavaScript UED
探索Python Django中的WebSocket集成:为前后端分离应用添加实时通信功能
通过在Django项目中集成Channels和WebSocket,我们能够为前后端分离的应用添加实时通信功能,实现诸如在线聊天、实时数据更新等交互式场景。这不仅增强了应用的功能性,也提升了用户体验。随着实时Web应用的日益普及,掌握Django Channels和WebSocket的集成将为开发者开启新的可能性,推动Web应用的发展迈向更高层次的实时性和交互性。
83 1
|
3月前
|
存储 JavaScript 前端开发
webSocket+Node+Js实现在线聊天(包含所有代码)
文章介绍了如何使用WebSocket、Node.js和JavaScript实现在线聊天功能,包括完整的前端和后端代码示例。
187 0
|
2月前
|
网络协议 API 网络安全
Web实时通信的学习之旅:轮询、WebSocket、SSE的区别以及优缺点
Web实时通信的学习之旅:轮询、WebSocket、SSE的区别以及优缺点
177 0
|
2月前
|
网络协议 安全 JavaScript
Web实时通信的学习之旅:WebSocket入门指南及示例演示
Web实时通信的学习之旅:WebSocket入门指南及示例演示
163 0
|
4月前
|
Ubuntu Linux
内核实验(九):添加IO驱动的阻塞读写功能
本文通过修改内核模块代码,介绍了如何在Linux内核中为IO驱动添加阻塞读写功能,使用等待队列和条件唤醒机制来实现读写操作的阻塞和非阻塞模式,并在Qemu虚拟机上进行了编译、部署和测试。
19 0
|
4月前
|
Linux C++ Docker
【Azure 应用服务】App Service for Linux 中实现 WebSocket 功能 (Python SocketIO)
【Azure 应用服务】App Service for Linux 中实现 WebSocket 功能 (Python SocketIO)
|
5月前
|
前端开发 JavaScript API
探索Python Django中的WebSocket集成:为前后端分离应用添加实时通信功能
【7月更文挑战第17天】现代Web开发趋势中,前后端分离配合WebSocket满足实时通信需求。Django Channels扩展了Django,支持WebSocket连接和异步功能。通过安装Channels、配置设置、定义路由和消费者,能在Django中实现WebSocket交互。前端使用WebSocket API连接后端,实现双向数据流,如在线聊天功能。集成Channels提升Web应用的实时性和用户体验,适应实时交互场景的需求。**
207 6
|
5月前
|
存储 缓存 JavaScript
WebSocket 学习
WebSocket是用于创建低延迟、高效率双向通信的协议,适合实时数据传输如即时通讯和在线游戏。它通过一次性握手建立长期连接,允许服务器主动推送数据。WebSocket API包括WebSocket对象和事件处理程序,如onopen、onmessage、onerror和onclose。示例代码展示了如何创建WebSocket连接、发送和接收消息及处理各种事件。WebSocket服务器通常需要特定的框架支持,如Node.js中的`ws`库。使用WebSocket时,前端和后端都可以监听open、close、error和message事件来管理连接状态和数据交换。
99 8
|
4月前
|
JavaScript 前端开发 网络协议
WebSocket在Java Spring Boot+Vue框架中实现消息推送功能
在现代Web应用中,实时消息提醒是一项非常重要的功能,能够极大地提升用户体验。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,为实现实时消息提醒提供了高效且低延迟的解决方案。本文将详细介绍如何在Java Spring Boot后端和Vue前端框架中利用WebSocket实现消息提醒功能。
186 0
|
7月前
|
移动开发 前端开发 JavaScript
uniapp中IO模块(管理本地文件系统)的常用功能封装
uniapp中IO模块(管理本地文件系统)的常用功能封装
645 1