广告
返回顶部
首页 > 资讯 > 后端开发 > Python >SpringBoot+STOMP协议实现私聊、群聊
  • 946
分享到

SpringBoot+STOMP协议实现私聊、群聊

2024-04-02 19:04:59 946人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录一、为什么需要STOMP?二、STOMP详解三、SpringBoot集成STOMP代码示例3.1、功能示例3.2、架构图3.3、服务端代码3.4、h5代码一、为什么需要S

一、为什么需要STOMP?

        websocket 协议是一种相当低级的协议。它定义了如何将字节流转换为帧。帧可以包含文本或二进制消息。由于消息本身不提供有关如何路由或处理它的任何其他信息,因此很难在不编写其他代码的情况下实现更复杂的应用程序。幸运的是,WEBSocket 规范允许在更高的应用程序级别上使用子协议。

        另外,单单使用WebSocket完成群聊、私聊功能时,需要自己管理session信息,通过STOMP协议时,spring已经封装好,开发者只需要关注自己的主题、订阅关系即可。

二、STOMP详解

消息流简单代理

        STOMP 中文为“面向消息的简单文本协议”,STOMP 提供了能够协作的报文格式,以至于 STOMP 客户端可以与任何 STOMP 消息代理(Brokers)进行通信,从而为多语言,多平台和 Brokers 集群提供简单且普遍的消息协作。STOMP 协议可以建立在 WebSocket 之上,也可以建立在其他应用层协议之上。通过 Websocket建立 STOMP 连接,也就是说在 Websocket 连接的基础上再建立 STOMP 连接。最终实现如上图所示,这一点可以在代码中有一个良好的体现。

业界已经有很多优秀的 STOMP 的服务器/客户端的开源实现

        Stomp 的特点是客户端的实现很容易,服务端相当于消息队列的 broker 或者是 server,一般不需要我们去实现,所以重点关注一下客户端如何使用

  • CONNECT 启动与服务器的流或 tcp 连接
  • SEND发送消息
  • SUBSCRIBE 订阅主题
  • UNSUBSCRIBE 取消订阅
  • BEGIN 启动事物
  • COMMIT提交事物
  • ABORT回滚事物
  • ACK确认来自订阅的消息的消费
  • NACK告诉服务器客户端没有消费该消息
  • DISCONNECT断开连接

        其实STOMP协议并不是为WS所设计的, 它其实是消息队列的一种协议, 和AMQP,JMS是平级的。 只不过由于它的简单性恰巧可以用于定义WS的消息体格式。 目前很多服务端消息队列都已经支持了STOMP, 比如RabbitMQ, Apache ActiveMQ等。很多语言也都有STOMP协议的客户端解析库,像JAVA的Gozirra,C的libstomp,python的pyactivemq,JavaScript的stomp.js等等。

STOMP协议官方文档

三、SpringBoot集成STOMP代码示例

3.1、功能示例

image-20210609170607678 

image-20210609170552704 

3.2、架构图

image-20210609143546406

3.3、服务端代码

pom文件引入jar


<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>websocket-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

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

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

        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>sockjs-client</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>stomp-websocket</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>Jquery</artifactId>
            <version>3.1.0</version>
        </dependency>


        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastJSON</artifactId>
            <version>1.2.62</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

WebSocketMessageBroker配置类


@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer
{
	// 启用一个简单的基于内存的消息代理
	@Override
	public void configureMessageBroker(MessageBrokerReGIStry config) {
		//通过/topic 开头的主题可以进行订阅
		config.enableSimpleBroker("/topic");
		//send命令时需要带上/app前缀
		config.setApplicationDestinationPrefixes("/app");
        //修改convertAndSendToUser方法前缀, 稍后解释作用
//		config.setUserDestinationPrefix ("/myUserPrefix");
	}
	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		//连接前缀
		registry.addEndpoint("/gs-guide-websocket")
				.setAllowedOrigins("*")  // 跨域处理
				.withSockJS();  //支持socketJs
	}
}

@EnableWebSocketMessageBroker注解启用 WebSocket 消息处理,由消息代理支持。

SockJS 有一些浏览器中缺少对 WebSocket 的支持,而 SockJS 是一个浏览器的 JavaScript库,它提供了一个类似于网络的对象,SockJS 提供了一个连贯的,跨浏览器的JavaScriptapi,它在浏览器和 Web 服务器之间创建了一个低延迟、全双工、跨域通信通道。SockJS 的一大好处在于提供了浏览器兼容性。即优先使用原生WebSocket,如果浏览器不支持 WebSocket,会自动降为轮询的方式。如果你使用 Java 做服务端,同时又恰好使用 Spring Framework 作为框架,那么推荐使用SockJS。

控制器代码


@Slf4j
@RestController
public class TestController
{
	@Autowired
	private SimpMessagingTemplate simpMessagingTemplate;

	@MessageMapping("/hello")
	@SendTo ("/topic/greetings")
	public Greeting greeting(HelloMessage message) throws Exception {
		Thread.sleep(1000); // simulated delay
		return new Greeting("Hello, " + htmlUtils.htmlEscape(message.getName()) + "!");
	}

	@MessageMapping("/topic/greetings")
	public Greeting greeting2(HelloMessage message) throws Exception {
		Thread.sleep(1000); // simulated delay
		log.info ("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
		return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
	}
	@GetMapping ("/hello2")
	public void greeting3(HelloMessage message) throws Exception {
		Thread.sleep(1000); // simulated delay
		simpMessagingTemplate.convertAndSend ("/topic/greetings",
				new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"));
	}


	@MessageMapping("/sendToUser")
	public void sendToUser(HelloMessage message) throws Exception {
		Thread.sleep(1000); // simulated delay
		log.info ("userId:{},msg:{}",message.getUserId (),message.getName ());
//		simpMessagingTemplate.convertAndSendToUser (message.getUserId (),"/sendToUser",
//				new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"));
//		simpMessagingTemplate.convertAndSend ("/user/1/sendToUser",
//				new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"));
		simpMessagingTemplate.convertAndSend ("/topic/user/"+message.getUserId ()+"/sendToUser",
				new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"));
	}
}
  • @MessageMapping 功能与RequestMapping注解类似。send指令发送信息时添加此注解
  • @SendTo/@SendToUser 将信息输出到该主题。客户端订阅同样的主题后就会收到信息。
  • 在只有指定@MessageMapping@MessageMapping == “/topic” + @SendTo
  • 如果想使用rest接口发送消息。可以通过SimpMessagingTemplate进行发送。
  • 点对点聊天时,可以使用SimpMessagingTemplate.convertAndSendToUser方法发送。个人意味比注解@SendToUser更加容易理解,更加方便
  • convertAndSendToUser方法和convertAndSend类似,区别在于convertAndSendToUser方法会在主题默认添加/user/为前缀。因此,示例代码中convertAndSend方法直接传入"/topic/user/"+message.getUserId ()+"/sendToUser" 也是点对点发送。topic其中是默认前缀。
  • 如果想修改convertAndSendToUser默认前缀可在配置类进行配置,可在WebSocketConfig类中查看。

3.4、h5代码


<!DOCTYPE html>
<html>
<head>
    <title>Hello WebSocket</title>
    <link href="/webjars/bootstrap/CSS/bootstrap.min.css" rel="external nofollow"  rel="stylesheet">
    <link href="/main.css" rel="external nofollow"  rel="stylesheet">
    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>

    <script src="/webjars/sockjs-client/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/stomp.min.js"></script>
    <script src="/app.js"></script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websocket relies on Javascript being
    enabled. Please enable
    Javascript and reload this page!</h2></noscript>
<div id="main-content" class="container">
    <div class="row">
        <div class="col-md-6">
            <fORM class="form-inline">
                <div class="form-group">
                    <label for="connect">WebSocket connection:</label>
                    <button id="connect" class="btn btn-default" type="submit">Connect</button>
                    <button id="disconnect" class="btn btn-default" type="submit" disabled="disabled">Disconnect
                    </button>
                </div>
            </form>
        </div>
        <div class="col-md-6">
            <form class="form-inline">
                <div class="form-group">
                    <label for="name">What is your name?</label>
                    <input type="text" id="name" class="form-control" placeholder="Your name here...">
                    <input type="text" id="userId" class="form-control" placeholder="userId">
                </div>
                <button id="send" class="btn btn-default" type="submit">Send</button>
                <button id="send2" class="btn btn-default" type="submit">Send2</button>

                <button id="send3" class="btn btn-default" type="submit">SendToUser</button>

            </form>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <table id="conversation" class="table table-striped">
                <thead>
                <tr>
                    <th>Greetings</th>
                </tr>
                </thead>
                <tbody id="greetings">
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>

app.js


var stompClient = null;
var userId = null;
function setConnected(connected) {
    $("#connect").prop("disabled", connected);
    $("#disconnect").prop("disabled", !connected);
    if (connected) {
        $("#conversation").show();
    }
    else {
        $("#conversation").hide();
    }
    $("#greetings").html("");
}

function connect() {
    var socket = new SockJS('/gs-guide-websocket');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (greeting) {
            showGreeting(JSON.parse(greeting.body).content);
        });
        //对应controller greeting2方法  注意,这儿有两个topic
         stompClient.subscribe('/topic/topic/greetings', function (greeting) {
                showGreeting(JSON.parse(greeting.body).content);
          });
  stompClient.subscribe('/topic/user/'+userId+'/sendToUser', function (greeting) {
                          showGreeting(JSON.parse(greeting.body).content);
                    });
           stompClient.subscribe('/user/'+userId+'/sendToUser', function (greeting) {
                          showGreeting(JSON.parse(greeting.body).content);
                    });
    });
}

function disconnect() {
    if (stompClient !== null) {
        stompClient.disconnect();
    }
    setConnected(false);
    console.log("Disconnected");
}

function sendName() {
    stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()}));
//    stompClient.send("/hello", {}, JSON.stringify({'name': $("#name").val()}));
}
function sendName2() {
    stompClient.send("/app/topic/greetings", {}, JSON.stringify({'name': $("#name").val()}));
//    stompClient.send("/topic/greetings", {}, JSON.stringify({'name': $("#name").val()}));
}
function sendName3() {
    stompClient.send("/app/sendToUser", {}, JSON.stringify({'userId':$("#userId").val(),'name': $("#name").val()}));
}

function showGreeting(message) {
    $("#greetings").append("<tr><td>" + message + "</td></tr>");
}
function GetQueryString(name) {
	var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
	var r = window.location.search.substr(1).match(reg); //获取url中"?"符后的字符串并正则匹配
	var context = "";
	if (r != null)
		context = r[2];
	reg = null;
	r = null;
	return context == null || context == "" || context == "undefined" ? "" : context;
}
$(function () {
    userId =  GetQueryString("userId");
    $("form").on('submit', function (e) {
        e.preventDefault();
    });
    $( "#connect" ).click(function() { connect(); });
    $( "#disconnect" ).click(function() { disconnect(); });
    $( "#send" ).click(function() { sendName(); });
    $( "#send2" ).click(function() { sendName2(); });
    $( "#send3" ).click(function() { sendName3(); });

});

一些无关紧要的类


public class Greeting
{
   private String content;

   public Greeting() {
   }

   public Greeting(String content) {
      this.content = content;
   }

   public String getContent() {
      return content;
   }
}

public class HelloMessage
{
   private String userId;
   private String name;
    // 省去get/set
}
Name3(); });

});

spring参考文档

websocket参考文档

到此这篇关于SpringBoot+STOMP协议实现私聊、群聊的文章就介绍到这了,更多相关SpringBoot STOMP私聊、群聊内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: SpringBoot+STOMP协议实现私聊、群聊

本文链接: https://www.lsjlt.com/news/128010.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SpringBoot+STOMP协议实现私聊、群聊
    目录一、为什么需要STOMP?二、STOMP详解三、SpringBoot集成STOMP代码示例3.1、功能示例3.2、架构图3.3、服务端代码3.4、h5代码一、为什么需要S...
    99+
    2022-11-12
  • SpringBoot+STOMP协议怎么实现私聊、群聊功能
    这篇文章主要介绍了SpringBoot+STOMP协议怎么实现私聊、群聊功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、为什么需要STOMP  &n...
    99+
    2023-06-15
  • springboot结合websocket聊天室实现私聊+群聊
    目录 先看效果 后端代码 前端代码 先看效果 一人分饰多角(bushi) 后端代码 先引入websocket依赖 <!-- websocket消息推送 -->...
    99+
    2022-11-13
  • Java实现局域网聊天室功能(私聊、群聊)
    本文实例为大家分享了Java实现局域网聊天室功能的具体代码,供大家参考,具体内容如下 Server 服务端 import java.io.IOException; import ja...
    99+
    2022-11-13
  • 微信小程序使用stomp.js实现STOMP传输协议的实时聊天
    简介: uniapp开发的小程序中使用 本来使用websocket,后端同事使用了stomp协议,导致前端也需要对应修改。 如何使用 在static/js中新建stomp.js和websocket.js,然后在需要使用的页面引入监听代码+...
    99+
    2023-08-30
    微信小程序 小程序 stomp websocket IM 即时通信
  • Java实现NIO聊天室的示例代码(群聊+私聊)
    目录功能介绍文件UtilsFinalValueMessageNioServerNioClient功能介绍 功能:群聊+私发+上线提醒+下线提醒+查询在线用户 文件 U...
    99+
    2022-11-12
  • 【uni-app】小程序实现微信在线聊天(私聊/群聊)
    之前学习使用uni-app简单实现一个在线聊天的功能,今天记录一下项目核心功能的实现过程。页面UI以及功能逻辑全部来源于微信,即时聊天业务的实现使用socket.io,前端使用uni-app开发,后端服务器基于node实现,数据库选择mon...
    99+
    2023-09-03
    uni-app 前端 小程序
  • uni-app小程序实现微信在线聊天功能(私聊/群聊)
    目录聊天信息列表的渲染聊天信息发送的相关问题实现一对一聊天关于websocket建立连接存储连接的用户发送聊天信息 首页新消息提示实现群聊加入房间发送群消息之前学习使用un...
    99+
    2023-02-18
    uni-app小程序微信聊天 uni-app微信小程序聊天
  • springboot整合websocket如何实现群聊
    这篇文章将为大家详细讲解有关springboot整合websocket如何实现群聊,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。实现思路发送者向服务器发送大家早上好。其它客户端可以收到对应消息。项目展示通...
    99+
    2023-06-15
  • 基于UDP协议实现聊天系统
    基于UDP协议的聊天系统的实现(含GUI),供大家参考,具体内容如下 这是一篇我的学习记录,这学期加入了JAVA 的学习,所以自己把教科书看了一下,然后尝试地写了一个UDP协议的聊天...
    99+
    2022-11-12
  • 使用springboot整合websocket实现群聊教程
    目录先上效果图:先来准备工作导入依赖导入依赖后扫描启用接收前端传回数据其中重点就是4个注解**@OnOpen,@OnClose,@OnMessage,@OnError**前端页面代码...
    99+
    2022-11-12
  • Android中基于XMPP协议实现IM聊天程序与多人聊天室
    简单的IM聊天程序 由于项目需要做一个基于XMPP协议的Android通讯软件。故开始研究XMPP。 XMPP协议采用的是客户端-服务器架构,所有从一个客户端发到另一个客户端的...
    99+
    2022-06-06
    xmpp 程序 聊天室 Android
  • 基于UDP协议实现聊天系统的方法
    这篇文章给大家分享的是有关基于UDP协议实现聊天系统的方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。代码展示下面展示一些 Client类。class Client extends ...
    99+
    2023-06-14
  • springboot整合websocket实现群聊思路代码详解
    实现思路 发送者向服务器发送大家早上好。其它客户端可以收到对应消息。 项目展示 通过springboot引入websocket,实现群聊,通过在线websocket测试进行展示。...
    99+
    2022-11-12
  • java实现基于UDP协议的聊天小程序操作
    UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去! UDP适用于一次只传送少...
    99+
    2022-11-12
  • 怎么用Python基于udp协议实现聊天小程序
    这篇文章主要介绍“怎么用Python基于udp协议实现聊天小程序”,在日常操作中,相信很多人在怎么用Python基于udp协议实现聊天小程序问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么用Python基于...
    99+
    2023-06-02
  • Python使用 TCP协议实现智能聊天机器人功能
    编写聊天程序的服务端代码和客户端代码。完成后,先启动服务端代码,然 后启动客户端程序输人问题,服务端可以返回相应的答案。要求服务端代码具 有一定的智能,能够根据不完整的问题识别客户端...
    99+
    2022-11-11
  • 怎么在SpringBoot中利用WebSocket实现一个群聊功能
    本篇文章为大家展示了怎么在SpringBoot中利用WebSocket实现一个群聊功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。消息群发创建新项目:添加依赖:<dependency>...
    99+
    2023-06-06
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作