一 WebScoketS 简介

RFC 6455 即 webSockets 协议提供了一种标准化的方式去建立全双工,双方面交流的通道在客户端和服务端甚至单一的TCP连接中进行通信; webSockets 协议其跟HTTP的tcp协议不同,但是其设计目的是通过HTTP协议进行工作,可以使用40或者443端口和重新使用现有的防火墙规则;

GET /spring-websocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: http://localhost:8080

webSockets 的交互是以HTTP协议开始的,使用Upgrade header 转向使用Upgrade连接;如果非200状态成功响应就类似于下面的信息;如果WebSocket server 是运行在nginx是需要配置WebSocket upgrade requests ;如果是运行在云上,需要查阅相关的云是否支持WebSocket ;

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp

二 HTTP 和 WebSocket 对比

  1. 在HTTP和REST中一个应用需要很多的URLs;应用和客户端是通过 请求和响应的风格使用这些URLs进行交互;服务端会路由这些请求给基于HTTP 的URL或者方法或者头进行处理;
  2. WebSockets 通常在初始化的时候就只有一个链接,所有应用的消息都是通过相同的TCP连接进行流动;这指向一个完全不同的异步、事件驱动的消息传递体系结构。
  3. WebSocket 是一种低端的协议,不像HTTP,其不规定消息中内容中任何的语义信息;这意味着其没有任何方式去路由或者处理这些信息,除非客户端和服务端在语义上达成一致;
  4. WebSocket 客户端和服务端其交流是通过使用更加高级的消息协议(比如STOMP)和基于HTTP握手请求的Sec-WebSocket-Protocol header ;

三 注意事项

WebSockets可以使web页面具有动态性和交互性。然而,在许多情况下,Ajax和HTTP流或 long polling(轮询)可以提供一个简单有效的解决方案。HTTP流和polling适用于消息不频繁的交互,WebSockets适用于消息较频繁的交互;在 因特网上由于没有Upgrade header 或者 关闭了空闲的长链接,受限于在你有限的代理可能会将WebSockets的交互排除;

四 websocket配置和依赖

4.1 依赖

	<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/>
</parent> <dependencies>
<!-- websocket依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 模板引擎-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>

4.2 配置

/**
* @Author lsc
* @Description <p>websocket配置类 </p>
* @Date 2019/11/12 22:27
*/
//使用STOMP协议来传输基于消息代理的消息,控制器支持在@Controller类中使用@MessageMapping
@EnableWebSocketMessageBroker
@Configurable
@EnableWebSocket
@Component
public class WebConfig implements WebSocketMessageBrokerConfigurer { @Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
// 注册 Stomp的端点(Endpoint),并且映射指定的url
registry.addEndpoint("/websocket")
.setAllowedOrigins("*") // 添加允许跨域访问
.withSockJS();// 指定SockJS协议
} @Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 启动广播模式代理,只有符合的的路径才发送消息
registry.enableSimpleBroker("/topic");
}
}

五 实体类

5.1 接受消息实体

/**
* @Author lsc
* @Description <p> 接受客户端消息</p>
* @Date 2019/11/12 22:42
*/
public class AcceptMessages { private String name; public String getName() {
return name;
}
}

5.2 发送消息实体

/**
* @Author lsc
* @Description <p>发送消息给客户端 </p>
* @Date 2019/11/12 22:42
*/
public class SendMessages { private String responseMessage; public String getResponseMessage() {
return responseMessage;
} public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}
}

六控制器

/**
* @Author lsc
* @Description <p>websockets 之 广播式</p>
* @Date 2019/11/12 22:49
*/
@Controller
public class WebSocketsController { @MessageMapping("/welcome")//类似@RequestMapping,进行客户端请求地址映射
@SendTo("/topic/getResponse")//订阅了@SendTo中的路径进行发送消息
public SendMessages broadcast(AcceptMessages acceptMessages){
System.out.println(acceptMessages.getName());
SendMessages sendMessages = new SendMessages();
sendMessages.setResponseMessage("知识追寻者:"+acceptMessages.getName());
return sendMessages;
} }

七 前端页面

在 resource目录下新建templates目录存放WebSockets.html;在resource目录下新建static目录,继续在其子目录下新建js目录存放sockjs.min.js,stomp.min.js,jquery-3.3.1.min.js;

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>springboot广播式WebSocket</title>
</head>
<body onload="disconnect()">
<noscript><h2 style="color: #ffff0000;">Sorry,not support the WebSocket</h2></noscript>
<div>
<div>
<button id="connect" onclick="connect();">连接</button>
<button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button>
</div>
<div id="conversationDiv">
<label>输入你的名字</label>
<input type="text" id="name"/>
<button id="sendName" onclick="sendName();">发送</button>
<p id="response"></p>
</div>
</div>
<script th:src="@{js/sockjs.min.js}"></script>
<script th:src="@{js/stomp.min.js}"></script>
<script th:src="@{js/jquery-3.3.1.min.js}"></script>
<script type="text/javascript">
var stompClient = null;
// 设置连接
function setConnected(connected) {
document.getElementById("connect").disabled = connected;
document.getElementById("disconnect").disabled = !connected;
document.getElementById("conversationDiv").style.visibility = connected ? 'visible' : 'hidden';
$("#response").html();
}
// 连接
function connect() {
// 转向 endpoint 名为websocket
var socket = new SockJS('/websocket');
// 使用ssocket的协议
stompClient = Stomp.over(socket);
// 连接
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected:' + frame);
// @Sendto 中定义路径 向目标订阅消息
stompClient.subscribe('/topic/getResponse', function (response) {
showResponse(JSON.parse(response.body).responseMessage);
})
});
}
function disconnect() {
if (stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log('Disconnected');
}
function sendName() {
var name = $('#name').val();
// 控制器@MessageMapping中定义向目标发送消息
stompClient.send("/welcome", {}, JSON.stringify({'name': name}));
}
function showResponse(message) {
$("#response").html(message);
}
</script>
</body>
</html>

八 视图转发

当客户端请求地址是localhost:8080/ws,经过springmvc视图转发器至WebSockets.html;

/**
* @Author lsc
* @Description <p> spingmvc视图映射转发</p>
* @Date 2019/11/12 23:35
*/
@Configurable
@Component
public class WebMvcConfig implements WebMvcConfigurer { @Override
public void addViewControllers(ViewControllerRegistry registry) {
// 配置视图转发
registry.addViewController("/ws").setViewName("/WebSockets");
}
}

九 效果图

即一个浏览器发送消息,其它连接的浏览器也能收到消息,即广播形式;

十参考文献

参考1:《JavaEE开发的颠覆者》

参考2: spring-web

源码: youku1327

springboot-集成WebSockets广播消息的更多相关文章

  1. springboot集成redis实现消息发布订阅模式-双通道(跨多服务器)

    基础配置参考https://blog.csdn.net/llll234/article/details/80966952 查看了基础配置那么会遇到一下几个问题: 1.实际应用中可能会订阅多个通道,而一 ...

  2. springboot集成swagger添加消息头(header请求头信息)

    springboot集成swagger上篇文章介绍: https://blog.csdn.net/qiaorui_/article/details/80435488 添加头信息: package co ...

  3. SpringBoot 集成Apache Kafak 消息队列

    Kafka is a distributed,partitioned,replicated commit logservice.它提供了类似于JMS的特性,但是在实现上完全不同,此外它并不是JMS规范 ...

  4. SpringBoot集成rabbitmq(二)

    前言 在使用rabbitmq时,我们可以通过消息持久化来解决服务器因异常崩溃而造成的消息丢失.除此之外,我们还会遇到一个问题,当消息生产者发消息发送出去后,消息到底有没有正确到达服务器呢?如果不进行特 ...

  5. spring boot 集成 websocket 实现消息主动推送

    spring boot 集成 websocket 实现消息主动 前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单 ...

  6. SpringBoot集成Kafka的实战用法大全

    本文是SpringBoot+Kafka的实战讲解,如果对kafka的架构原理还不了解的读者,建议先看一下<大白话kafka架构原理>.<秒懂kafka HA(高可用)>两篇文章 ...

  7. SpringBoot集成RabbitMQ消息队列搭建与ACK消息确认入门

    1.RabbitMQ介绍 RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面表现不俗.Rabbi ...

  8. SpringBoot集成WebSocket【基于纯H5】进行点对点[一对一]和广播[一对多]实时推送

    代码全部复制,仅供自己学习用 1.环境搭建 因为在上一篇基于STOMP协议实现的WebSocket里已经有大概介绍过Web的基本情况了,所以在这篇就不多说了,我们直接进入正题吧,在SpringBoot ...

  9. springboot集成websocket实现向前端浏览器发送一个对象,发送消息操作手动触发

    工作中有这样一个需示,我们把项目中用到代码缓存到前端浏览器IndexedDB里面,当系统管理员在后台对代码进行变动操作时我们要更新前端缓存中的代码怎么做开始用想用版本方式来处理,但这样的话每次使用代码 ...

随机推荐

  1. MUI - 解决动态列表页图片懒加载再次加载不成功的bug

    首先描述一下功能 实现列表页动态加载 通过官方提供的"下拉刷新和上拉刷新"及"图片懒加载"示例实现. http://www.cnblogs.com/philly ...

  2. 自动编码(AE)器的简单实现

    一.目录 自动编码(AE)器的简单实现 一.目录 二.自动编码器的发展简述 2.1 自动编码器(Auto-Encoders,AE) 2.2 降噪自编码(Denoising Auto-Encoders, ...

  3. @codeforces - 793G@ Oleg and chess

    目录 @description - translation@ @solution@ @part - 1@ @part - 2@ @part - 3@ @part - 4@ @accepted code ...

  4. php 对接java短信接口带有英文逗号就无法通过

    在对接短息接口时,对方是java接口,要求content两次编码 短信内容(Content)发起请求前必须进行URL转码.例如对于短信内容为“中文短信abc”,转码过程如下(java语言): Stri ...

  5. PHP 试题(1)

    1.__FILE__表示什么意思?(5分)文件的完整路径和文件名.如果用在包含文件中,则返回包含文件名.自 PHP 4.0.2 起,__FILE__ 总是包含一个绝对路径,而在此之前的版本有时会包含一 ...

  6. 【a503】圆排列问题

    Time Limit: 1 second Memory Limit: 32 MB [问题描述] 给定n个大小不等的圆c1,c2,...., cn,现要将这n个圆排列进一个矩形框中,且要求各圆与矩形框的 ...

  7. 【t065】最敏捷的机器人

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] [背景] Wind设计了很多机器人.但是它们都认为自己是最强的,于是,一场比赛开始了~ [问题描述] ...

  8. H3C PAP验证

  9. ThinkPHP3.2版本安全更新

    近日我们收到了一个关于3.2版本的漏洞提醒,官方已经第一时间进行处理和更新.由于3.2版本已经过了官方的维护和安全更新周期,而且大量的开发者也进行了二次开发,因此不再发布新版,官方仅进行安全公告和修复 ...

  10. Java Integer类的缓存

    首先看一段代码(使用JDK 5),如下: public class Hello { public static void main(String[] args) { int a = 1000, b = ...