SpringBoot2.0整合WebSocket,实现后端数据实时推送!
之前公司的某个系统为了实现推送技术,所用的技术都是ajax轮询,这种方式浏览器需要不断的向服务器发出请求,显然这样会浪费很多的带宽等资源,所以研究了下websocket,本文将详细介绍下。
一、什么是websocket?
websocket是html5开始提供的一种在单个tcp连接上进行全双工通讯的协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
websocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据,在websocket api中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
二、springboot整合websocket
新建一个spring boot项目spring-boot-websocket,按照下面步骤操作。
- pom.xml引入jar包
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-websocket</artifactid> </dependency>
- 新建websocket的配置类
这个配置类检测带注解@serverendpoint的bean并注册它们,配置类代码如下:
@configuration public class websocketconfig { /** * 给spring容器注入这个serverendpointexporter对象 * 相当于xml: * <beans> * <bean id="serverendpointexporter" class="org.springframework.web.socket.server.standard.serverendpointexporter"/> * </beans> * <p> * 检测所有带有@serverendpoint注解的bean并注册他们。 * * @return */ @bean public serverendpointexporter serverendpointexporter() { system.out.println("我被注入了"); return new serverendpointexporter(); } }
- 新建websocket的处理类
这个处理类需要使用@serverendpoint,这个类里监听连接的建立关闭、消息的接收等,具体代码如下:
@serverendpoint(value = "/ws/asset") @component public class websocketserver { @postconstruct public void init() { system.out.println("websocket 加载"); } private static logger log = loggerfactory.getlogger(websocketserver.class); private static final atomicinteger onlinecount = new atomicinteger(0); // concurrent包的线程安全set,用来存放每个客户端对应的session对象。 private static copyonwritearrayset<session> sessionset = new copyonwritearrayset<session>(); /** * 连接建立成功调用的方法 */ @onopen public void onopen(session session) { sessionset.add(session); int cnt = onlinecount.incrementandget(); // 在线数加1 log.info("有连接加入,当前连接数为:{}", cnt); sendmessage(session, "连接成功"); } /** * 连接关闭调用的方法 */ @onclose public void onclose(session session) { sessionset.remove(session); int cnt = onlinecount.decrementandget(); log.info("有连接关闭,当前连接数为:{}", cnt); } /** * 收到客户端消息后调用的方法 * * @param message * 客户端发送过来的消息 */ @onmessage public void onmessage(string message, session session) { log.info("来自客户端的消息:{}",message); sendmessage(session, "收到消息,消息内容:"+message); } /** * 出现错误 * @param session * @param error */ @onerror public void onerror(session session, throwable error) { log.error("发生错误:{},session id: {}",error.getmessage(),session.getid()); error.printstacktrace(); } /** * 发送消息,实践表明,每次浏览器刷新,session会发生变化。 * @param session * @param message */ public static void sendmessage(session session, string message) { try { // session.getbasicremote().sendtext(string.format("%s (from server,session id=%s)",message,session.getid())); session.getbasicremote().sendtext(message); } catch (ioexception e) { log.error("发送消息出错:{}", e.getmessage()); e.printstacktrace(); } } /** * 群发消息 * @param message * @throws ioexception */ public static void broadcastinfo(string message) throws ioexception { for (session session : sessionset) { if(session.isopen()){ sendmessage(session, message); } } } /** * 指定session发送消息 * @param sessionid * @param message * @throws ioexception */ public static void sendmessage(string message,string sessionid) throws ioexception { session session = null; for (session s : sessionset) { if(s.getid().equals(sessionid)){ session = s; break; } } if(session!=null){ sendmessage(session, message); } else{ log.warn("没有找到你指定id的会话:{}",sessionid); } } }
- 新建一个html
目前大部分浏览器支持websocket,比如chrome, mozilla,opera和safari,在html页面进行websocket的连接建立、收消息的监听,页面代码如下:
<html> <head> <meta charset="utf-8"> <title>websocket测试</title> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <style type="text/css"> h3,h4{ text-align:center; } </style> </head> <body> <h3>websocket测试,客户端接收到的消息如下:</h3> <textarea id = "messageid" readonly="readonly" cols="150" rows="30" > </textarea> <script type="text/javascript"> var socket; if (typeof (websocket) == "undefined") { console.log("遗憾:您的浏览器不支持websocket"); } else { console.log("恭喜:您的浏览器支持websocket"); //实现化websocket对象 //指定要连接的服务器地址与端口建立连接 //注意ws、wss使用不同的端口。我使用自签名的证书测试, //无法使用wss,浏览器打开websocket时报错 //ws对应http、wss对应https。 socket = new websocket("ws://localhost:8080/ws/asset"); //连接打开事件 socket.onopen = function() { console.log("socket 已打开"); socket.send("消息发送测试(from client)"); }; //收到消息事件 socket.onmessage = function(msg) { $("#messageid").append(msg.data+ "\n"); console.log(msg.data ); }; //连接关闭事件 socket.onclose = function() { console.log("socket已关闭"); }; //发生了错误事件 socket.onerror = function() { alert("socket发生了错误"); } //窗口关闭时,关闭连接 window.unload=function() { socket.close(); }; } </script> </body> </html>
三、查看运行效果
启动springboot项目
- 打开首页
本地浏览器打开首页http://localhost:8080/,出现websocket测试页面,同时后台打印连接的日志。
有连接加入,当前连接数为:1,sessionid=0
- 往客户端发送消息
通过上面日志可以看到客户端连接连接的sessionid,我测试时候sessionid是0,然后浏览器访问下面接口即可往客户端发送消息。
//参数说明: id:sessionid //参数说明: message:消息内容 http://localhost:8080/api/ws/sendone?id=0&message=你好java碎碎念
到此springboot整合websocket的功能已经全部实现,有问题欢迎留言沟通哦!
完整源码地址:
推荐阅读
3.一分钟带你学会利用mybatis-generator自动生成代码!
5.springboot系列-整合mybatis(注解方式)
如果觉得文章不错,希望可以随手转发或者”在看“哦,非常感谢哈!
关注下方公众号后回复「1024」,有惊喜哦!
本文由博客一文多发平台 openwrite 发布!