websocket是一种长连接协议,相较于传统的http短连接,websocket不仅可以由客户端向服务器发送消息,可以主动向客户端发起信息,经常用于及时聊天,游戏和服务器向客户端推送信息。

主要优点:

1. 节约带宽。 不停地轮询服务端数据这种方式,使用的是http协议,head信息很大,有效数据占比低, 而使用WebSocket方式,头信息很小,有效数据占比高。
2. 无浪费。 轮询方式有可能轮询10次,才碰到服务端数据更新,那么前9次都白轮询了,因为没有拿到变化的数据。 而WebSocket是由服务器主动回发,来的都是新数据。

3. 实时性,考虑到服务器压力,使用轮询方式不可能很短的时间间隔,否则服务器压力太多,所以轮询时间间隔都比较长,好几秒,设置十几秒。 而WebSocket是由服务器主动推送过来,实时性是最高。

接下来我们看看怎么在springboot中使用websocket和html页面交互:

首先新建springboot项目,导入需要的websocket和springboot依赖,pom.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.lk</groupId><artifactId>websocketdemo</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>websocketdemo</name><description>Demo project for Spring Boot</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><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-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.properties中配置tomcat端口,我配置的是80:

server.port=80

然后就可以开始配置websocket了,首先创建WebSocket配置文件:WebSocketConfig.class

@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

再创建WebSocket服务器类:WebSocketServer.class,具体代码说明注释都写得很清楚了:

package com.cyjz.impl;import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;@Component
//访问服务端的url地址
@ServerEndpoint(value = "/websocket/{id}")
public class WebSocketServer {private static int onlineCount = 0;private static ConcurrentHashMap<String, WebSocketServer> webSocketSet = new ConcurrentHashMap<>();//与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;private static Logger log = LogManager.getLogger(WebSocketServer.class);private String id = "";/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(@PathParam(value = "id") String id, Session session) {this.session = session;this.id = id;//接收到发送消息的人员编号webSocketSet.put(id, this);     //加入set中addOnlineCount();           //在线数加1log.info("用户"+id+"加入!当前在线人数为" + getOnlineCount());try {sendMessage("连接成功");} catch (IOException e) {log.error("websocket IO异常");}}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {webSocketSet.remove(this);  //从set中删除subOnlineCount();           //在线数减1log.info("有一连接关闭!当前在线人数为" + getOnlineCount());}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, Session session) {System.err.println("来自客户端的消息:" + message);log.info("来自客户端的消息:" + message);//可以自己约定字符串内容,比如 内容|0 表示信息群发,内容|X 表示信息发给id为X的用户String sendMessage = message.split("[|]")[0];String sendUserId = message.split("[|]")[1];try {if(sendUserId.equals("0"))sendtoAll(sendMessage);elsesendtoUser(sendMessage,sendUserId);} catch (IOException e) {e.printStackTrace();}}/**** @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("发生错误");error.printStackTrace();}public void sendMessage(String message) throws IOException {this.session.getBasicRemote().sendText(message);}/*** 发送信息给指定ID用户,如果用户不在线则返回不在线信息给自己* @param message* @param sendUserId* @throws IOException*/public void sendtoUser(String message,String sendUserId) throws IOException {if (webSocketSet.get(sendUserId) != null) {if(!id.equals(sendUserId))webSocketSet.get(sendUserId).sendMessage( "用户" + id + "发来消息:" + " <br/> " + message);elsewebSocketSet.get(sendUserId).sendMessage(message);} else {//如果用户不在线则返回不在线信息给自己sendtoUser("当前用户不在线",id);}}/*** 发送信息给所有人* @param message* @throws IOException*/public void sendtoAll(String message) throws IOException {for (String key : webSocketSet.keySet()) {try {webSocketSet.get(key).sendMessage(message);} catch (IOException e) {e.printStackTrace();}}}public static synchronized int getOnlineCount() {return onlineCount;}public static synchronized void addOnlineCount() {WebSocketServer.onlineCount++;}public static synchronized void subOnlineCount() {WebSocketServer.onlineCount--;}public static ConcurrentHashMap<String, WebSocketServer> getWebSocketSet() {return webSocketSet;}public static void setWebSocketSet(ConcurrentHashMap<String, WebSocketServer> webSocketSet) {WebSocketServer.webSocketSet = webSocketSet;}
}

这时我们的webSocket后端已经创建好了,接下来写两个前端代码:


<!DOCTYPE HTML>
<html>
<head><title>WebSocket</title>
</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;//判断当前浏览器是否支持WebSocketif('WebSocket' in window){websocket = new WebSocket("ws://localhost:80/websocket/2");}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>
<!DOCTYPE HTML>
<html>
<head><title>WebSocket</title>
</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;//判断当前浏览器是否支持WebSocketif('WebSocket' in window){websocket = new WebSocket("ws://localhost:80/websocket/1");}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>

两个前端代码都是一样的,不同的地方在于一个访问是new WebSocket("ws://localhost:80/websocket/1");一个是new WebSocket("ws://localhost:80/websocket/2");即访问id传参不同,这时启动springboot后台服务,再打开两个前端html文件:

根据之前在代码中定义的输入格式:“信息内容|接受者Id|”进行输入,当输入id为0时表示群发:

Springboot中使用websocket发送信息给指定用户和群发相关推荐

  1. 解决:SpringBoot中使用WebSocket传输数据,提示 1009|The decoded text message was too big for the output buffer and

    SpringBoot项目中使用webSocket传输数据的时候,提示数据过大,断开了.服务器这边也接收不到数据. 报错如下: 1009|The decoded text message was too ...

  2. 实现微信公众号发送消息给指定用户

    一.前言 在实际项目开发中,需要实现消息中心向关注微信公众号的指定用户发送消息通知,在翻阅了网上很多资料及微信官方开发文档后,最终顺利完成功能开发,但是其中走过的路艰辛且曲折,因此特将开发过程中踩过的 ...

  3. 在linux系统中查看组管理信息命令,Linux用户和组管理常用命令

    导读 这篇文章主要介绍了 用户和组管理常见 ,总结整理了linux用户和组管理相关原理.操作 与使用注意事项,需要的朋友可以参考下. 1.用户隶属于用户组的 2.用户与用户组配置文件 1)用户组配置文 ...

  4. java和redis统计在线,在SpringBoot中使用Redis的zset统计在线用户信息

    统计在线用户的数量,是应用很常见的需求了.如果需要精准的统计到用户是在线,离线状态,我想只有客户端和服务器通过保持一个TCP长连接来实现.如果应用本身并非一个IM应用的话,这种方式成本极高. 现在的应 ...

  5. Spring Boot 2 中通过 WebSocket 发送 STOMP 消息

    描述 在这篇博客中,我们将了解如何设置应用程序以通过 WebSocket 连接,发送和接收 STOMP 消息.我们将以 Spring Boot 2 为基础,因为它包含对 STOMP 和 WebSock ...

  6. 向指定的服务器端口发送信息,向指定服务器的指定端口发送UDP包

    //功能:读取文件文件,向指定服务器的指定端口发送UDP包, //2015.9.26 OK #include #include #include #include #include #include ...

  7. vue全局安装jquery,vue使用bootstrap框架,vue中封装websocket通讯,vue引入element-ui 组件库,引入highcharts图表插件

    vue安装jquery: 1.使用vue-cli创建好vue项目后,在项目文件夹下,使用命令npm install jquery --save-dev 引入jquery. 2.修改项目文件 build ...

  8. SpringCloud工作笔记060---SpringBoot中使用WebSocket实现即时通讯_实现呼叫中心业务封装

    JAVA技术交流QQ群:170933152 ---------------我们主要用这个来转接,呼叫中心发过来的分机电话 呼叫中心:呼叫过程,首先呼叫中心运营商给个,api手册,api会规定,首先登陆 ...

  9. 使用信使服务批量发送信息

    使用信使服务批量发送信息 信使服务 设计需求 VBS设计 过程中已解决的问题 尚未解决的问题 2021.2.2更新:读取AD中计算机名的时候排除了已禁用的计算机 信使服务 信使服务在XP系统中是用ne ...

最新文章

  1. 页面GBK,用jquery.post乱码问题
  2. windows平台HTTP代理server搭建(CCproxy)
  3. 2 模版_你还只会套PPT模版吗? | 大学生PPT进阶指南(附免费资源amp;教程)
  4. leetcode算法题--扁平化嵌套列表迭代器
  5. linux root登陆ftp,LINUX服务器下用root登录ftp
  6. keepalived 多个应用_Keepalived与LVS部署多个服务
  7. 国庆中秋活动——读完这两套书,宝宝就变小小物理学家了!
  8. 标记偏见_分析师的偏见
  9. HDU-5935 Car 逆推 贪心 精度
  10. Qt笔记——添加菜单图片/添加资源文件
  11. 期待!2019年春晚将成为科技盛宴:5G、4K都安排上了
  12. JavaScript权威指南 - 数组
  13. Python--Turtle钟表
  14. msvcp140.dll丢失的解决方法_msvcp140.dll丢失怎样修复win10
  15. git stash暂存修改
  16. 以HT82K629B为主控的程序员专用CV键盘(无需代码烧写)
  17. 关于Intriguing properties of neural networks的理解
  18. 正则表达式 匹配中文,英文字母和数字及_长度详解
  19. 二十六万字详解bat文件
  20. matlab实现图形几何变换如平移,matlab实现平面图形的几何变换

热门文章

  1. Excel字符串比较(exact)
  2. 软件测试测试用例编写 不超过7步骤_教你快速编写一个合格的测试用例!
  3. vSphere虚拟化使用第三方备份方案常见CBT故障实战处理
  4. Nginx学习总结(9)——前端跨域问题解决
  5. Linux学习总结(19)——Linux中文本编辑器vim特殊使用方法
  6. python中pip不可用_python – pip无法确认SSL证书:SSL模块不可用
  7. TZOJ 5640: 数据结构实验:仓库管理
  8. 使用ldconfig命令将/usr/local/lib加入到默认库
  9. WIN7网络共享打印机设置 家庭工作组
  10. [Tjoi2016Heoi2016]排序[01序列]