后端:Java
前端: Vue.js
框架:SpringBoot
websocket的功能:简单说一下。主要就还是后台向前台主动推送消息方便界面渲染的一个功能。
适应场景:数据实时展示的时候,类似于数据监控界面。当我们的数据实时变化的时候,就需要一个后端主动向前端推送数据的东西,没错他就是websocket(个人是这样理解的哈,目前只挖掘到此功能。如理解有误还望指正!)
ajax轮询或者手动F5:一般情况下我们需要改变界面数据的时候,类似于一个界面,我们点击界面跳转的时候回向后端发送一个请求获取数据然后进行界面渲染。当然这样的方式只会在第一次进入界面或者手动F5的时候才会生效。或者进行ajax轮询,定时向后台发送请求,询问后台数据是否变化。大致的意思就是每隔一段时间询问一次后台,有没有数据更新。没有就没有,有的话就返回刷新界面。当然可想而知对于内存和效率的影响肯定是有的。轮询时间过长会导致数据不及时,过短对资源损耗又会较大。
websocket的优势:websocket是基于TCP协议的一个框架,当我们进入界面的时候会和后台建立连接,当我们后台一有数据更新的时候,第一时间就推送到前端。简而言之就是变被动为主动。个人觉得这个东西还是比较实用的,今天就来分享一个简单的websocket操作。
首先的当然是依赖了,版本看自己需求吧,我用的是2.2.0:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>2.2.0.RELEASE</version> </dependency>服务端连接工具类WS:
@ServerEndpoint(value = "/ws") @Component @Slf4j public class WS { /** * 存放所有在线的客户端 */ private static Map<String, Session> clients = new ConcurrentHashMap<>(); private Session session; private static CopyOnWriteArraySet<WS> ws=new CopyOnWriteArraySet<>(); @OnOpen public void onOpen(Session session) { this.session = session; log.info("有新的客户端连接了: {}", session.getId()); //将新用户存入在线的组 clients.put(session.getId(), session); } /** * 客户端关闭 * @param session session */ @OnClose public void onClose(Session session) { log.info("有用户断开了, id为:{}", session.getId()); //将掉线的用户移除在线的组里 clients.remove(session.getId()); } /** * 发生错误 * @param throwable e */ @OnError public void onError(Throwable throwable) { throwable.printStackTrace(); } /** * 收到客户端发来消息 * @param message 消息对象 */ @OnMessage public void onMessage(String message) { log.info("服务端收到客户端发来的消息: {}", message); this.sendAll(message); } /** * 群发消息 * @param message 消息内容 */ public void sendAll(String message) { for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) { sessionEntry.getValue().getAsyncRemote().sendText(message); } } public void sendMessage(String message){ for(WS webSocket : ws){ log.info("【websocket消息】广播消息:{}",message); try { webSocket.session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } } }客户端配置类WebSocketConfig:
@Configuration @ConditionalOnWebApplication public class WebSocketConfig { //使用boot内置tomcat时需要注入此bean @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }以上,服务端的代码姑且是可以了。
然后我们来配置客户端的(也就是前端),我这边用的是Vue,我们只用在js里面的methods里面定义一个connect的方法,如下connectWS:
connectWS : function(){ var ws = null; if('WebSocket' in window) { ws = new WebSocket('ws://127.0.0.1:8081/ws'); }else { alert('该浏览器不支持websocket!'); } ws.onopen = function (event) { console.log('建立连接'); } ws.onclose = function (event) { console.log('连接关闭'); } ws.onmessage = function (event) { console.log('收到消息:' + event.data) //所要执行的操作,关键一步,这里会接收到后台发过来的数据或者消息,我们在这里构造一个方法进行响应的数据渲染即可达到我们的目的。 } ws.onerror = function () { alert('ws通信发生错误!'); } window.onbeforeunload = function () { ws.close(); } }然后默认在构造器里面启动该方法,意为进入界面即连接。
这样我们的websocket基本就搭建完成了。然后接下来我们就可以使用了。我们在后台对应的位置,比如某个数据入库的地方,当我们数据入库,我们就发送一个数据包过去。这里我写的是发送字符串可以传Json字符串哈,后面有时间再来讲更详细的吧。我们接着来讲发送一个字符串。
放在在后端数据更新的地方,或者定时启动的线程的方法里面即可使用。开袋即食,哈哈
@Autowired private WS ws; //注入工具类 private void testSendMsg(){ ws.sendAll("发车成功"); //进 }然后在前端onmessage里面就会收到我们发送的 —“发车成功” —了。
当然本文只是简单的搭建,这个存在个很大的漏洞,也就是当我们有很多界面的时候,我们发送的时候就会更新到所有在线的界面。扩展的话会受限。公司项目也有用websocket,不知道是不是用的太老了,和这个我临时整合的差异还是较大的。后面有时间的话再来写一篇升级版的吧。不同界面单独推送
这个是我前段时间刷题,搭的一个小项目,截取了里面的websocket部分,可能会有纰漏的地方,但是目测应该跑起来是没问题的。文笔有限,如有错误,还望路过的大佬们指正!手动滑稽~~~~
私信好像不能发百度云,小伙伴需要项目源码的可以点传送门链接下载吧:》》提取传送门 提取码:07mq
