感谢作者,支持原创: https://blog.csdn.net/moshowgame/article/details/80275084

什么是WebSocket?

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

为什么需要 WebSocket?

初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?

  • 答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起,HTTP 协议做不到服务器主动向客户端推送信息。

举例来说,我们想要查询当前的排队情况,只能是页面轮询向服务器发出请求,服务器返回查询结果。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此WebSocket 就是这样发明的。

Maven依赖

         <!--springboot的高级组件会自动引用基础的组件-->
<!--,像spring-boot-starter-websocket就引入了spring-boot-starter-web和spring-boot-starter,-->
<!--所以不要重复引入。-->
<!--JavaEE标准-->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<scope>provided</scope>
</dependency>
<!--websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

WebSocket配置类

 package com.zr.demo.config;

 import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter; /**
* @Author: Hujh
* @Date: 2019/7/16 11:10
* @Description: WebSocket配置类
*/
@Configuration
public class WebSocketConfig { /*使用@ServerEndpoint创立websocket endpoint*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

WebSocketServer

因为WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller直接@ServerEndpoint("/websocket")@Component启用即可,然后在里面实现@OnOpen,@onClose,@onMessage等方法

 package com.zr.demo.socket;

 import org.springframework.stereotype.Component;

 import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet; /**
* @Author: Hujh
* @Date: 2019/7/16 11:13
* @Description: webSocket实现类
*/
@ServerEndpoint(value = "/webSocket")
@Component
public class WebSocket {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<WebSocket>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session; /**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session) {
this.session = session; //加入set中
webSocketSet.add(this);
addOnlineCount(); //在线数加1
System.out.println("有新连接加入!当前在线人数为:" + getOnlineCount());
try {
sendMessage("连接成功");
} 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); //群发消息
for (WebSocket item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* 发生错误时调用
@OnError
*/
public void onError(Session session, Throwable error) {
System.out.println("发生错误");
error.printStackTrace();
} /*
* @Title: sendMessage
* @Author : Hujh
* @Date: 2019/7/17 10:52
* @Description : 发送消息
* @param : message
* @Return : void
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
} /*
* @Title: sendInfo
* @Author : Hujh
* @Date: 2019/7/17 10:52
* @Description : 群发自定义消息
* @param : message
* @Return : void
*/
public static void sendInfo(String message) throws IOException {
for (WebSocket item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
continue;
}
}
} /*
* @Title: getOnlineCount
* @Author : Hujh
* @Date: 2019/7/17 10:51
* @Description : 获得当前在线人数
* @param :
* @Return : int
*/
public static synchronized int getOnlineCount() {
return onlineCount;
} /*
* @Title: addOnlineCount
* @Author : Hujh
* @Date: 2019/7/17 10:51
* @Description : 在线人数+1
* @param :
* @Return : void
*/
public static synchronized void addOnlineCount() {
WebSocket.onlineCount++;
} /*
* @Title: subOnlineCount
* @Author : Hujh
* @Date: 2019/7/17 10:52
* @Description :在线人数-1
* @param :
* @Return : void
*/
public static synchronized void subOnlineCount() {
WebSocket.onlineCount--;
} }

消息推送

至于推送新信息,可以再自己的Controller写个方法调用WebSocket.sendInfo();

 package com.zr.demo.controller;

 import com.zr.demo.socket.WebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; /**
* @Author: Hujh
* @Date: 2019/7/19 15:40
* @Description: 消息发送控制器
*/
@RestController
public class SendMessageController { @Autowired
private WebSocket webSocket; @RequestMapping("sendInfo")
public String sendInfo(@RequestParam String msg) {
try {
webSocket.sendInfo(msg);
} catch (Exception e) {
e.printStackTrace();
return "信息发送异常!";
} return "发送成功~";
} }

页面代码

 <!DOCTYPE HTML>
<html>
<head>
<title>WebSocket</title>
</head> <body>
<div style="width: 800px;height: 100%; margin: 0px auto;">
<span style="color: coral; font-size: 22px;"> Welcome WebSocket</span><br/><br/>
<div id="message">
</div>
</div>
</body> <script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
if('WebSocket' in window){
websocket = new WebSocket("ws://localhost:8082/webSocket");
}else{
alert('连接失败!!')
} //连接发生错误的回调方法
websocket.onerror = function(){
setMessageInnerHTML("error");
}; //连接成功建立的回调方法
websocket.onopen = function(event){
setMessageInnerHTML("webSocket 连接成功~");
} //接收到消息的回调方法
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();
} </script>
</html>

测试效果

1.建立两个连接

2.消息推送

 注:本文仅作为个人学习记录,不提供任何参考价值!

SpringBoot2.0集成WebSocket,实现后台向前端推送信息的更多相关文章

  1. springboot2.0集成webSocket

    WebSocket和http的区别? http协议是用在应用层的协议,他是基于tcp协议的,http协议建立链接也必须要有三次握手才能发送信息. http链接分为短链接,长链接,短链接是每次请求都要三 ...

  2. Django2.0.4 + websocket 实现实时通信,主动推送,聊天室及客服系统

    webSocket是一种在单个TCP连接上进行全双工通信的协议. webSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据.在WebSocket API中,浏览器 ...

  3. SpringBoot集成websocket发送后台日志到前台页面

    业务需求 后台为一个采集系统,需要将采集过程中产生的日志实时发送到前台页面展示,以便了解采集过程. 技能点 SpringBoot 2.x websocket logback thymeleaf Rab ...

  4. SpringBoot2.x集成WebSocket

    WebSocket 不做过多得介绍,这里有篇比较全面得文章      Spring Boot系列十六 WebSocket简介和spring boot集成简单消息代理 我这里是精简版,只挑出核心代码记录 ...

  5. spring集成webSocket实现服务端向前端推送消息

    原文:https://blog.csdn.net/ya_nuo/article/details/79612158 spring集成webSocket实现服务端向前端推送消息   1.前端连接webso ...

  6. SpringBoot2.0集成FastDFS

    SpringBoot2.0集成FastDFS 前两篇整体上介绍了通过 Nginx 和 FastDFS 的整合来实现文件服务器.但是,在实际开发中对图片或文件的操作都是通过应用程序来完成的,因此,本篇将 ...

  7. (补漏)Springboot2.0 集成shiro权限管理

    原文Springboot2.0 集成shiro权限管理 一.关于停止使用外键. 原本集成shiro建立用户.角色.权限表的时候使用了外键,系统自动创建其中两个关联表,用@JoinTable.看起来省事 ...

  8. SpringBoot2.0集成Shiro

    1.shiro的三个核心概念: 1)Subject:代表当前正在执行操作的用户,但Subject代表的可以是人,也可以是任何第三方系统帐号.当然每个subject实例都会被绑定到SercurityMa ...

  9. 为美多商城(Django2.0.4)添加基于websocket的实时通信,主动推送,聊天室及客服系统

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_67 websocket是个啥? webSocket是一种在单个TCP连接上进行全双工通信的协议 webSocket使得客户端和服务 ...

随机推荐

  1. 用TTcpClient和TTcpServer进行文件的传输

    发送数据时有Sendln,SendBuf,SendStream.接收数据时有Receiveln,ReceiveBuf,当时我很奇怪为什么没有ReceiveStream.因为很自然的想到是对应关系的.但 ...

  2. 用CDialog实现的消息框MessageBoxST类

    http://blog.csdn.net/akof1314/article/details/5078563

  3. Eric Linux - 1 Basic concepts of linux

    Computer basic Computer 5 parts CPU Input Output Memory External storage device. CPU RISC: Reduced I ...

  4. springmvc拦截请求

    springmvc.xml <!--拦截请求 --> <mvc:interceptors> <mvc:interceptor> <!-- 要拦截的请求类型 / ...

  5. android 写文件到sd卡问题小记

    android 写文件到sd卡问题小记 事情是这样子的.... 这天我开始编写项目调试工具,高大上不?-----其实就是记录实时网络请求和崩溃日志相关等的小工具(此处一个会心的微笑). 然后我是这样写 ...

  6. 3020配置_Java_win10

    1. 安装Java SE平台 1°  下载 https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-213315 ...

  7. 利用Maven, 搭建最简单的SpringMVC框架

    本文介绍使用maven搭建SpringMVC最简单的框架程序过程,适合初学者上手. 文章下载

  8. Hadoop —— 单机环境搭建

    一.前置条件 Hadoop的运行依赖JDK,需要预先安装,安装步骤见: Linux下JDK的安装 二.配置免密登录 Hadoop组件之间需要基于SSH进行通讯. 2.1 配置映射 配置ip地址和主机名 ...

  9. 【JDK基础】java基础的一些资料

    工具:https://blog.csdn.net/javazejian/article/details/72828483 类加载器:https://blog.csdn.net/X5fnncxzq4/a ...

  10. centos7.3nginx启动命令

    #!/bin/sh # chkconfig: 2345 80 90 # description: Start and Stop nginx #PATH=/usr/local/sbin:/usr/loc ...