Spring Boot + WebSocket 学习笔记
首先需要了解一下背景,什么是WebSocket以及为什么要用WebSocket。
在常见的Web应用中,客户端与服务器通信,都是通过HTTP协议进行通信,客户端一次请求,服务端一次响应。而WebSocket使得客户端与服务端可以直接构建起一条TCP的通道。这里附上一段百度百科的文字说明:WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
当客户端有需要向后台实时请求最新数据的情景下(实际上应该是服务端侦知到数据发生变更主动推送给客户端),目前一般是使用AJAX来进行一个定时的轮询,而使用WebSocket即可很好的适配该种需求场景。两种方式的对比可见下图:

相关背景就说到这里,下面结合代码进行实战。
首先在Spring Boot工程的pom文件中添加相关依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
接下来先实现一个WebSocket类,并通过注解@ServerEndpoint指定在服务器上发布的URI供客户端连接时填写。
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController; @ServerEndpoint("/testWebSocket")
@RestController
public class TestWebSocket { // 用来记录当前连接数的变量
private static volatile int onlineCount = 0; // concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象
private static CopyOnWriteArraySet<TestWebSocket> webSocketSet = new CopyOnWriteArraySet<TestWebSocket>(); // 与某个客户端的连接会话,需要通过它来与客户端进行数据收发
private Session session; private static final Logger LOGGER = LoggerFactory.getLogger(TestWebSocket.class); @OnOpen
public void onOpen(Session session) throws Exception {
this.session = session;
System.out.println(this.session.getId());
webSocketSet.add(this);
LOGGER.info("Open a websocket.");
} @OnClose
public void onClose() {
webSocketSet.remove(this);
LOGGER.info("Close a websocket. ");
} @OnMessage
public void onMessage(String message, Session session) throws IOException, InterruptedException {
LOGGER.info("Receive a message from client: " + message); for (int i = 0; i < 10; i ++) { session.getBasicRemote().sendText(String.valueOf(i));
Thread.sleep(1000);
}
} @OnError
public void onError(Session session, Throwable error) {
LOGGER.error("Error while websocket. ", error);
} public void sendMessage(String message) throws Exception {
if (this.session.isOpen()) {
this.session.getBasicRemote().sendText("Send a message from server. ");
}
} public static synchronized int getOnlineCount() {
return onlineCount;
} public static synchronized void addOnlineCount() {
TestWebSocket.onlineCount++;
} public static synchronized void subOnlineCount() {
TestWebSocket.onlineCount--;
}
}
对应前端页面websocket.html内容如下方所示。
<html>
<body>
<input id="text" type="text"/>
<button onclick="send()">发送消息</button>
<hr/>
<div id="message"></div>
</body> <script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/testWebSocket");
}
else {
alert('当前浏览器 不支持WebSocket')
} //连接发生错误的回调方法
websocket.onerror = function () {
setMessageInnerHTML("WebSocket连接发生错误");
}; //连接成功建立的回调方法
websocket.onopen = function () {
setMessageInnerHTML("WebSocket连接成功");
} //接收到消息的回调方法
websocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
} //连接关闭的回调方法
websocket.onclose = function () {
setMessageInnerHTML("WebSocket连接关闭");
} //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
closeWebSocket();
} //将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '<br/>';
} //关闭WebSocket连接
function closeWebSocket() {
websocket.close();
} //发送消息
function send() {
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</html>
同时在控制层中增加对新增页面的定向。
@RequestMapping("/websocket")
public String websocket() {
return "websocket";
}
这时启动项目并通过http://localhost:8080/websocket访问,出现如下报错。

原因是未将WebSocket添加到Spring的容器中。
@Configuration
public class WebSocketConfig { @Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
网上有资料提到,该类必须与项目入口或者说启动类在同一个子包下,不然可能会出现注入失败的问题。我这里倒没有遇到,也没办法复现,该问题也就不继续深究。

验证成功!
参考资料:
https://www.runoob.com/html/html5-websocket.html
https://www.cnblogs.com/strugglion/p/10021173.html
Spring Boot + WebSocket 学习笔记的更多相关文章
- Spring BOOT的学习笔记
1,静态文件夹src/main/resources/static下的,图片必须放在images文件夹下才能访问,直接放在static下不能访问 2,配置热部署,否则修改下Html,图片都得重启 htt ...
- Spring boot + jdbc学习笔记
pom.xml: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www. ...
- Spring boot ----RestTemplate学习笔记
****spring boot-----restTemplate 封装了HttpURLConnection,HttpClient,Netty等接口访问实现库 restTemplet包含以下部分 Htt ...
- Spring Boot WebSocket从入门到放弃
在构建Spring boot项目时已经提供webSocket依赖的勾选.webSocket是TCP之上的一个非常薄的轻量级层 ,webSocket主要的应用场景离不开即时通讯与消息推送,但只要应用程序 ...
- spring cloud(学习笔记)高可用注册中心(Eureka)的实现(二)
绪论 前几天我用一种方式实现了spring cloud的高可用,达到两个注册中心,详情见spring cloud(学习笔记)高可用注册中心(Eureka)的实现(一),今天我意外发现,注册中心可以无限 ...
- WebSocket学习笔记IE,IOS,Android等设备的兼容性问
WebSocket学习笔记IE,IOS,Android等设备的兼容性问 一.背景 公司最近准备将一套产品放到Andriod和IOS上面去,为了统一应用的开发方式,决定用各平台APP嵌套一个HTML5浏 ...
- WebSocket学习笔记——无痛入门
WebSocket学习笔记——无痛入门 标签: websocket 2014-04-09 22:05 4987人阅读 评论(1) 收藏 举报 分类: 物联网学习笔记(37) 版权声明:本文为博主原 ...
- 玩转spring boot——websocket
前言 QQ这类即时通讯工具多数是以桌面应用的方式存在.在没有websocket出现之前,如果开发一个网页版的即时通讯应用,则需要定时刷新页面或定时调用ajax请求,这无疑会加大服务器的负载和增加了客户 ...
- spring boot websocket stomp 实现广播通信和一对一通信聊天
一.前言 玩.net的时候,在asp.net下有一个叫 SignalR 的框架,可以在ASP .NET的Web项目中实现实时通信.刚接触java寻找相关替代品,发现 java 体系中有一套基于stom ...
随机推荐
- Hive 系列(八)—— Hive 数据查询详解
一.数据准备 为了演示查询操作,这里需要预先创建三张表,并加载测试数据. 数据文件 emp.txt 和 dept.txt 可以从本仓库的resources 目录下载. 1.1 员工表 -- 建表语句 ...
- SpingBoot:整合Elasticsearch7.2.0
Spring boot 2.1.X整合Elasticsearch最新版的一处问题 新版本的Spring boot 2的spring-boot-starter-data-elasticsearch中支持 ...
- Leetcode之二分法专题-704. 二分查找(Binary Search)
Leetcode之二分法专题-704. 二分查找(Binary Search) 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 t ...
- ES6之模块化导入导出
1.概述 在js的历史上一直没有模块(module)体系,无法将一个大程序拆分成相互依赖的小文件,再用简单的方法拼装起来,这对开发大型的.复杂的项目形成了巨大障碍. 在 ES6 之前,社区制定了一些模 ...
- git 如何实现进行多人协作开发(远程仓库)
第一.Git作为分布式的版本控制系统,你是你本地仓库的主人,但是想要实现多人的协作开发,你就要将你本地的开发推送到远程共享仓库中供大家下载,本篇主要以github作为远程服务器来介绍有关远程仓库这块内 ...
- ST算法 Sliding Window algorithm template
ST算法(Sliding Window):A easy way to slove the substring problems algorithm template to slove substrin ...
- HDU-3478Catch二分图的否命题
HDU-3478Catch 题意:考虑Thief能否: 由于我推着推着就想到必须要三点可以互通,和二分图的结论正好相反,所以就试了一发, 真没想到thief的初始位置是不用考虑的. 下面是ac代码: ...
- 棋盘问题 POJ - 1321 [kuangbin带你飞]专题一 简单搜索
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. ...
- hadoop之数据倾斜
数据倾斜介绍 在做Shuffle阶段的优化过程中,遇到了数据倾斜的问题,造成了对一些情况下优化效果不明显.主要是因为在Job完成后的所得到的Counters是整个Job的总和,优化是基于这些Count ...
- Three.js 开发机房(四)
这一节我们讲讲怎么画机柜,其实机柜如果作的复杂一点.逼真一点可以用3D建模工具,不过一般的项目中也不用做的那么麻烦,那我们就可以将机柜抽象以下,首先它是一块具有长宽高的立方体铁块,然后我们从中间在掏掉 ...