websocket简介以及使用

    技术2023-10-24  121

    这里写自定义目录标题

    websocket简介websocket协议与http协议的区别项目实战前端部分(客户端)后端代码,集成springbootsocket配置文件websocket服务端代码 websocket提供了发送信息的方法encode代码decode代码

    websocket简介

    websocket协议与http协议的区别

    HTTP协议介绍.

    websocket介绍 首先,Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说。 简单的举个例子吧,用目前应用比较广泛的PHP生命周期来解释。

    HTTP的生命周期通过Request来界定,也就是一个Request 一个Response,那么在HTTP1.0中,这次HTTP请求就结束了。 在HTTP1.1中进行了改进,使得有一个keep-alive,也就是说,在一个HTTP连接中,可以发送多个Request,接收多个Response。 但是请记住 Request = Response , 在HTTP中永远是这样,也就是说一个request只能有一个response。而且这个response也是被动的,不能主动发起。

    项目实战

    前端部分(客户端)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script> <title>Java后端WebSocket实现</title> </head> <body> 信息框:<input id="text" type="text"/> <button onclick="send()">发送</button> <hr/> <button onclick="closeWebSocket()">关闭WebSocket连接</button> <hr/> 收到的信息如下:</br> <div id="message"> </div> </body> <script type="text/javascript"> if(typeof(WebSocket) == "undefined") { alert("您的浏览器不支持WebSocket"); } /*var webSocket = new WebSocket("ws://127.0.0.1:8998/webSocket/1/liang");*/ var webSocket = new WebSocket("ws://localhost:8080/websocket"); //连接发生错误的回调方法 webSocket.onerror = function () { setMessageInnerHTML("WebSocket连接发生错误"); }; //连接成功建立的回调方法 webSocket.onopen = function () { alert(132) setMessageInnerHTML("WebSocket连接成功"); } //接收到消息的回调方法 webSocket.onmessage = function (event) { setMessageInnerHTML(event.data); } //连接关闭的回调方法 webSocket.onclose = function () { setMessageInnerHTML("WebSocket连接关闭"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭webSocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function () { closeWebSocket(); } //关闭WebSocket连接 function closeWebSocket() { webSocket.close(); } //发送消息 function send() { var message = $('#text').val(); webSocket.send(message); $("#text").val(""); } //将消息显示在网页上 var val = ""; function setMessageInnerHTML(innerHTML) { var temp = '<br/>' + innerHTML + '<br/>'; val = val + temp; $("#message").html(val); } </script> </html>

    后端代码,集成springboot

    websocket的依赖

    <!-- springboot版本 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <!--websocket依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
    socket配置文件
    package com.example.demo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * webSocket配置类,绑定前端连接端点url及其他信息 * * @author han * */ @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } /** * 注册webSocket端点,不注册的话也可以使用 */ @Override public void registerStompEndpoints(StompEndpointRegistry registry) { // 添加一个/WebSocketServer端点,客户端就可以通过这个端点来进行连接;withSockJS作用是添加SockJS支持 registry.addEndpoint("/websocket").setAllowedOrigins("*").withSockJS(); } }
    websocket服务端代码
    如果需要写的带参数的话可以选择使用使用restful风格每一个客户端连接带当前服务端时候,都会生成一个session对象,表示当前websocket长连接已经连接成功.服务端向客户端发送消息也是通过session对象提供的方法发送信息. package com.example.demo; import com.example.demo.util.WebSocketMapUtil; import org.springframework.stereotype.Component; import java.io.IOException; 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.ServerEndpoint; @Component @ServerEndpoint(value = "/websocket") public class MyWebSocket{ //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session=null; private static CopyOnWriteArraySet<MyWebSocket> webSocketSet = new CopyOnWriteArraySet<>(); /** * 连接建立成功调用的方法 * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 * @throws Exception */ @OnOpen public void onOpen(Session session) throws Exception{ this.session = session; System.out.println(this); webSocketSet.add(this); } /** * 连接关闭调用的方法 * @throws Exception */ @OnClose public void onClose() throws Exception{ //从map中删除 webSocketSet.remove(this); } /** * 收到客户端消息后调用的方法 * @param message 客户端发送过来的消息 * @param session 可选的参数 * @throws IOException */ @OnMessage public void onMessage(String message, Session session) throws IOException { /* try { MyWebSocket myWebSocket= ((MyWebSocket) WebSocketMapUtil.get(session.getQueryString().replace("service", "client"))); if(myWebSocket != null){ myWebSocket.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); }*/ for(MyWebSocket item: webSocketSet){ item.session.getBasicRemote().sendText(message); } } /** * 发生错误时调用 * @param session * @param error */ @OnError public void onError(Session session, Throwable error){ error.printStackTrace(); } /** * 发送消息方法。 * @param message * @throws IOException */ public void sendMessage(String message) throws IOException{ this.session.getBasicRemote().sendText(message); } /** * 群发消息方法。 * @param message * @throws IOException */ public void sendMessageAll(String message) throws IOException{ for(MyWebSocket myWebSocket : WebSocketMapUtil.getValues()){ myWebSocket.sendMessage(message); } } }

    websocket提供了发送信息的方法

    this.session.getBasicRemote()对象的方法. sendMessage(String message) 发送字符串数据sendObject(Object obj) 发送对象类型的数据,obj要求被encode才行,不然会报异常;
    encode代码

    本质 sendObject方法在调用时候,会先将参数obj进行encode,然后才会将encode后的数据发送给客户端. 其实就是将对象解析成字符串形式,再发送;

    这里推荐使用sendMessage方法,手动将参数对象进行解析成json字符串(使用alibb的fastjson依赖和方法).

    package com.example.demo.websocket; import com.alibaba.fastjson.JSON; import com.example.demo.bean.Per; import javax.websocket.EncodeException; import javax.websocket.EndpointConfig; public class WebSocketEncoder implements javax.websocket.Encoder.Text<Per> { @Override public void destroy() { } @Override public void init(EndpointConfig arg0) { } @Override public String encode(Per param) throws EncodeException { return JSON.toJSONString(param); } }
    decode代码
    对客户端发送的数据(String)编码成指定对象格式本质依然是使用的alibb的fastjson方法; package com.example.demo.websocket; import com.alibaba.fastjson.JSON; import com.example.demo.bean.Per; import javax.websocket.DecodeException; import javax.websocket.EndpointConfig; public class WebSocketDecoder implements javax.websocket.Decoder.Text<Per> { @Override public void destroy() { } @Override public void init(EndpointConfig arg0) { } @Override //返回值per是一个自定义的对象 public Per decode(String user) throws DecodeException { return JSON.parseObject(user, Per.class); } @Override public boolean willDecode(String arg0) { return true; } }
    Processed: 0.028, SQL: 9