一、WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

  WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

  二、STOMP即Simple (or Streaming) Text Orientated Messaging Protocol,简单(流)文本定向消息协议,它提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互。STOMP协议由于设计简单,易于开发客户端,因此在多种语言和多种平台上得到广泛地应用。

  三、首先,我们先理解一下为什么需要STOMP。

  1)常规的websocket连接和普通的TCP基本上没有什么差别的。

  2)那我们如果像http一样加入一些响应和请求层。

  3)所以STOMP在websocket上提供了一中基于帧线路格式(frame-based wire format)。

  4)简单一点,就是在我们的websocket(TCP)上面加了一层协议,使双方遵循这种协议来发送消息。

  四、STOMP

  1)Frame

  

  例如:

  

  command:CONNECT

  其他部分都是headers的一部分。

  2)command类别

    CONNECT

    SEND

    SUBSCRIBE

    UNSUBSCRIBE

    BEGIN

    COMMIT

    ABORT

    ACK

    NACK

    DISCONNECT

  3)客户端常用连接方式

  a、ws  

  var url = "ws://localhost:8080/websocket";
var client = Stomp.client(url);

  b、sockJs

  <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<script>
// use SockJS implementation instead of the browser's native implementation
var ws = new SockJS(url);
var client = Stomp.over(ws);
[...]
</script>

  说明:使用ws协议需要浏览器的支持,但是一些老版本的浏览器不一定支持。Stomp.over(ws)的凡是就是用来定义服务websocket的协议。

  4)服务端的实现过程

  

  a、服务端:/app,这里访问服务端,前缀通过设定的方式访问。

  b、用户:/user,这里针对的是用户消息的传递,针对于当前用户进行传递。

  c、其他消息:/topic、/queue,这两种方式。都是定义出来用于订阅。并且消息只能从这里通过并处理

  五、springboot的简单例子

  1)目录结构

  

  2)依赖包(pom.xml)

    <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>

  3)websocket配置(WebSocketConfiguration、SecurityConfiguration

/**
* webSocket配置
*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer { /**
* 注册stomp端点,主要是起到连接作用
* @param stompEndpointRegistry
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry
.addEndpoint("/webSocket") //端点名称
//.setHandshakeHandler() 握手处理,主要是连接的时候认证获取其他数据验证等
//.addInterceptors() 拦截处理,和http拦截类似
.setAllowedOrigins("*") //跨域
.withSockJS(); //使用sockJS } /**
* 注册相关服务
* @param registry
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
//这里使用的是内存模式,生产环境可以使用rabbitmq或者其他mq。
//这里注册两个,主要是目的是将广播和队列分开。
//registry.enableStompBrokerRelay().setRelayHost().setRelayPort() 其他方式
registry.enableSimpleBroker("/topic", "/queue");
//客户端名称前缀
registry.setApplicationDestinationPrefixes("/app");
//用户名称前
registry.setUserDestinationPrefix("/user");
}
}

  认证配置:

/**
* 配置基本登录
*/
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{ /**
* 加密方式
*/
@Autowired
private BCryptPasswordEncoder passwordEncoder; /**
* 所有请求过滤,包含webSocket
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().authenticated()
.and()
.httpBasic();
} /**
* 加入两个用户测试不同用的接受情况
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password(passwordEncoder.encode("admin")).roles("ADMIN")
.and()
.withUser("user").password(passwordEncoder.encode("user")).roles("USER");
} @Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}

  4)服务端

/**
* 消息接收处理
*/
@RestController
public class MessageResource { //spring提供的推送方式
@Autowired
private SimpMessagingTemplate messagingTemplate; /**
* 广播模式
* @param requestMsg
* @return
*/
@MessageMapping("/broadcast")
@SendTo("/topic/broadcast")
public String broadcast(RequestMsg requestMsg) {
//这里是有return,如果不写@SendTo默认和/topic/broadcast一样
return "server:" + requestMsg.getBody().toString();
} /**
* 订阅模式,只是在订阅的时候触发,可以理解为:访问——>返回数据
* @param id
* @return
*/
@SubscribeMapping("/subscribe/{id}")
public String subscribe(@DestinationVariable Long id) {
return "success";
} /**
* 用户模式
* @param requestMsg
* @param principal
*/
@MessageMapping("/one")
//@SendToUser("/queue/one") 如果存在return,可以使用这种方式
public void one(RequestMsg requestMsg, Principal principal) {
//这里使用的是spring的security的认证体系,所以直接使用Principal获取用户信息即可。
//注意为什么使用queue,主要目的是为了区分广播和队列的方式。实际采用topic,也没有关系。但是为了好理解
messagingTemplate.convertAndSendToUser(principal.getName(), "/queue/one", requestMsg.getBody());
}
}

  客户端(JavaScript):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>webSocket</title>
<script src="js/jquery.js"></script>
<script src="js/sockjs.min.js"></script>
<script src="js/stomp.js"></script>
</head>
<body>
<div>
<button id="connect">连接</button>
<button id="disconnect" disabled="disabled">断开</button>
</div>
<div>
<h3>广播形式</h3>
<button id="broadcastButton">发送</button><input id="broadcastText" type="text">
<label>广播消息:</label><input id="broadcastMsg" type="text" disabled="disabled">
</div>
<div>
<h3>订阅形式</h3>
<label>订阅消息:</label><input id="subscribeMsg" type="text" disabled="disabled">
</div>
<div>
<h3>角色形式</h3>
<button id="userButton">发送</button><input id="userText" type="text">
<label>用户消息:</label><input id="userMsg" type="text" disabled="disabled">
</div>
<div>
<h3>无APP</h3>
<button id="appButton">发送</button><input id="appText" type="text">
<label>前端消息:</label><input id="appMsg" type="text" disabled="disabled">
</div>
</body>
<script>
var stomp = null;
$("#connect").click(function () {
var url = "http://localhost:8080/webSocket"
var socket = new SockJS(url);
stomp = Stomp.over(socket);
//连接
stomp.connect({}, function (frame) {
//订阅广播
stomp.subscribe("/topic/broadcast", function (res) {
$("#broadcastMsg").val(res.body);
});
//订阅,一般只有订阅的时候在返回
stomp.subscribe("/app/subscribe/1", function (res) {
$("#subscribeMsg").val(res.body);
});
//用户模式
stomp.subscribe("/user/queue/one", function (res) {
$("#userMsg").val(res.body);
});
//无APP
stomp.subscribe("/topic/app", function (res) {
$("#appMsg").val(res.body);
});
setConnect(true);
});
}); $("#disconnect").click(function () {
if (stomp != null) {
stomp.disconnect();
}
setConnect(false);
});
//设置按钮
function setConnect(connectStatus) {
$("#connect").attr("disabled", connectStatus);
$("#disconnect").attr("disabled", !connectStatus);
} //发送广播消息
$("#broadcastButton").click(function () {
stomp.send("/app/broadcast", {}, JSON.stringify({"body":$("#broadcastText").val()}))
}); //发送用户消息
$("#userButton").click(function () {
stomp.send("/app/one", {}, JSON.stringify({"body":$("#userText").val()}))
}); //发送web消息
$("#appButton").click(function () {
stomp.send("/topic/app", {}, JSON.stringify({"body":$("#appText").val()}))
});
</script>
</html>

  5)普通测试

  角色测试:

  六、相关资料

  http://jmesnil.net/stomp-websocket/doc/

  七、源码:https://github.com/lilin409546297/springboot-websocket

springboot之websocket,STOMP协议的更多相关文章

  1. 【Java分享客栈】SpringBoot整合WebSocket+Stomp搭建群聊项目

    前言 前两周经常有大学生小伙伴私信给我,问我可否有偿提供毕设帮助,我说暂时没有这个打算,因为工作实在太忙,现阶段无法投入到这样的领域内,其中有两个小伙伴又问到我websocket该怎么使用,想给自己的 ...

  2. springboot websocket集群(stomp协议)连接时候传递参数

    最近在公司项目中接到个需求.就是后台跟前端浏览器要保持长连接,后台主动往前台推数据. 网上查了下,websocket stomp协议处理这个很简单.尤其是跟springboot 集成. 但是由于开始是 ...

  3. springboot+websocket+sockjs进行消息推送【基于STOMP协议】

    springboot+websocket+sockjs进行消息推送[基于STOMP协议] WebSocket是在HTML5基础上单个TCP连接上进行全双工通讯的协议,只要浏览器和服务器进行一次握手,就 ...

  4. springBoot -webSocket 基于STOMP协议交互

    浅谈WebSocket WebSocket是在HTML5基础上单个TCP连接上进行全双工通讯的协议,只要浏览器和服务器进行一次握手,就可以建立一条快速通道,两者就可以实现数据互传了.说白了,就是打破了 ...

  5. SpringBoot WebSocket STOMP 广播配置

    目录 1. 前言 2. STOMP协议 3. SpringBoot WebSocket集成 3.1 导入websocket包 3.2 配置WebSocket 3.3 对外暴露接口 4. 前端对接测试 ...

  6. websocket的子协议stomp协议

    stomp协议Spring实现 服务器注册EndPoint 用来与客户端建立websocket连接 websocket连接的建立应该与客户端与服务器之间的通道无关 jdk中 javax下的websoc ...

  7. Spring Boot实现STOMP协议的WebSocket

    关注公众号:锅外的大佬 每日推送国外优秀的技术翻译文章,励志帮助国内的开发者更好地成长! WebSocket协议是应用程序处理实时消息的方法之一.最常见的替代方案是长轮询(long polling)和 ...

  8. spring-boot支持websocket

    spring-boot本身对websocket提供了很好的支持,可以直接原生支持sockjs和stomp协议.百度搜了一些中文文档,虽然也能实现websocket,但是并没有直接使用spring-bo ...

  9. SpringBoot 整合 WebSocket

    SpringBoot 整合 WebSocket(topic广播) 1.什么是WebSocket WebSocket为游览器和服务器提供了双工异步通信的功能,即游览器可以向服务器发送消息,服务器也可以向 ...

随机推荐

  1. 执行SQL的DbHelperSQL

    using System; using System.Collections; using System.Collections.Specialized; using System.Data; usi ...

  2. win10 虚拟机 hyper-v 安装 centos 7

    一.win 10 企业版 自带虚拟机 hyper-v 1.控制面板-->程序和功能-->启用或关闭Windows功能 勾上 hyper-v 确定就ok了 2.安装成功后会发现在 左下角“开 ...

  3. 11g数据库查看dataguard是否同步

    一.环境      主库:       ip地址:192.168.122.203       oracle根目录:/data/db/oracle       SID:qyq       数据文件路径/ ...

  4. 访问一个HTTPS的网站的大致流程

    浏览器向服务器发送请求,请求中包括浏览器支持的协议,并附带一个随机数. 服务器收到请求后,选择某种非对称加密算法,把数字证书签名公钥.身份信息发送给浏览器,同时也附带一个随机数. 浏览器收到后,验证证 ...

  5. Hibernate事务、缓存和连接池

    一.事务 1.数据库事务的概念 数据库事务是指由一个或多个SQL语句组成的工作单元,这个工作单元中的SQL语句相互依赖,如果有一个SQL语句执行失败,就必须撤销整个工作单元.在并发环境中,多个事务同时 ...

  6. React 如何正常渲染一段HTML字符串

    dangerouslySetInnerHTMl 属性 很多时候我们做一个项目接口会返回一段 HTML 字符串文本,然后我们把它解析渲染成正常的html,这是在项目中常见不能再常见的情况了,可是在 re ...

  7. 20145203Java实验报告四:Android开发基础

    Java实验报告四:Android开发基础 实验要求: 1.安装Android Studio 2.运行安卓AVD模拟器 3.使用安卓运行出虚拟手机并显示HelloWorld以及自己的学号 实验过程 ( ...

  8. salt常用命令(一)

    查看模块包含哪些函数 salt 'node' sys.list_functions test 查看函数的用法 salt 'node' sys.doc test.echo 使用模块中的函数 salt ' ...

  9. HDU 1203 01背包变形题,(新思路)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1203 I NEED A OFFER! Time Limit: 2000/1000 MS (Java/ ...

  10. K2使用Nginx做负载均衡

    K2使用Nginx做负载均衡 K2目前是支持Load Balancing这种方式,来做负载均衡,也可以使用F5来做负载均衡,但这次我使用nginx来实现K2的负载均衡 下载nginx 请下载nginx ...