栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Springboot集成websocket聊天室功能

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Springboot集成websocket聊天室功能

WebSocket协议是基于TCP协议的一种长连接,只需要通过一次请求来初始化连接,可以实现服务器和客户端全双工通信。
利用Springboot实现遵循WebSocket协议的聊天室功能
达成效果如下:
窗口1:

窗口2:

窗口3:

前端代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>



    
    
    SpringBoot+WebSocket+JSP



    动力在线聊天室
    
        
        
    
    
        
        
            
            
            
        
    

    


前端代码是作为了客户端:
其中

这里引入了jquery.min的js文件,采用了bootstrap框架,form-group将同一个form组的内容放在一起,bootstrap给组与组之间加了一定的间距,类似段落。
这里将后端代码作为服务端,首先看一下后端代码的目录结构:

在控制层中

AtomicInteger用来实现用户数字的自动增长,AtomicInteger涉及到多线程安全方面相关知识,这个知识点,小编会专门出一期多线程方面的专题进行说明。用user与从0增长的数字组成username,这个username会在前端jsp文件和后端其他代码中出现
这里先介绍后端代码
首先先进行一个配置类的代码编写(这个可记为固定写法)

在endpoint层首先进行工具类WebSocketUtils的编写

package com.bjpowernode.endpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public final class WebSocketUtils {

    private static final Logger logger = LoggerFactory.getLogger(WebSocketUtils.class);

    
    public static final Map CLIENTS = new ConcurrentHashMap<>();

    
    public static void sendMessage(Session session, String message) {
        if (session == null) {
            return;
        }
        // 通过会话得到远程对象
        final RemoteEndpoint.Basic basic = session.getBasicRemote();
        if (basic == null) {
            return;
        }
        try {
            //发送
            basic.sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("sendMessage IOException ", e);
        }
    }

    
    public static void sendMessageAll(String message) {
        CLIENTS.forEach((sessionId, session) -> sendMessage(session, message));
    }

    
    public static String getonlineInfo() {
        Set userNames = CLIENTS.keySet();
        if (userNames.size() == 0) {
            return "当前无人在线...";
        }
        return CLIENTS.keySet().toString() + "在线";
    }
}


这里是一种固定写法,xxx.class中的xxx代表类名。可用logger.info()在控制台打印输出信息。
ConcurrentHashMap是J.U.C(java.util.concurrent包)的重要成员,它是HashMap的一个线程安全的、支持高效并发的版本。在多人聊天室中适用,关于HashMap线程安全这一块会在之后的专题中进行分析。
在sendMessage方法中,首先确定得有对话Session,RemoteEndpoint.Basic通过会话得到远程对象。当用户存在的时候,发送信息message。
在sendMessageAll方法中,

sessinID记录每个用户,用lambda表达式发送消息给其他人。
在getonlineInfo()方法中,用keySet取得key,也就是用户ID,用于统计在线人数。

最后进行ChatServerEndpoint类的编写,这里也是服务端业务编写的代码

package com.bjpowernode.endpoint;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;


@Slf4j //lombok jar包,帮我们自动生成一些代码:@Data
@Component
@ServerEndpoint("/websocket/{username}")
public class ChatServerEndpoint {

    
    @onOpen
    public void openSession(@PathParam("username") String username, Session session) {
        log.info("用户{}登录", username);
        String message = "用户[" + username + "] 已进入聊天室!";
        // 发送登录消息给其他人
        WebSocketUtils.sendMessageAll(message);

        // 获取当前在线人数,发给自己
        String onlineInfo = WebSocketUtils.getonlineInfo();

        //发送消息
        WebSocketUtils.sendMessage(session, onlineInfo);

        // 添加自己到map中
        WebSocketUtils.CLIENTS.put(username, session);
    }

    
    @onMessage
    public void onMessage(@PathParam("username") String username, String message) {
        log.info("发送消息:{}, {}", username, message);
        //广播,把消息同步给其他客户端
        WebSocketUtils.sendMessageAll("[" + username + "] : " + message);
    }

    
    @onClose
    public void onClose(@PathParam("username") String username, Session session) {
        // 当前的Session移除某个用户
        WebSocketUtils.CLIENTS.remove(username);

        // 离开消息通知所有人
        WebSocketUtils.sendMessageAll("[" + username + "] 已离开!");

        try {
            //关闭WebSocket Session会话
            session.close();
            log.info("{} 已退出, onclose", username);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("onClose error", e);
        }
    }

    
    @onError
    public void onError(Session session, Throwable throwable) {
        try {
            //关闭WebSocket Session会话
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("onError Exception", e);
        }
        log.info("Throwable msg " + throwable.getMessage());
    }
}

在类上的注解@ServerEndpoint("/websocket/{username}")申明这是一个websocket服务;需要指定访问该服务的地址,在地址中可以指定参数,需要通过{}进行占位;@Slf4j 帮我们自动生成一些代码;@Component实现bean的注入。
@OnOpen
public void openSession(@PathParam(“username”) String username, Session session)
该方法将在建立连接后执行,会传入session对象,就是客户端与服务端建立的长连接通道,通过@PathParam获取url中声明的参数。

@OnMessage
public void onMessage(@PathParam(“username”) String username, String message)
该方法用于接收客户端发送的消息;
message:发来的消息数据;

@OnClose
public void onClose(@PathParam(“username”) String username, Session session)
该方法是在连接关闭后执行。当前会话对象Session移除该用户,再把该用户离开消息通知给所有聊天室窗口;关闭对话通道,并在输出台打印相关信息。


这里让上方可读文本框接收到下方书写后点击发送的文字内容。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/358163.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号