【2023最新】SpringBoot整合WebSocket实现简易私聊聊天室

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、WebSocket是什么?

1.1 为什么会有WebSocket这项技术?

在比较早的时期,很多网站做一种实时推送的功能(服务端需要向客户端主动推送数据),所用的技术都是轮询/短轮询。轮询指的是客户端定期的向服务端发起HTTP请求来获取到服务端返回数据给客户端,WebSocket与轮询的区别如下:
在这里插入图片描述

1.2 简介

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 把客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

1.3 优缺点

优点:
  1. 减少开销:服务端能够主动向客户端推送数据,避免了不必要资源开销;
  2. 更强的实时性:因为协议是全双工的,所以服务器可以随时向客户端推送数据;相对HTTP请求需要等待客户端发起请求服务端才能够响应数据,延迟明显更少;
  3. 保持连接状态:与 HTTP 不同的是,WebSocket 需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息;
  4. 更好的二进制支持:WebSocket 定义了二进制帧,相对 HTTP,可以更轻松地处理二进制内容;
缺点:
  1. 因为是长连接:所以受网络限制比较大,需要处理好重连机制,比如地铁这种网络比较差的环境容易断开,这个时候就需要重连了;
  2. 各个浏览器支持程度不一样;

二、编码步骤

1.引入依赖

代码如下(示例):

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.25</version>
        </dependency>

    </dependencies>

2.编写WebScoket配置类

代码如下(示例):

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

3.编写WebScoketServer服务

代码如下(示例):

@Component
@Slf4j
@ServerEndpoint("/webSocketServer/{myUserId}")
public class WebSocketServer {

    /**
     * 与客户端的连接会话,需要通过他来给客户端发消息
     */
    private Session session;

    /**
     * 当前用户ID
     */
    private String userId;

    /**
     *  concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
     *  虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。
     */
    private static CopyOnWriteArraySet<WebSocketServer> webSockets =new CopyOnWriteArraySet<>();

    /**
     *用来存在线连接用户信息
     */
    private static ConcurrentHashMap<String,Session> sessionPool = new ConcurrentHashMap<String,Session>();

    /**
     * 连接成功方法
     * @param session 连接会话
     * @param userId 用户编号
     */
    @OnOpen
    public void onOpen(Session session , @PathParam("myUserId") String userId){
        try {
            this.session = session;
            this.userId = userId;
            webSockets.add(this);
            sessionPool.put(userId, session);
            log.info("【websocket消息】 用户:" + userId + " 加入连接...");
        } catch (Exception e) {
            log.error("---------------WebSocket连接异常---------------");
        }
    }

    /**
     * 关闭连接
     */
    @OnClose
    public void onClose(){
        try {
            webSockets.remove(this);
            sessionPool.remove(this.userId);
            log.info("【websocket消息】 用户:"+ this.userId + " 断开连接...");
        } catch (Exception e) {
            log.error("---------------WebSocket断开异常---------------");
        }
    }

    @OnMessage
    public void onMessage(@PathParam("myUserId") String userId, String body){
        try {
            //将Body解析
            JSONObject jsonObject = JSONObject.parseObject(body);
            //获取目标用户地址
            String targetUserId = jsonObject.getString("targetUserId");
            //获取需要发送的消息
            String message = jsonObject.getString("message");
            jsonObject.put("userId" , userId);
            if(userId.equals(targetUserId)){
                sendMoreMessage(new String[]{targetUserId} ,  JSONObject.toJSONString(jsonObject));
            }else{
                sendMoreMessage(new String[]{userId , targetUserId} ,  JSONObject.toJSONString(jsonObject));
            }
        } catch (Exception e) {
            log.error("---------------WebSocket消息异常---------------");
        }
    }


    /**
     * 此为广播消息
     * @param message
     */
    public void sendAllMessage(String message) {
        log.info("【websocket消息】广播消息:"+message);
        for(WebSocketServer webSocket : webSockets) {
            try {
                if(webSocket.session.isOpen()) {
                    webSocket.session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                log.error("---------------WebSocket消息广播异常---------------");
            }
        }
    }

    /**
     * 单点消息
     * @param userId
     * @param message
     */
    public void sendOneMessage(String userId, String message) {
        Session session = sessionPool.get(userId);
        if (session != null&&session.isOpen()) {
            try {
                log.info("【websocket消息】 单点消息:"+message);
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                log.error("---------------WebSocket单点消息发送异常---------------");
            }
        }
    }

    /**
     * 发送多人单点消息
     * @param userIds
     * @param message
     */
    public void sendMoreMessage(String[] userIds, String message) {
        for(String userId:userIds) {
            Session session = sessionPool.get(userId);
            if (session != null&&session.isOpen()) {
                try {
                    log.info("【websocket消息】 单点消息:"+message);
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    log.error("---------------WebSocket多人单点消息发送异常---------------");
                }
            }
        }
    }
}

项目结构
在这里插入图片描述

4.编写一个简单的html进行交互

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
    <style>
        #content {
            overflow: auto;
            width: 500px;
            height: 300px;
            background-color: white;
        }

        body {
            background-color: lightblue;
        }
    </style>
</head>
<body>
<div>
    <div id="content">
    </div>
    <p><label for="myUserId">用户名称:</label><input type="text" name="myUserId" id="myUserId"
                                                     placeholder="用户名称"><input type="submit" value="登录"
                                                                                   id="login"/></p>
    <p><label for="targetUserId">目标用户名称:</label><input type="text" name="targetUserId" id="targetUserId"
                                                             placeholder="目标用户名称"></p>
    <textarea name="message" id="message" cols="38" rows="10" placeholder="消息..."></textarea>
    <p><input type="submit" id="send" value="发送"/></p>
    </form>
</div>

</body>
</html>

<script>
    $(function () {
        var websocket = null;
        $("#login").on('click', function () {
            let myUserId = $("#myUserId").val();
            websocket = new WebSocket("ws://localhost:8080/webSocketServer/" + myUserId);
            // 连接成功后的回调函数
            socket();
        });

        function socket(){
            websocket.onopen = function (params) {
                console.log('客户端连接成功')
            };

            websocket.onmessage = function (e) {
                var data = JSON.parse(e.data);
                if(data.userId == $("#myUserId").val()){
                    $("#content").append(`<div style="width: 500px;height:40px;line-height: 30px;"><p style="float:right;margin:0;padding:0;">我:${data.message}</p></div>`);
                }else{
                    $("#content").append(`<div style="width: 500px;height:40px;line-height: 30px;"><p style="float:left;margin:0;padding:0;">${data.userId}${data.message}</p></div>`);
                }
            };

            websocket.onclose = function (evt) {
                console.log("关闭客户端连接");
            };

            websocket.onerror = function (evt) {
                console.log("连接失败了");
            };
        }
        
        $("#send").on('click', function () {
            websocket.send(`{"targetUserId": "${$("#targetUserId").val()}" , "message": "${$("#message").val()}"}`);
        });
    });
</script>

三、测试

1.准备网页

在网页中,输入用户名称点击登录进行登录(在F12中看到客户端连接成功就表示成功登陆了):
在这里插入图片描述

2.发送消息

在网页中输入目标用户名称,然后输入需要发送的消息,点击发送即可:
在这里插入图片描述
到这简易的私聊聊天室就完成啦!!!

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: Spring Boot是一个用于快速构建基于Spring框架的Java应用程序的开源框架。它简化了Spring应用程序的开发过程,并提供了许多内置的功能和插件,使得开发人员可以更加专注于业务逻辑的实现WebSocket是一种在Web浏览器和Web服务器之间建立持久连接的通信协议,能够实现实时双向通信。 要实现聊天软件的功能,可以使用Spring Boot来快速搭建项目结构和配置。首先,需要在pom.xml文件中添加WebSocket的依赖,例如使用SpringSpring WebSocket库: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 然后,需要创建一个WebSocket配置类来配置WebSocket的相关信息,例如定义访问WebSocket的端点、配置消息传输方式等。可以继承Spring提供的AbstractWebSocketMessageBrokerConfigurer类,并重写相关方法: ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/chat").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic"); registry.setApplicationDestinationPrefixes("/app"); } } ``` 在上述配置类中,使用"/chat"作为WebSocket的端点,并启用了基于内存的消息代理(SimpleBroker),其中"/topic"为消息主题的前缀,"/app"为应用程序请求的前缀。 接下来,可以创建一个WebSocket处理器类来处理WebSocket的连接、关闭和消息等事件。可以实现SpringWebSocketHandler接口,并重写相关方法: ```java @Component public class ChatHandler extends TextWebSocketHandler { private static final List<WebSocketSession> sessions = new ArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.add(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessions.remove(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { for (WebSocketSession s : sessions) { s.sendMessage(message); } } } ``` 上述处理器类中,使用一个静态List来保存所有连接的WebSocketSession,以便将消息发送给所有已连接的客户端。 最后,在需要使用WebSocket的控制器或服务中,可以使用@Autowired注解将ChatHandler注入,并使用它来发送消息。 总结来说,通过以上的步骤,我们可以使用Spring Boot整合WebSocket实现聊天软件的功能。当有新的WebSocket连接建立时,我们将其保存在一个静态List中,并在收到消息时将消息发送给所有的连接。通过Spring Boot的简化开发流程和WebSocket的实时双向通信特性,实现了一个简单的聊天软件。 ### 回答2: Spring Boot是一个用于开发Java应用程序的框架,它能够帮助开发人员更快速、更简洁地构建应用程序。WebSocket是HTML5新增的一种协议,它能够在客户端与服务器之间建立持久的双向通信连接,实时地传输数据。 要实现聊天软件的功能,首先需要导入Spring BootWebSocket的相关依赖。在pom.xml文件中添加Spring BootWebSocket的依赖项。 在Spring Boot的主类中,使用@EnableWebSocket注解启用WebSocket的支持。编写一个WebSocket处理器类,继承自TextWebSocketHandler,并重写其中的方法。在onTextMessage方法中处理接收到的文本消息,在sendMessage方法中处理发送消息。 配置WebSocket的映射路径和处理器,使用@Configuration注解和实现WebSocketConfigurer接口。重写registerWebSocketHandlers方法,设置WebSocket的映射路径和处理器。 在前端界面中,使用JavaScript代码连接WebSocket服务器,并处理接收消息和发送消息的逻辑。通过WebSocket对象的onmessage方法处理接收到的消息,并将消息显示在聊天界面上。通过WebSocket对象的send方法发送消息给服务器。 通过以上步骤,就可以实现Spring BootWebSocket整合,从而实现聊天软件的功能。开发人员可以根据具体的需求,进一步完善聊天软件的功能,例如用户名的验证、消息的存储和管理等。 总结起来,使用Spring BootWebSocket可以快速、简洁地实现聊天软件。借助Spring Boot的开发效率和WebSocket的实时通信功能,开发人员能够轻松地构建出高效、稳定的聊天软件。 ### 回答3: Spring Boot 是一个基于 Spring 框架的开源服务端开发框架,提供了快速开发和方便部署的特性。WebSocket 是一种基于TCP协议的双向通信协议,通过浏览器与服务器建立持久连接,实现实时通信。 使用 Spring Boot 整合 WebSocket 实现聊天软件的步骤如下: 1. 创建一个 Spring Boot 项目,引入 WebSocket 依赖包。 2. 在配置类上添加 `@EnableWebSocket` 注解以启用 WebSocket 功能。 3. 创建一个 WebSocket 处理器类,继承自 `TextWebSocketHandler`,覆写其中的方法,如 `handleTextMessage()` 和 `afterConnectionEstablished()`。 4. 在 `handleTextMessage()` 方法中,获取客户端发送的消息,处理后将消息发送给所有连接到服务器的客户端。 5. 在 `afterConnectionEstablished()` 方法中,可以处理客户端连接成功后的逻辑。 6. 创建一个控制器类,处理客户端与服务器的交互,如发送消息、接收消息等。 7. 在控制器类中,使用 `@Autowired` 注入 WebSocket 处理器类的对象,并通过该对象发送消息给客户端。 8. 在前端页面中使用 JavaScript 创建 WebSocket 连接,并实现相应的回调函数,实现与服务器的实时通信。 通过以上步骤,可以实现一个简单的聊天软件。用户在页面上发送消息,消息通过 WebSocket 连接发送到服务器,服务器将消息广播给所有客户端,实现实时聊天的功能。 总之,借助 Spring Boot 提供的便利性和 WebSocket 协议的实时通信特性,可以快速实现一个聊天软件。不仅可以在浏览器上实现聊天功能,还可以通过移动端等其他客户端实现跨平台的聊天应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值