springboot - websocket实现及原理
本文章包括websocket面试相关问题以及spring boot如何整合webSocket。
参考文档 https://blog.csdn.net/prayallforyou/article/details/53737901 、https://www.cnblogs.com/bianzy/p/5822426.html
webSocket是HTML5的一种新协议,它实现了服务端与客户端的全双工通信,建立在传输层,tcp协议之上,即浏览器与服务端需要先建立tcp协议,再发送webSocket连接建立请求。
webSocket的连接:客户端发送请求信息,服务端接受到请求并返回相应的信息。连接建立。客户端发送http请求时,通过 Upgrade:webSocket Connection:Upgrade 告知服务器需要建立的是webSocket连接,并且还会传递webSocket版本号,协议的字版本号,原始地址,主机地址等等。
webSocket相互通信的Header很小,大概只有2Bytes。
以下是基于spring boot及支持webScoket的高版本浏览器的配置过程。
一、pom.xml中引入webSocket组件
</dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
二、后台引入webSocket
要想让一个类处理webScoket的请求,需要两个东西:
① 类名上加webScoket请求拦截注释@ServerEndpoint(value="/***")
② 类需要继承org.springframework.web.socket.server.standard.ServerEndpointExporter,重写交互过程中各种情况下调用的方法(建立时、断开时、出错时、接收消息、发送消息)
针对②,一方面根据spring的IOC特性,需要反向代理,另一方面因为webSocket是一个功能而不仅仅是属于某个业务,所以应当在配置文件中声明。配置文件可以是xml文件,也可以是注释了@Configuration的类文件,根据个人喜好使用~,这里使用的是@Configuration。
@Configuration
public class ProjectConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
使用@ServerEndpoint(value="/***") 时会自动注入返回类型为ServerEndpointExporter的bean。等同于继承了ServerEndpointExporter类。继承类后再重写onOpen、onClose、onMessage、onError方法,因为不是直接使用继承,所以方法的重写也需要使用注释,代码如下
package com.example.SpringBootTry.controller.webSocket; 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.springframework.stereotype.Component; /**
* 双工通信websocket工具类
* @author wwl
*
*/
@ServerEndpoint(value="/webSocket")
@Component
public class WebSocketUtil{
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
private static CopyOnWriteArraySet<WebSocketUtil> webSocketSet = new CopyOnWriteArraySet<WebSocketUtil>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session; /**
* 连接建立成功调用的方法*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
webSocketSet.add(this); //加入set中
addOnlineCount(); //在线数加1
System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
try {
sendMessage("您是第" + getOnlineCount() + "个双工通信的用户!");
} catch (IOException e) {
System.out.println("IO异常");
}
} /**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
} /**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("来自客户端的消息:" + message);
//发送消息
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 发生错误时调用
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发生错误");
error.printStackTrace();
} /**
* 发送消息
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
} /**
* 群发自定义消息
* */
public static void sendInfo(String message) throws IOException {
for (WebSocketUtil item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
continue;
}
}
} public static synchronized int getOnlineCount() {
return onlineCount;
} public static synchronized void addOnlineCount() {
WebSocketUtil.onlineCount++;
} public static synchronized void subOnlineCount() {
WebSocketUtil.onlineCount--;
}
}
三、前端引入webSocket
使用 var websocket = new WebSocket("ws://localhost:8081/***") 建立webSocket连接,定义websocket的onerror、onopen、onmessage、onclose的属性,跟后台的四个方法相对应,完成合理的webSocket交互。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>websocket测试页面</title>
<meta http-equiv="keywords" content="websocket,例子">
<meta http-equiv="description" content="测试websocket">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
</head>
<body>
Welcome<br/>
<input id="text" type="text" /><button onclick="send()">Send</button> <button onclick="closeWebSocket()">Close</button>
<div id="message">
</div>
</body>
<script type="text/javascript">
var websocket = null; //判断当前浏览器是否支持WebSocket
if('WebSocket' in window){
websocket = new WebSocket("ws://localhost:8081/webSocket");
}else{
alert('Not support websocket')
} //连接发生错误的回调方法
websocket.onerror = function(){
setMessageInnerHTML("error");
}; //连接成功建立的回调方法
websocket.onopen = function(event){
setMessageInnerHTML("open");
} //接收到消息的回调方法
websocket.onmessage = function(event){
setMessageInnerHTML(event.data);
} //连接关闭的回调方法
websocket.onclose = function(){
setMessageInnerHTML("close");
} //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function(){
websocket.close();
} //将消息显示在网页上
function setMessageInnerHTML(innerHTML){
document.getElementById('message').innerHTML += innerHTML + '<br/>';
} //关闭连接
function closeWebSocket(){
websocket.close();
} //发送消息
function send(){
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</html>
以上为spring boot 整合webSocket的一些入门知识。有错误欢迎指正。
demo地址:https://github.com/ttjsndx/someDemo/blob/master/SpringBootTryDemo.rar
springboot - websocket实现及原理的更多相关文章
- springboot+websocket+sockjs进行消息推送【基于STOMP协议】
springboot+websocket+sockjs进行消息推送[基于STOMP协议] WebSocket是在HTML5基础上单个TCP连接上进行全双工通讯的协议,只要浏览器和服务器进行一次握手,就 ...
- SpringBoot+WebSocket
SpringBoot+WebSocket 只需三个步骤 导入依赖 <dependency> <groupId>org.springframework.boot</grou ...
- WebSocket是什么原理,为什么可以实现持久连接
本文摘抄自知乎,原文标题:WebSocket 是什么原理?为什么可以实现持久连接? Websocket只是协议而已. 一.WebSocket是HTML5出的东西(协议),也就是说HTTP协议没有变化, ...
- SpringBoot嵌入式Servlet配置原理
SpringBoot嵌入式Servlet配置原理 SpringBoot修改服务器配置 配置文件方式方式修改,实际修改的是ServerProperties文件中的值 server.servlet.con ...
- SpringBoot WebSocket STOMP 广播配置
目录 1. 前言 2. STOMP协议 3. SpringBoot WebSocket集成 3.1 导入websocket包 3.2 配置WebSocket 3.3 对外暴露接口 4. 前端对接测试 ...
- SpringBoot集成MyBatis底层原理及简易实现
MyBatis是可以说是目前最主流的Spring持久层框架了,本文主要探讨SpringBoot集成MyBatis的底层原理.完整代码可移步Github. 如何使用MyBatis 一般情况下,我们在Sp ...
- 【springboot】自动装配原理
摘自:https://mp.weixin.qq.com/s/ZxY_AiJ1m3z1kH6juh2XHw 前言 Spring翻译为中文是"春天",的确,在某段时间内,它给Java开 ...
- Java Springboot webSocket简单实现,调接口推送消息到客户端socket
Java Springboot webSocket简单实现,调接口推送消息到客户端socket 后台一般作为webSocket服务器,前台作为client.真实场景可能是后台程序在运行时(满足一定条件 ...
- Springboot+Websocket+JWT实现的即时通讯模块
场景 目前做了一个接口:邀请用户成为某课程的管理员,于是我感觉有能在用户被邀请之后能有个立马通知他本人的机(类似微博.朋友圈被点赞后就有立马能收到通知一样),于是就闲来没事搞了一套. 涉及技术栈 ...
随机推荐
- threejs 草场足球运动视角(三)
这次要模拟的场景如下图:就是在绿草地上足球的运动,并且视角会随着足球的运动发生变化,同时整个草地的视角也会旋转. 接下来,我们就对各个元素进行分析: 1,草地 用PlaneGeometry在三维空间里 ...
- Redis 持久化RDB 和AOF
一.持久化之全量写入:RDB rdb配置 [redis@6381]$ more redis.conf save 900 1 save 300 10 save 60 10000 dbfilename & ...
- Jenkins 配置邮件通知步骤
Jenkins 配置邮件通知前言 可以在Jenkins 中配置邮件通知,比如在构建失败时发送邮件通知项目组来及时修复问题. Jenkins 邮件通知功能的插件主要包括: Mailer Plugin ( ...
- 【转】 HDMI介绍与流程
转自:https://www.cnblogs.com/TaigaCon/p/3840653.html HDMI,全称为(High Definition Multimedia Interface)高清多 ...
- SpringBoot整合Mybatis注解版---update出现org.apache.ibatis.binding.BindingException: Parameter 'XXX' not found. Available parameters are [arg1, arg0, param1, param2]
SpringBoot整合Mybatis注解版---update时出现的问题 问题描述: 1.sql建表语句 DROP TABLE IF EXISTS `department`; CREATE TABL ...
- springboot返回页面
1.使用@Controller注解: @Controller必须配合模板 先导入依赖: <dependency> <groupId>org.springframework.bo ...
- Vue-devtools 安装浏览器调试
工欲善其事,必先利其器. 本文主要讲解Vue-devtools的安装和使用 安装方法有两个: 方法一:(前提条件需要FQ,省事省力省心方便快速) FQ =>谷歌商店 =>搜索 =>V ...
- CF-551-D-树dp/思维
http://codeforces.com/contest/1153/problem/D 给出一颗有根树,叶子节点可以从1开始赋值但不能相同,每个节点有一个属性max/min表示选择所有儿子值中的ma ...
- uva 10288 gailv
Problem F Coupons Input: standard input Output: standard output Time Limit: seconds Memory Limit: MB ...
- 3DsMax 自动化操作(maxScript)
这是我编写的一部分maxScript 脚本,专注于3DsMax 快速建模,程序化地为我们完成一些繁琐的工作. 可以极大提高公司开发的效率! 2019年04月09日 :上传 今年新开发的插件,还有很多, ...