基于WebSocket实现一个简易的群聊功能

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

引入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>

项目的目录结构

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

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, 建立一个连接,模拟一个客户端。

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

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

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

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

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

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

如果觉得这篇文章对你有所帮助,还请帮忙点赞、在看、转发一下,码字不易,非常感谢!

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现基于 WebSocket 的聊天室单聊和群聊,可以分为以下几个步骤: 1. 创建 SpringBoot 项目:使用 SpringBoot 创建一个后端项目,添加 WebSocket 依赖。 2. 配置 WebSocket:在 SpringBoot 项目中添加配置类,开启 WebSocket 支持,并注册 WebSocket 处理器。 3. 创建前端项目:使用 Vue 创建一个前端项目,安装 WebSocket 库。 4. 实现单聊和群聊功能:前端和后端通过 WebSocket 进行通信,前端发送消息到后端后端将收到的消息进行处理,然后再将消息发送给前端。 下面是一个简单的示例代码: 后端代码: 1. 添加 WebSocket 依赖 ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. WebSocket 配置类 ``` @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new WebSocketHandler(), "/ws").setAllowedOrigins("*"); } } ``` 3. WebSocket 处理器 ``` @Component public class WebSocketHandler extends TextWebSocketHandler { private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.put(session.getId(), session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessions.remove(session.getId()); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 处理收到的消息 String payload = message.getPayload(); JSONObject jsonObject = JSONObject.parseObject(payload); String type = jsonObject.getString("type"); String content = jsonObject.getString("content"); String from = jsonObject.getString("from"); String to = jsonObject.getString("to"); if("chat".equals(type)) { // 单聊 WebSocketSession toSession = sessions.get(to); if(toSession != null && toSession.isOpen()) { TextMessage textMessage = new TextMessage(content); toSession.sendMessage(textMessage); } } else if("group".equals(type)) { // 群聊 for(WebSocketSession session1 : sessions.values()) { if(session1.isOpen()) { TextMessage textMessage = new TextMessage(content); session1.sendMessage(textMessage); } } } } } ``` 前端代码: 1. 安装 WebSocket 库 ``` npm install --save sockjs-client npm install --save stompjs ``` 2. 连接 WebSocket ``` import SockJS from 'sockjs-client' import Stomp from 'stompjs' let stompClient = null; function connect() { const socket = new SockJS('/ws'); stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { console.log('Connected: ' + frame); stompClient.subscribe('/topic/chat', function (message) { // 接收到消息 console.log(message); }); }); } connect(); ``` 3. 发送消息 ``` function sendChatMessage() { const message = { type: 'chat', content: 'hello', from: 'user1', to: 'user2' }; stompClient.send('/app/chat', {}, JSON.stringify(message)); } ``` 以上代码仅为示例,具体实现还需要根据具体需求进行修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值