用WebSocket实现一个简易的群聊功能,so easy

简介: 本文主要来讲解如何使用WebSocket来实现一个简易的群聊功能。

大家好,我是三友~~

本文主要来讲解如何使用WebSocket来实现一个简易的群聊功能。

公众号:三友的java日记

引入maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.2.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
    <version>2.2.5.RELEASE</version>
</dependency>

搭建项目

项目的目录结构

image.png

接下来,我们来分析每个类的作用。

WebSocketApplication

@SpringBootApplication
public class WebSocketApplication {
   
   
    public static void main(String[] args) {
   
   
        SpringApplication.run(WebSocketApplication.class, args);
    }
}

这个类就是一个简单的启动引导类的功能。

WebSocketServer:群聊核心类

@Component
@ServerEndpoint(value = "/chat/{username}", configurator = SpringBasedConfigurator.class)
public class WebSocketServer {
   
   
    private final Map<Session, String> userSessionMap = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
   
   
        userSessionMap.put(session, username);
        multicastMessage(session, "欢迎" + username + "加入群聊!");
    }

    @OnMessage
    public void onMessage(Session session, String message) {
   
   
        String username = userSessionMap.get(session);
        multicastMessage(session, username + ": " + message);
    }

    @OnClose
    public void onClose(Session session) {
   
   
        String username = userSessionMap.remove(session);
        multicastMessage(session, username + "退出群聊。");
    }

    private void multicastMessage(Session session, String message) {
   
   
        for (Session userSession : userSessionMap.keySet()) {
   
   
            if (userSession == session) {
   
   
                //是自己,忽略
                continue;
            }
            try {
   
   
                userSession.getBasicRemote().sendText(message);
            } catch (IOException e) {
   
   
                e.printStackTrace();
            }
        }
    }
}

@ServerEndpoint:作用是用来表明当前类是一个节点类,当连接成功之后,用户的操作都会回调这个类对应的对象的方法,对象怎么创建的是根据configurator 属性对应的类来实现的,默认是每个连接对应的对象都是通过反射构建的,但是对于本群聊功能来说,是通过SpringBasedConfigurator对象来获取,这个类的作用接下来会剖析。

@OnOpen:当客户端与服务端建立连接的时候,会回调 @OnOpen 注解标记的方法

@PathParam:可以看成跟spring mvc中的@PathVariable注解作用一样,就是取出连接路径中的占位符对应的值

@OnMessage:当客户端发送消息给服务端的时候,会回调OnMessage 注解标记的方法

@OnClose:当客户端断开连接的时候,会回调@OnClose注解标记的方法。

Session:是代表当前客户端与服务端建立的一个会话,通过这个对象,服务端可以主动给客户端发送消息。

WebSocketServer这个类的主要作用是保存每个客户端与服务端建立的连接,一旦有客户端跟服务端建立连接、发送消息、断开连接,都会发送消息给其他客户端,从而实现群聊的功能。

SpringBasedConfigurator

@Component
public class SpringBasedConfigurator extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
   
   

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
   
   
        SpringBasedConfigurator.applicationContext = applicationContext;
    }

    @Override
    public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
   
   
        return applicationContext.getBean(clazz);
    }

}

这个类是继承了WebSocket包提供的api ServerEndpointConfig.Configurator ,重写了 getEndpointInstance 方法,主要是因为WebSocket是通过调用getEndpointInstance方法来获取每个连接对应调用的对象, 而getEndpointInstance方法默认是通过直接通过反射构造的,而不是从spring容器获取连接对象,导致类中的像@Resource 这类注解无法生效,所以重写了getEndpointInstance方法,让每个连接对应调用的对象都是从spring容器中获取

WebSocketConfiguration:配置类

@Configuration
public class WebSocketConfiguration {
   
   

    /**
     * 这个类的主要注册每个加了{@link javax.websocket.server.ServerEndpoint}的 spring bean节点,这算是spring整合websocket的一个体现
     * 具体是怎么实现注册的,可以看看 {@link ServerEndpointExporter#afterSingletonsInstantiated()}方法的实现
     *
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
   
   
        return new ServerEndpointExporter();
    }

}

暴露每个加@ServerEndpoint注解的spring bean,算是spring跟WebSocket整合的一处体现。

测试

好了,说完这些类的功能,那么开启测试吧。WebSocket客户端,我们使用https://www.idcd.com/tool/socket网站来模拟。

通过启动引导类来启动项目之后,我们输入 ws://localhost:8080/chat/sanyou, 建立一个连接,模拟一个客户端。

image.png

输入连接地址,点击连接,就会显示连接成功,username这里我们填sanyou,填什么都无所谓,相当于一个名字。

我们再建立一个连接,模拟另一个客户端。

image.png

第一个客户端就会显示这条信息。

image.png

接下来,就可以在发送栏往服务端发送消息,服务端会转给其他的客户端,实现群聊的功能,效果如下。

image.png

image.png

如果还想加入群聊,另外建立连接就行了,这样,一个简易的群聊功能就完成了。

以上就是本篇文章的全部内容,代码我已经上传到https://github.com/sanyou3/sanyou-parent.git 仓库上了,有更详细的注释,如有需要欢迎自行clone,同时如果你有什么不懂或者想要交流的地方,欢迎关注微信公众号来联系我,我们下篇文章再见。

PS:如果觉得这篇文章对你有帮助,欢迎大家关注公众号三友的java日记、分享、点赞、在看,感谢支持。

往期热门文章推荐

如何去阅读源码,我总结了18条心法

如何写出漂亮代码,我总结了45个小技巧

三万字盘点Spring/Boot的那些常用扩展点

三万字盘点Spring 9大核心基础功能

万字+20张图剖析Spring启动时12个核心步骤

1.5万字+30张图盘点索引常见的11个知识点

两万字盘点那些被玩烂了的设计模式

搜索关注公众号 三友的java日记 ,及时干货不错过,公众号致力于通过画图加上通俗易懂的语言讲解技术,让技术更加容易学习,回复 面试 即可获得一套面试真题。

相关文章
|
6月前
|
开发框架 前端开发 NoSQL
推荐一个.Net Core开发的Websocket群聊、私聊的开源项目
推荐一个.Net Core开发的Websocket群聊、私聊的开源项目
53 0
|
10月前
|
前端开发 JavaScript
Netty异步NIO框架(二)websocket 前端后端聊天 私聊及群聊
Netty异步NIO框架(二)websocket 前端后端聊天 私聊及群聊
|
存储 JavaScript 开发者
Vue合理配置WebSocket并实现群聊
Vue合理配置WebSocket并实现群聊
Vue合理配置WebSocket并实现群聊
|
XML Java 数据格式
spring websocket 和socketjs实现单聊群聊,广播的消息推送详解
spring websocket 和socketjs实现单聊群聊,广播的消息推送详解 WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。
2834 0
|
网络协议 前端开发 安全
websocket和http的瓜葛以及websocket协议实现
websocket和http的瓜葛以及websocket协议实现
websocket和http的瓜葛以及websocket协议实现
|
JavaScript
js实现websocket实例
js实现websocket实例
195 0
|
消息中间件 网络协议 前端开发
SpringBoot轻松整合WebSocket,实现Web在线聊天室
前面为大家讲述了 Spring Boot的整合Redis、RabbitMQ、Elasticsearch等各种框架组件;随着移动互联网的发展,服务端消息数据推送已经是一个非常重要、非常普遍的基础功能。今天就和大家聊聊在SpringBoot轻松整合WebSocket,实现Web在线聊天室,希望能对大家有所帮助。
SpringBoot轻松整合WebSocket,实现Web在线聊天室
|
网络协议 Linux 网络安全
php实现websocket实时消息推送
php实现websocket实时消息推送
429 0
php实现websocket实时消息推送
|
JavaScript 前端开发 Python
Python编程:tornado实现WebSocket通讯
以下实例有点像广播通讯,支持多个客户端连接 代码参考别人的,稍微做了一点点修改 服务器端 websocket_demo.py
98 0
Python编程:tornado实现WebSocket通讯