HTML5 WebSocket

  • WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

  • WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

  • 在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

  • 现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

  • HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

  • 浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

  • 当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

  • 以下 API 用于创建 WebSocket 对象。

var Socket = new WebSocket(url, [protocol] );

以上代码中的第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。

WebSocket 属性

以下是 WebSocket 对象的属性。假定我们使用了以上代码创建了 Socket 对象:

属性 描述
Socket.readyState 只读属性 readyState 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。
Socket.bufferedAmount 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

WebSocket 事件

以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象:

事件 事件处理程序 描述
open Socket.onopen 连接建立时触发
message Socket.onmessage 客户端接收服务端数据时触发
error Socket.onerror 通信发生错误时触发
close Socket.onclose 连接关闭时触发

WebSocket 方法

以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:

方法 描述
Socket.send() 使用连接发送数据
Socket.close() 关闭连接

WebSocket 实例

WebSocket 协议本质上是一个基于 TCP 的协议。

为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。

客户端的 HTML 和 JavaScript

目前大部分浏览器支持 WebSocket() 接口,你可以在以下浏览器中尝试实例: Chrome, Mozilla, Opera 和 Safari。

runoob_websocket.html 文件内容

<!DOCTYPE HTML>
<html><head><meta charset="utf-8"><title>菜鸟教程(runoob.com)</title><script type="text/javascript">function WebSocketTest(){if ("WebSocket" in window){alert("您的浏览器支持 WebSocket!");// 打开一个 web socketvar ws = new WebSocket("ws://localhost:9998/echo");ws.onopen = function(){// Web Socket 已连接上,使用 send() 方法发送数据ws.send("发送数据");alert("数据发送中...");};ws.onmessage = function (evt) { var received_msg = evt.data;alert("数据已接收...");};ws.onclose = function(){ // 关闭 websocketalert("连接已关闭..."); };}else{// 浏览器不支持 WebSocketalert("您的浏览器不支持 WebSocket!");}}</script></head><body><div id="sse"><a href="javascript:WebSocketTest()">运行 WebSocket</a></div></body>
</html>

Springboot-h5websocket

pom

 <!--h5-websocket--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!--net.sf.json.JSONObject--><dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><version>2.4</version><classifier>jdk15</classifier></dependency>

客户端与服务器建立WebSocket连接,实际上是创建了一个Socket,这个Socket是共享与客户端和服务器的。两者只要往对应的Socket里操作,就可以实现双方实时通讯了

第一种方式:三个java类

  • Myhandle

    package com.liujiang.shop.controller;import net.sf.json.JSONObject;
    import org.springframework.stereotype.Service;
    import org.springframework.web.socket.*;import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;@Service
    public class MyHandler implements WebSocketHandler {//在线用户列表private static final Map<String, WebSocketSession> users;static {users = new HashMap<>();}//新增socket@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {System.out.println("成功建立连接");String ID = session.getUri().toString().split("ID=")[1];System.out.println(ID);if (ID != null) {users.put(ID, session);session.sendMessage(new TextMessage("成功建立socket连接"));System.out.println(ID);System.out.println(session);}System.out.println("当前在线人数:"+users.size());}//接收socket信息@Overridepublic void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {try{JSONObject jsonobject = JSONObject.fromObject(webSocketMessage.getPayload());System.out.println(jsonobject.get("id"));System.out.println(jsonobject.get("message")+":来自"+(String)webSocketSession.getAttributes().get("WEBSOCKET_USERID")+"的消息");sendMessageToUser(jsonobject.get("id")+"",new TextMessage("服务器收到了,hello!"));}catch(Exception e){e.printStackTrace();}}/*** 发送信息给指定用户* @param clientId* @param message* @return*/public boolean sendMessageToUser(String clientId, TextMessage message) {if (users.get(clientId) == null) return false;WebSocketSession session = users.get(clientId);System.out.println("sendMessage:" + session);if (!session.isOpen()) return false;try {session.sendMessage(message);} catch (IOException e) {e.printStackTrace();return false;}return true;}/*** 广播信息* @param message* @return*/public boolean sendMessageToAllUsers(TextMessage message) {boolean allSendSuccess = true;Set<String> clientIds = users.keySet();WebSocketSession session = null;for (String clientId : clientIds) {try {session = users.get(clientId);if (session.isOpen()) {session.sendMessage(message);}} catch (IOException e) {e.printStackTrace();allSendSuccess = false;}}return  allSendSuccess;}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {if (session.isOpen()) {session.close();}System.out.println("连接出错");users.remove(getClientId(session));}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {System.out.println("连接已关闭:" + status);users.remove(getClientId(session));}@Overridepublic boolean supportsPartialMessages() {return false;}/*** 获取用户标识* @param session* @return*/private Integer getClientId(WebSocketSession session) {try {Integer clientId = (Integer) session.getAttributes().get("WEBSOCKET_USERID");return clientId;} catch (Exception e) {return null;}}}

    1.实现了WebSocketHandler接口,并实现了关键的几个方法。

    ① afterConnectionEstablished(接口提供的):建立新的socket连接后回调的方法。主要逻辑是:将成功建立连接的webSocketSssion放到定义好的常量[private static final Map<String, WebSocketSession> users;]中去。这里也截取客户端访问的URL的字符串,拿到标识,以键值对的形式讲每一个webSocketSession存到users里,以记录每个Socket。

    ② handleMessage(接口提供的):接收客户端发送的Socket。主要逻辑是:获取客户端发送的信息。这里之所以可以获取本次Socket的ID,是因为客户端在第一次进行连接时,拦截器进行拦截后,设置好ID,这样也说明,双方在相互通讯的时候,只是对第一次建立好的socket持续进行操作。

    ③ sendMessageToUser(自己定义的):发送给指定用户信息。主要逻辑是:根据用户ID从常量users(记录每一个Socket)中,获取Socket,往该Socket里发送消息,只要客户端还在线,就能收到该消息。

    ④sendMessageToAllUsers (自己定义的):这个广播消息,发送信息给所有socket。主要逻辑是:跟③类型,只不过是遍历整个users获取每一个socket,给每一个socket发送消息即可完广播发送

    ⑤handleTransportError(接口提供的):连接出错时,回调的方法。主要逻辑是:一旦有连接出错的Socket,就从users里进行移除,有提供该Socket的参数,可直接获取ID,进行移除。这个在客户端没有正常关闭连接时,会进来,所以在开发客户端时,记得关闭连接

    ⑥afterConnectionClosed(接口提供的):连接关闭时,回调的方法。主要逻辑:一旦客户端/服务器主动关闭连接时,将个socket从users里移除,有提供该Socket的参数,可直接获取ID,进行移除。

  • WebSocketH5Config 这是配置文件

    package com.liujiang.shop.controller;import org.springframework.context.annotation.Configuration;
    import org.springframework.web.socket.config.annotation.EnableWebSocket;
    import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
    import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import javax.websocket.*;
    import javax.websocket.server.ServerEndpoint;
    import java.io.IOException;
    import java.util.concurrent.CopyOnWriteArraySet;//实现接口来配置Websocket请求的路径和拦截器。
    @Configuration
    @EnableWebSocket
    public class WebSocketH5Config implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {//handler是webSocket的核心,配置入口registry.addHandler(new MyHandler(), "/myHandler/{ID}").setAllowedOrigins("*").addInterceptors(new WebSocketInterceptor());}}

    1.@Configuration:注解标识该类为Spring的配置类

    2.@EnableWebSocket:开启注解接收和发送消息

    3.实现WebSocketConfigurer接口,重写registerWebSocketHandlers方法,这是一个核心实现方法,配置websocket入口,允许访问的域、注册Handler、定义拦截器。客户端通过“/myHandler/{ID}”直接访问Handler核心类,进行socket的连接、接收、发送等操作,这里由于还加了个拦截器,所以建立新的socket访问时,都先进来拦截器再进去Handler类,“new WebSocketInterceptor()”是我实现的拦截器,“new MyHandler()”是我实现的一个Handler类。
  • WebSocketInterceptor

package com.liujiang.shop.controller;import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;import java.util.Map;public class WebSocketInterceptor implements HandshakeInterceptor {//在握手之前执行该方法, 继续握手返回true, 中断握手返回false. 通过attributes参数设置WebSocketSession的属性@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> attributes) throws Exception {if (request instanceof ServletServerHttpRequest) {String ID = request.getURI().toString().split("ID=")[1];System.out.println("当前session的ID=" + ID);//ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;//HttpSession session = serverHttpRequest.getServletRequest().getSession();attributes.put("WEBSOCKET_USERID", ID);}return true;}
//完成握手之后执行该方法@Overridepublic void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {System.out.println("进来webSocket的afterHandshake拦截器!");}
}

1.实现了HandshakeInterceptor 接口,并实现了beforeHandshake该方法,该方法是在进入Handler核心类之前进行拦截。

这里主要实现的逻辑是:

截取客户端建立webSocket连接时发送的URL地址字符串,并通过对该字符串进行特殊标识截取操作,获取客户端发送的唯一标识(由自己定义的,一般是系统用户ID唯一标识,用以标识该用户),并把它以键值对的形式放到Session里,这样后期可以通过该session获取它对应的用户ID了。【一个session对应着一个webSocketSession】

  • html

    
    <!DOCTYPE html>
    <html>
    <head><title>socket.html</title><meta name="keywords" content="keyword1,keyword2,keyword3"><meta name="description" content="this is my page"><meta name="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>
    <!-- 公共JS --><script src="/assets/bower_components/jquery/dist/jquery.min.js"></script><script type="text/javascript">var userID="888";var websocket=null;$(function() {//创建WebSocketconnectWebSocket();})//强制关闭浏览器  调用websocket.close(),进行正常关闭window.onunload = function() {//关闭连接closeWebSocket();}//建立WebSocket连接function connectWebSocket(){console.log("开始...");//建立webSocket连接websocket = new WebSocket("ws://127.0.0.1:8080/myHandler/ID="+userID);//打开webSokcet连接时,回调该函数websocket.onopen = function () {console.log("onpen");}//关闭webSocket连接时,回调该函数websocket.onclose = function () {//关闭连接console.log("onclose");}//接收信息websocket.onmessage = function (msg) {console.log(msg.data);}}//发送消息function send(){var postValue={};postValue.id=userID;postValue.message=$("#text").val();websocket.send(JSON.stringify(postValue));}//关闭连接function closeWebSocket(){if(websocket != null) {websocket.close();}}</script>
    </body>
    </html>

页面比较简单,简单解释一下:

1.new WebSocket(“ws://127.0.0.1:9091/cloud-sbjm/myHandler/ID=”+userID),与服务器建立webSocket连接,后面的ID="+userID,是动态参数,跟服务器配置Handler的访问地址时对应"/myHandler/{ID}"。

2.H5也提供多个回调函数

onopen:打开webSokcet连接时,回调该函数

onclose:关闭webSocket连接时,回调该函数

onmessage:服务器给该socket发送消息时,回调该函数,获取消息

websocket.send(JSON.stringify(postValue));:给Socket发送消息,服务器获取

websocket.close();客户端主要关闭连接,会触发客户端的onclose方法和服务器的afterConnectionClosed方法

  • 到此服务端的开发也完成了,下面执行一下程序效果图:

一、建立连接

客户端:

访问路径加项目名,这里我的电商不用加项目名

访问路径,先访问项目里的html就可以

第二种实现方法

java

package com.aishang.day01;import java.io.IOException;
import java.util.Set;
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.PathParam;
import javax.websocket.server.ServerEndpoint;@ServerEndpoint(value="/ws/chat/{nickName}")
public class Chat {private static final Set<Chat> connections = new CopyOnWriteArraySet<Chat>();private String nickName; //接收用户名称private Session session; //建立的会话public Chat(){}/** 打开连接*/    @OnOpenpublic void onOpen(Session session,@PathParam(value="nickName") String nickName){this.session=session;this.nickName=nickName;connections.add(this);System.out.println("新用户连接进入,名字是:"+this.nickName);String message=String.format("System>%s %s",this.nickName,"hasjoined.");Chat.broadCast(message);}/** 关闭连接*/@OnClosepublic void onClose(){connections.remove(this);String message=String.format("System> %s, %s", this.nickName," has disconnection.");Chat.broadCast(message);}/** 接收信息*/@OnMessagepublic void onMessage(String message,@PathParam(value="nickName")String nickName){System.out.println("新消息from:"+nickName+" : "+message);Chat.broadCast(nickName+">"+message);}/** 错误消息*/@OnErrorpublic void onError(Throwable throwable){System.out.println(throwable.getMessage());}/** 广播消息*/private static void broadCast(String message){for(Chat chat:connections){try{synchronized (chat) { //线程同步控制并发访问chat.session.getBasicRemote().sendText(message);}}catch(IOException e){connections.remove(chat);try{chat.session.close();}catch(IOException e1){chat.broadCast(String.format("System> %s %s", chat.nickName," has bean disconnection."));}}}}
}

html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Testing websockets</title>
</head>
<body><div><input type="text" id="yourName"/><button id="start">click to start</button></div><div style="width:100%;"><div id="messages" style="border:5px solid red;width:50%;height:300px;margin-top:20px;"></div></div><div style="width:100%;margin-top:20px;"><div id="sends" style="float:left;width:50%;height:50px;margin-right:20px;"><input type="text"  id="MessageUN" style="width:100%;height:48px;"/></div><button style="float:left;width:10%;height:50px;" id="sendMessage">发送</button></div><script type="text/javascript">var button=document.getElementById("start");button.onclick=function(){var name=document.getElementById("yourName");console.log(name.value);var websocketAdd="ws://localhost:8080/1901/ws/chat/"+name.value;var webSocket=new WebSocket(websocketAdd); function onMessage(event) {document.getElementById('messages').innerHTML += '<br />' + event.data;}function onOpen(event) {document.getElementById('messages').innerHTML = 'Connection established';//一旦链接开始,尝试发出一条通讯消息start();alert("消息通道开启,可以发送消息了");//确认链接开始,就可以开始消息的发送了//首先绑定一个点击事件var sendMessage=document.getElementById("sendMessage");sendMessage.onclick=function(){var message= document.getElementById('MessageUN').value;//我们之前会有一个唯一的标识符,就是在click to start之前的标识符webSocket.send(message);//上边一部完成之后,会自动触发onmessage事件}}function start() {webSocket.send(name.value+" : "+'hello');}function onError(event) {alert(event.data);}webSocket.onerror = function(event) {onError(event)};webSocket.onopen = function(event) {onOpen(event)};webSocket.onmessage = function(event) {onMessage(event)};      }</script>
</body>
</html>

这种方式,只适于普通的web项目,java文件件放在src下,jsp或html文件放在webapps下

第三种方式

客户端

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<input type="text" id="box">发送
<script>var websocket = null;if(websocket in window){websocket = new websocket("ws://localhost:8080/websocket")}else{alert("浏览器不支持websocket")}websocket.onopen(function (event) {console.log("建立连接")})websocket.onclose(function (event) {console.log("连接关闭")})websocket.onmessage(function (event) {console.log("收到消息"+event.data)//弹出提醒和播放音乐等})websocket.onerror(function (event) {alert("websocket通信发生错误")})
//    窗口关闭的时候,关闭websocketwebsocket.onbeforeunload(function (event) {websocket.close();})
</script>
</body>
</html>

服务端:

@SpringBootApplication
@MapperScan("com.liujiang.shop.dao")
//@EnableWebSocket
public class ShopApplication {public static void main(String[] args) {SpringApplication.run(ShopApplication.class, args);}@Beanpublic ChatServer chatServer() {return new ChatServer();}@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}}
package com.liujiang.shop.controller;import javax.crypto.MacSpi;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;@ServerEndpoint(value = "/server")
public class ChatServer {//    private static int count = 0;
//
//    @OnOpen
//    public void open() {//        System.out.println("有客户端进行连接");
//    }
//
//    @OnMessage
//    public void message(String message, Session session) {//        System.out.println("客户端发送数据 -> " + message);
//        try {//            session.getBasicRemote().sendText(message);
//        } catch (IOException e) {//            e.printStackTrace();
//        }
//        count++;
//        if (count == 10) {//            System.out.println("发送的数据超过了十次,服务器告诉客户端关闭连接");
//            count = 0;
//            try {//                session.getBasicRemote().sendText(message);
//            } catch (IOException e) {//                e.printStackTrace();
//            }
//        }
//    }
//
//    @OnClose
//    public void close() {//        System.out.println("有客户端关闭了连接");
//    }private static final CopyOnWriteArraySet<ChatServer> connections = new CopyOnWriteArraySet<ChatServer>();private Session session; //建立的会话/** 打开连接*/@OnOpenpublic void onOpen(Session session) {this.session = session;connections.add(this);System.out.println("服务器有新的连接,总连接数:"+connections.size());
//        String message = String.format("System>%s %s", this.nickName, "hasjoined.");
//        ChatServer.broadCast(message);}/** 关闭连接*/@OnClosepublic void onClose() {connections.remove(this);
//        String message = String.format("System> %s, %s", this.nickName,
//                " has disconnection.");
//        ChatServer.broadCast(message);System.out.println("服务器断开的连接,总连接数:"+connections.size());}/** 接收信息*/@OnMessagepublic void onMessage(String message) {System.out.println("收到客户端发来的消息"  + message);
//        ChatServer.broadCast(nickName + ">" + message);}/** 错误消息*/@OnErrorpublic void onError(Throwable throwable) {System.out.println(throwable.getMessage());}/** 广播消息==发送消息*/public static void broadCast(String message) {for (ChatServer chat : connections) {//            try {//                synchronized (chat) { //线程同步控制并发访问
//                    chat.session.getBasicRemote().sendText(message);
//                }
//            } catch (IOException e) {//                connections.remove(chat);
//                try {//                    chat.session.close();
//
//                } catch (IOException e1) {//                    chat.broadCast(String.format("System> %s %s", "test",
//                            " has bean disconnection."));
//                }
//            }System.out.println("广播消息:"+message);try {chat.session.getBasicRemote().sendText(message);} catch (IOException e) {e.printStackTrace();}}}
}

前台模板

 <%--socket收到消息弹出提示框--%><%--<button type="button" class="btn btn-default" data-toggle="modal" data-target="#modal-default">--%><%--Launch Default Modal--%><%--</button>--%><div class="modal fade" id="myModal"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button><h4 class="modal-title">提醒</h4></div><div class="modal-body"><p>您有一条新的订单!&hellip;</p></div><div class="modal-footer"><button type="button" class="btn btn-default pull-left" data-dismiss="modal">忽略</button><button type="button" onclick="location.reload()" class="btn btn-primary">查看新的订单</button></div></div><!-- /.modal-content --></div><!-- /.modal -->

js

<script>console.log("websocket");var url = "ws://localhost:8080/server";var ws = "";if ("WebSocket" in window) {ws = new WebSocket(url);} else if ("MozWebSocket" in window) {ws = new MozWebSocket(url);}ws.onopen = function () {console.log("客户端已经打开了websocket连接,可以进行实时通信了");};ws.onmessage = function (e) {console.log("客户端接受到的数据:" + e.data);$("#myModal").modal('show');// if (e.data == "close") {//   //这里要注意onclose的第一个参数必须是1000或者3000—4999//   ws.onclose(1000, "服务器通知关闭");// } else {//   $(".panel-body").append("<p>" + e.data + "</p>");// }};ws.onerror = function (e) {console.log("websocket连接错误" + e.error);// ws.close(3000, "websocket连接异常导致的关闭");};ws.onclose = function (e) {console.log("websocket关闭连接:" + e.error);};ws.onbeforeunload = function (e) {ws.close();};</script>

vue的websocket

 data() {      return {        websock: null,}},created() {      this.initWebSocket();},destroyed() {      this.websock.close() //离开路由之后断开websocket连接},    methods: {initWebSocket(){ //初始化weosocketconst wsuri = "ws://127.0.0.1:8080";this.websock = new WebSocket(wsuri);this.websock.onmessage = this.websocketonmessage;this.websock.onopen = this.websocketonopen;this.websock.onerror = this.websocketonerror;this.websock.onclose = this.websocketclose;},websocketonopen(){ //连接建立之后执行send方法发送数据let actions = {"test":"12345"};this.websocketsend(JSON.stringify(actions));},websocketonerror(){//连接建立失败重连this.initWebSocket();},websocketonmessage(e){ //数据接收const redata = JSON.parse(e.data);},websocketsend(Data){//数据发送this.websock.send(Data);},websocketclose(e){  //关闭console.log('断开连接',e);},},}

通过事件,改造代码:

<template><div class="cart"><!-- 结算区域 --><div class="mui-card"><div class="mui-card-content"><div class="mui-card-content-inner pay"><div class="left"><p>总计(不含运费)</p><p>已勾选商品<span>{{$store.getters.getCartCountAndAmount.count}}</span> 件,总价<span>¥{{$store.getters.getCartCountAndAmount.amount}}</span></p></div><mt-button type="danger" @click="send">去结算</mt-button></div></div></div></div>
</template><script>
import numberboxCart from "./numberboxCart";
export default {data() {return {carList: [],websock: null};},methods: {initWebSocket() {//初始化weosocketconst wsuri = "ws://127.0.0.1:8080/server";this.websock = new WebSocket(wsuri);this.websock.onmessage = this.websocketonmessage;this.websock.onopen = this.websocketonopen;this.websock.onerror = this.websocketonerror;this.websock.onclose = this.websocketclose;},websocketonopen() {console.log("连接服务器成功");},websocketonerror() {//连接建立失败重连this.initWebSocket();},websocketonmessage(e) {//数据接收const redata = JSON.parse(e.data);},websocketsend(Data) {//数据发送this.websock.send(Data);},websocketclose(e) {//关闭console.log("断开连接", e);},send() {let actions = { test: "12345" };this.websocketsend(JSON.stringify(actions));}},created() {this.getCarList();this.initWebSocket();},destroyed() {this.websock.close(); //离开路由之后断开websocket连接}
};
</script>

继续改造成发送数据请求后台的访问路径

send() {// let actions = { test: "12345" };// this.websocketsend(JSON.stringify(actions));this.$http.jsonp('http://localhost:8080/user/order').then(res=>{console.log(res.body)})}

测试,回调函数每处理

  • 流程

  • 启动idea的shop

  • 启动vue里的server.js

  • 启动vue

  • 打开http://localhost:8080/jsp/index.jsp

  • 购物车结算点击是发送请求,后台接收到消息发送给后端的前端页面,弹出 对话框

问题:

  • 怎么在弹出框累计请求数量

H5-websocket实战案例相关推荐

  1. SpringBoot 整合WebSocket 简单实战案例

    前言 这个简单实战案例主要目的是让大家了解websocket的一些简单使用. 另外使用stomp方式的: <Springboot 整合 WebSocket ,使用STOMP协议 ,前后端整合实战 ...

  2. 视频教程-Vue全家桶前后台分离实战案例(含资料)-Vue

    Vue全家桶前后台分离实战案例(含资料) 张长志技术全才.擅长领域:区块链.大数据.Java等.10余年软件研发及企业培训经验,曾为多家大型企业提供企业内训如中石化,中国联通,中国移动等知名企业.拥有 ...

  3. 跟一夫学UI设计 APPUI综合设计与图标实战案例视频教程 photoshop绘制icon案例-王诚-专题视频课程...

    跟一夫学UI设计 APPUI综合设计与图标实战案例视频教程 photoshop绘制icon案例-651人已学习 课程介绍         跟一夫学UI设计 APPUI图标设计实战案例视频教程 phot ...

  4. html5帘幕,腾讯实战案例!聊聊刷一刷红包预热HTML 5背后的设计过程

    编者按:一个UV高达9700万的HTML 5页面是怎么设计出来的?这篇实战案例让你全方位感受腾讯设计师的流弊!作为元旦和除夕2亿现金红包预热HTML 5的设计师,今天里奥同学把设计过程中的思考和经验都 ...

  5. 2021年大数据Spark(四十一):SparkStreaming实战案例六 自定义输出 foreachRDD

    目录 SparkStreaming实战案例六 自定义输出-foreachRDD 需求 注意: 代码实现 SparkStreaming实战案例六 自定义输出-foreachRDD 需求 对上述案例的结果 ...

  6. 2021年大数据Spark(三十九):SparkStreaming实战案例四 窗口函数

    目录 SparkStreaming实战案例四 窗口函数 需求 代码实现 SparkStreaming实战案例四 窗口函数 需求 使用窗口计算: 每隔5s(滑动间隔)计算最近10s(窗口长度)的数据! ...

  7. 2021年大数据Spark(三十七):SparkStreaming实战案例二 UpdateStateByKey

    目录 SparkStreaming实战案例二 UpdateStateByKey 需求 1.updateStateByKey 2.mapWithState 代码实现 SparkStreaming实战案例 ...

  8. 2021年大数据Spark(三十六):SparkStreaming实战案例一 WordCount

    目录 SparkStreaming实战案例一 WordCount 需求 准备工作 代码实现 第一种方式:构建SparkConf对象 第二种方式:构建SparkContext对象 完整代码如下所示: 应 ...

  9. flash h5录音_博乐h5网站建设案例-AI优网络

    沈阳滑翔网站建设/设计沈阳荷兰村网站建设/设计沈阳和泰新城网站建设/设计沈阳黑山网站建设/设计沈阳红旗台网站建设/设计沈阳浑河堡网站建设/设计沈阳浑南中路网站建设/设计沈阳浑河站西网站建设/设计沈阳浑 ...

  10. 【分布式事务】tcc-transaction分布式TCC型事务框架搭建与实战案例(基于Dubbo/Dubbox)...

    一.背景 有一定分布式开发经验的朋友都知道,产品/项目/系统最初为了能够快速迭代上线,往往不太注重产品/项目/系统的高可靠性.高性能与高扩展性,采用单体应用和单实例数据库的架构方式快速迭代开发:当产品 ...

最新文章

  1. vivo手机计算机错误怎么弄,手机计算器出错,原因竟是人性化设计
  2. 在 .NET Compact Framework 2.0 中宿主 ActiveX 控件
  3. 对OS实验中的“管道”的一点儿理解
  4. macOS配置Visual Studio Code开发Java项目
  5. 判断一个int数组中的元素是否存在重复
  6. 869. 重新排序得到 2 的幂
  7. [转帖]Docker 清理占用的磁盘空间
  8. 面试官 | JVM 为什么使用元空间替换了永久代?
  9. 【集合】Java 集合的ConcurrentModificationException
  10. html select下拉菜单长度过长不出滚动条问题解决办法
  11. C++基础知识(二)命名空间
  12. mongodb之副本集搭建
  13. vue脚手架根据需要进行配置
  14. Learning AV Foundation(二)AVAudioPlayer
  15. 计算机应用程序没声音,电脑突然没声音,多半是这三个原因导致的-维修经验...
  16. 四十多岁的男人还适合重新创业吗?
  17. 【软件工程】------软件开发
  18. 路由器或交换机密码忘了——带你修改路由器+交换机密码
  19. Qualcomm 音频学习(Bring up)
  20. 史上最著名的10个思想实验(思想解放运动)

热门文章

  1. Araneid 蜘蛛纸牌游戏源代码
  2. TMS320F28335学习_CCS与JTAG仿真器连接常见问题汇总
  3. Android之TextView设置autoLink属性后自定义跳转到指定界面
  4. C语言程序设计期末复习重点知识,C语言程序设计期末总复习.ppt
  5. 浅谈计算机仿真技术对各行业发展的重要性和必要性
  6. 三相电压型整流器的设计与仿真
  7. 近期学到的css样式
  8. Redis中的Bitmaps、HyperLogLog、Geospatial
  9. 基于asp.net采购管理系统的设计与实现
  10. 基于RIFD的自习室座位管理系统设计与实现.rar(论文+项目源码)