Springboot + Websocket的集成实现简单的聊天室功能

这篇具有很好参考价值的文章主要介绍了Springboot + Websocket的集成实现简单的聊天室功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、websocket的介绍

WebSocket是一种网络通信协议,它可以在单个TCP连接上实现双向(全双工)通信。WebSocket使用HTML5标准,并且可以在客户端和服务器之间建立持久连接,这意味着连接在浏览器刷新或关闭后仍然保持打开状态。

WebSocket的主要优点包括:

1. 双向通信:WebSocket支持客户端和服务器之间的双向通信,这使得实时数据传输变得非常容易。
2. 持久连接:WebSocket使用单个TCP连接,这使得服务器可以保持与客户端的通信,即使浏览器被关闭或刷新。
3. 零延迟:由于WebSocket使用单个TCP连接,因此数据传输不会出现延迟。
4. 更好的性能:WebSocket使用二进制传输,这使得数据传输速度更快。
5. 更好的可伸缩性:WebSocket可以处理大量的并发连接,因为它使用单个TCP连接。

二、springboot集成websocket(用注解的方式)

1.创建一个springboot项目,测试是否成功
package com.dong.websocket.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping(value = "/")
    public String index() {
        return "Hello World!";
    }
}
2.目录

java springboot 聊天室,后端,spring boot,websocket,后端

3.依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.dong</groupId>
	<artifactId>springboot_websocket</artifactId>
	<version>1.0.0-SNAPSHOT</version>
	<name>SpringBootProject</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>8</java.version>
	</properties>
	<dependencies>

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

		<!-- lombok -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.8</version>
		</dependency>

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

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

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
4.配置类
package com.dong.websocket.websocket;

import javax.websocket.server.ServerEndpoint;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter ServerEndpointExporter () {
        return new ServerEndpointExporter();
    }

}
5.监听类
package com.dong.websocket.websocket;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

/**
* 监听websocket地址/myWs
*/
@ServerEndpoint("/myWs")
@Component
@Slf4j
public class WsServeEndPont {

    // 线程安全的Map,用来保存session, static用来确保是属于类的而不是对象的
    static Map<String, Session> sessionMap = new ConcurrentHashMap<>(); 

    // 连接建立时执行的操作
    @OnOpen
    public void OnOpen (Session session) {
        sessionMap.put(session.getId(), session);
        log.info("websocket is open");
    }

    // 收到客户端消息执行的操作
    @OnMessage
    public String onMessage(String text) {
        log.info("收到了一条消息:" + text);
        return "已收到你的消息";
    }

    // 连接关闭时执行的操作
    @OnClose
      public void OnClose (Session session) {
        sessionMap.remove(session.getId());
        log.info("websocket is close");
    }

    // 定时任务:间隔时间2s 
    @Scheduled(fixedRate = 2000)
    public void sendMsg () {
        sessionMap.keySet().forEach(item->{
            try {
				sessionMap.get(item).getBasicRemote().sendText("心跳");
			} catch (IOException e) {
				e.printStackTrace();
			}
        });
    }
}
6.前端页面ws-client
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ws client</title>
</head>

<body>

</body>

<script>
    let ws = new WebSocket("ws://localhost:8080/myWs")
    ws.onopen= function () {
        ws.send("hello")
    }
    ws.onmessage = function (message) {
        console.log(message.data)
    }
</script>
</html>

三、springboot集成websocket(用spring框架实现)

1.Spring提供的类和接口
  • HttpSessionHandshakeInterceptor(抽象类):握手拦截器,在握手钱后添加操作
  • AbstractWebSocketHandler(抽象类):WebSocket处理程序,监听连接前,连接中,连接后
  • WebSocketConfigurer(接口):配置程序,比如配置监听哪个端口,自定义的握手拦截器,处理程序的使用
2.项目结构

java springboot 聊天室,后端,spring boot,websocket,后端

 3.SessionBean类,封装websocketsession和用户id标识
package com.dong.websocket.spring;

import org.springframework.web.socket.WebSocketSession;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class SessionBean {

    private WebSocketSession webSocketSession;

    private Integer clientId;

}
4.MyWsInterceptor类,握手拦截器
package com.dong.websocket.spring;

import java.util.Map;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import lombok.extern.slf4j.Slf4j;

/**
* 握手拦截器
*/
@Component
@Slf4j
public class MyWsInterceptor extends HttpSessionHandshakeInterceptor{

    @Override
    public boolean beforeHandshake (ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes ) throws Exception {
        log.info(request.getRemoteAddress().toString() + "开始握手");
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        log.info(request.getRemoteAddress().toString() + "完成握手");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}
5.MyWsHander类
package com.dong.websocket.spring;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import lombok.extern.slf4j.Slf4j;

/**
 * web socket 主处理程序
 */
@Slf4j
@Component
public class MyWsHandler extends AbstractWebSocketHandler {

    private static Map<String,SessionBean> sessionBeanMap ;

    private static AtomicInteger clientIdMaker;

    private static StringBuffer stringBuffer;

    static {
        sessionBeanMap = new ConcurrentHashMap<>();
        clientIdMaker = new AtomicInteger(0);
        stringBuffer = new StringBuffer();
    }

    //连接建立
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
        SessionBean sessionBean = new SessionBean(session,clientIdMaker.getAndIncrement());
        sessionBeanMap.put(session.getId(),sessionBean);
        log.info(sessionBeanMap.get(session.getId()).getClientId()+"建立了连接");
        stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+"进入了群聊<br/>");
        sendMessage(sessionBeanMap);
    }
    //收到消息
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
        log.info(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload());
        stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload()+"<br/>");
        sendMessage(sessionBeanMap);
    }
    //传输异常
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
        if(session.isOpen()){
            session.close();
        }
        sessionBeanMap.remove(session.getId());
    }
    //连接关闭
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        int clientId = sessionBeanMap.get(session.getId()).getClientId();
        sessionBeanMap.remove(session.getId());
        log.info(clientId+"关闭了连接");
        stringBuffer.append(clientId+"退出了群聊<br/>");
        sendMessage(sessionBeanMap);
    }

    //    //每2s发送给客户端心跳消息
//    @Scheduled(fixedRate = 2000)
//    public void sendMsg() throws IOException {
//        for(String key:sessionBeanMap.keySet()){
//            sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage("心跳"));
//        }
//    }
    public void sendMessage(Map<String,SessionBean> sessionBeanMap){
        for(String key:sessionBeanMap.keySet()){
            try {
                sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(stringBuffer.toString()));
            } catch (IOException e) {
//                e.printStackTrace();
                log.error(e.getMessage());
            }
        }
    }
}

6.MyWsConfig类

package com.dong.websocket.spring;

import javax.annotation.Resource;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class MyWsConfig implements WebSocketConfigurer {

    @Resource
    MyWsHandler myWsHandler;

    @Resource
    MyWsInterceptor myWsInterceptor;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myWsHandler, "/myWs1").addInterceptors(myWsInterceptor).setAllowedOrigins("*");
    }

}

四、实现一个简单的聊天室功能

1.ws-client.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ws client</title>
</head>
<body>
<p style="border:1px solid black;width: 600px;height: 500px" id="talkMsg"></p>
<input id="message" /><button id="sendBtn" onclick="sendMsg()">发送</button>
</body>
<script>
    let ws = new WebSocket("ws://localhost:8080/myWs1")
    // ws.onopen=function () {
    // }
    ws.onmessage=function (message) {
        document.getElementById("talkMsg").innerHTML = message.data
    }
    function sendMsg() {
        ws.send(document.getElementById("message").value)
        document.getElementById("message").value=""
    }
</script>
</html>

2.MyWsHandler

package com.dong.websocket.spring;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import lombok.extern.slf4j.Slf4j;

/**
 * web socket 主处理程序
 */
@Slf4j
@Component
public class MyWsHandler extends AbstractWebSocketHandler {

    private static Map<String,SessionBean> sessionBeanMap ;

    private static AtomicInteger clientIdMaker;

    private static StringBuffer stringBuffer;

    static {
        sessionBeanMap = new ConcurrentHashMap<>();
        clientIdMaker = new AtomicInteger(0);
        stringBuffer = new StringBuffer();
    }

    //连接建立
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
        SessionBean sessionBean = new SessionBean(session,clientIdMaker.getAndIncrement());
        sessionBeanMap.put(session.getId(),sessionBean);
        log.info(sessionBeanMap.get(session.getId()).getClientId()+"建立了连接");
        stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+"进入了群聊<br/>");
        sendMessage(sessionBeanMap);
    }
    //收到消息
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
        log.info(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload());
        stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload()+"<br/>");
        sendMessage(sessionBeanMap);
    }
    //传输异常
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
        if(session.isOpen()){
            session.close();
        }
        sessionBeanMap.remove(session.getId());
    }
    //连接关闭
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        int clientId = sessionBeanMap.get(session.getId()).getClientId();
        sessionBeanMap.remove(session);
        log.info(clientId+"关闭了连接");
        stringBuffer.append(clientId+"退出了群聊<br/>");
        sendMessage(sessionBeanMap);
    }

    //    //每2s发送给客户端心跳消息
//    @Scheduled(fixedRate = 2000)
//    public void sendMsg() throws IOException {
//        for(String key:sessionBeanMap.keySet()){
//            sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage("心跳"));
//        }
//    }
    public void sendMessage(Map<String,SessionBean> sessionBeanMap){
        for(String key:sessionBeanMap.keySet()){
            try {
                sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(stringBuffer.toString()));
            } catch (IOException e) {
//                e.printStackTrace();
                log.error(e.getMessage());
            }
        }
    }
}

效果:

第一个页面打开:

java springboot 聊天室,后端,spring boot,websocket,后端

 第二个页面打开并聊天

java springboot 聊天室,后端,spring boot,websocket,后端

demo链接:springboot-demo集合: demo集合 - Gitee.com文章来源地址https://www.toymoban.com/news/detail-842196.html

到了这里,关于Springboot + Websocket的集成实现简单的聊天室功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot与webSocket实现在线聊天室——实现私聊+群聊+聊天记录保存

    引用参考:原文章地址:https://blog.csdn.net/qq_41463655/article/details/92410518 在此基础上实现对聊天记录的保存。 代码地址:链接:https://pan.baidu.com/s/1IJFZDa4S_DF08773sKJWeA 提取码:jkui 思路:新建一个实体类用于保存聊天记录,在消息发送时,设置对象的各个值然后保存到数据库中。

    2024年02月02日
    浏览(41)
  • 基于 SpringBoot+WebSocket 无DB实现在线聊天室(附源码)

    0.1 样例展示 0.2 源码地址 GitHub:https://github.com/ShiJieCloud/web-chat Gitee:https://gitee.com/suitbaby/web-chat GitCode:I’m Jie / web-chat · GitCode 1.1 HTTP 常用的 HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出

    2024年02月05日
    浏览(38)
  • Vue + Element-Plus + SpringBoot + WebSocket实现简易网络聊天室

    项目流程图 1. 前端搭建:         前端用Vue+Element-Plus 来搭建,由登录页面和聊天页面组成 1.1 登录页面         由一个昵称输入框组成,用户输入自己的昵称若昵称和别的用户不重复,则可进入聊天室,否则提示错误并请重新输入。         这段代码是一个Vue.js组件的

    2024年02月03日
    浏览(53)
  • 在线聊天室(Vue+Springboot+WebSocket)

    实现了一个简单的在线聊天室的前后端。前端用Vue实现,后端用Springboot实现。         在线聊天室的功能包括创建用户和显示在线用户列表、发送消息和显示消息列表、用户和消息列表实时更新这几点。以下是整体功能的活动图: 用户身份         进入聊天室的用户需

    2024年01月15日
    浏览(39)
  • 基于SpringBoot+Vue+WebSocket的在线聊天室

    WebSocket 是一种在 Web 应用程序中实现双向通信的协议。它提供了一种持久连接,允许客户端和服务器之间进行实时数据传输,而无需进行频繁的请求和响应。 相对于传统的 HTTP 请求-响应模式,WebSocket 在客户端和服务器之间建立起一条长久的双向通信通道。这意味着服务器可

    2024年01月16日
    浏览(58)
  • Django实现websocket聊天室

    WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器双向通信,即允许服务器主动发送信息给客户端。因此,在WebSocket中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,客户端和服务器之间的数据交换变

    2023年04月23日
    浏览(33)
  • django websocket实现聊天室功能

    注意事项channel版本 django2.x 需要匹配安装 channels 2 django3.x 需要匹配安装 channels 3 Django 3.2.4 channels 3.0.3 Django 3.2.* channels 3.0.2 Django4.2 channles==3.0.5 是因为最新版channels默认不带daphne服务器 直接用命令 python manage.py runsever 默认运行的是wsgi ,修改,删除settings中的wsgi,都不能正确运

    2024年01月22日
    浏览(37)
  • Java+Vue实现聊天室(WebSocket进阶-聊天记录)

    WebSocket 是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。 WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服

    2024年02月11日
    浏览(45)
  • websocket+elementui+vue实现简易聊天室

    搭建服务端环境 安装socket.io 服务端基于node,js的express框架生成,所以写成模块,引入至app.js中 其中,io.sockets.emit用于向所有建立连接的客户端发送信息,socket.broadcast.emit用于向除发送方之外的客户端发送信息。 客户端基于vue和elementui 进入聊天页面后,先判断用户是否登录,

    2024年04月25日
    浏览(40)
  • 基于WebSocket的简易聊天室的基本实现梳理

    目前在很多网站为了实现推送技术所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信

    2024年02月11日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包