300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > WebSocket 从入门到精通 -- Spring boot服务端客户端 -- HTML客户端

WebSocket 从入门到精通 -- Spring boot服务端客户端 -- HTML客户端

时间:2022-04-17 21:24:15

相关推荐

WebSocket 从入门到精通 -- Spring boot服务端客户端 -- HTML客户端

注意:学习本文章一定要打开自己的开发工具,代码中有详细的解释。电脑不在身边建议先收藏,方便日后观看。最后祝大家技术突飞猛进,早日拿到心仪的offer。

WebSocket -- 从入门到精通

基础讲解Spring Boot 服务端Spring Boot 客户端HTML 客户端 基础示例代码Spring Boot服务端maven引入依赖开启服务端自动注册@ServerEndpoint注解 Spring Boot 客户端maven引入依赖创建一个类,继承WebSocketClient添加一个带参构造重写下面四个方法直接copy源码 再自定义一个类,创建一个static静态方法返回一个WebSocketClient对象直接copy源码 编写一个Collections类,向服务端发送消息 HTML 客户端直接copy源码 进阶示例代码Spring Boot服务端自动注册@ServerEndpoint注解编写服务端代码向客户端推送请求所用实体类引入依赖第一次请求实体类第二次请求实体类 HTML客户端 超级进阶示例代码Spring Boot服务端代码改动之处maven引入依赖自动注册@ServerEndpoint注解开启服务端代码向客户端推送请求 H5 客户端代码 彩蛋(获取源码)

基础讲解

Spring Boot 服务端

这里我们需要先介绍几个注解

Spring Boot 客户端

创建步骤:

自定义一个类继承WebSocketClient声明一个带参的构造方法(参数为ServerEndpoint指定的URI)

例如:ws://localhost:8080/websocketdemo将参数通过super(serverUri)传给父类的构造方法;请看下方详细代码

HTML 客户端

//创建WebSocket对象var websocket = new WebSocket("ws://localhost:8080/websocketdemo");

四大监听参数

请求方法

基础示例代码

Spring Boot服务端

maven引入依赖

<!--WebSocket核心依赖包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.4.1</version><scope>compile</scope></dependency>

开启服务端

这里主要就是四大监听参数,以及设置URI地址。

import org.ponent;import javax.websocket.*;import javax.websocket.server.ServerEndpoint;//这里的服务地址为:ws://localhost:8080/websocketdemo@ServerEndpoint("/websocketdemo")@Componentpublic class MyDemoServer {/*** 百度搜索:程序员小哲* 建立连接成功调用* @param session*/@OnOpenpublic void onOpen(Session session) {System.out.println("连接成功!");}/*** 百度搜索:程序员小哲* 关闭连接时调用* @param session*/@OnClosepublic void onClose(Session session) {System.out.println("关闭连接!");}/*** 百度搜索:程序员小哲* 收到客户端消息后调用的方法* @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(Session session,String message) {System.out.println("接收消息:"+message);}/*** 百度搜索:程序员小哲* @param session* @param throwable*/@OnErrorpublic void onError(Session session, Throwable throwable) {System.out.println("连接异常:{}"+throwable);}}

自动注册@ServerEndpoint注解

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configurationpublic class WebSocketConfig {/*** ServerEndpointExporter 作用* 这个Bean会自动注册@ServerEndpoint* @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

Spring Boot 客户端

稍微复杂,可以使用HTML客户端

maven引入依赖

<!--WebSocket核心依赖包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.4.1</version><scope>compile</scope></dependency>

创建一个类,继承WebSocketClient

添加一个带参构造

重写下面四个方法

直接copy源码

import org.java_websocket.client.WebSocketClient;import org.java_websocket.handshake.ServerHandshake;import .URI;public class MyWebSocketClient extends WebSocketClient {public MyWebSocketClient(URI serverUri) {super(serverUri);}@Overridepublic void onOpen(ServerHandshake serverHandshake) {System.out.println("连接成功!");}@Overridepublic void onMessage(String s) {System.out.println("接收到服务端数据:"+s);}@Overridepublic void onClose(int i, String s, boolean b) {System.out.println("关闭连接"+s);}@Overridepublic void onError(Exception e) {System.out.println("发生异常"+e);}}

再自定义一个类,创建一个static静态方法返回一个WebSocketClient对象

直接copy源码

这里就是创建了连接服务器的方法。

import com.xiaozhe.websocket.MyWebSocketClient;import org.java_websocket.client.WebSocketClient;import .URI;import .URISyntaxException;public class WebSocketDemo {public static WebSocketClient webSocketClient() {try {MyWebSocketClient webSocketClient = new MyWebSocketClient(new URI("ws://localhost:8080/websocketdemo"));webSocketClient.connect();return webSocketClient;} catch (URISyntaxException e) {e.printStackTrace();}return null;}}

编写一个Collections类,向服务端发送消息

我们可以使用浏览器url方式访问,也可以通过postman等测试工具来进行访问。

url : localhost:8080/sendfirst

import com.xiaozhe.bo.FirstClient;import org.java_websocket.client.WebSocketClient;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class WebSocketController {WebSocketClient webSocketClient = WebSocketDemo.webSocketClient();@RequestMapping("sendfirst")public void sendfirst() {webSocketClient.send("百度搜索:程序员小哲");}}

HTML 客户端

直接copy源码

简单的h5客户端代码,可以创建连接,断开连接,向服务端发送数据。

<!DOCTYPE HTML><html><head><title>WebSocketDemo</title></head><body><button onclick="oppen()">创建链接</button><button onclick="closeWebSocket()">断开连接</button><hr><input id="text" type="text" /><button onclick="send()">向服务器发送数据</button><div id="message"></div></body><script type="text/javascript">var websocket = null;//创建连接function oppen(){//判断当前浏览器是否支持WebSocketif('WebSocket' in window){//连接WebSocket节点websocket = new WebSocket("ws://localhost:8080/websocketdemo");}else{alert('当前浏览器不支持websocket');}//连接发生错误的回调方法websocket.onerror = function(){setMessageInnerHTML("错误!");};//连接成功建立的回调方法websocket.onopen = function(event){setMessageInnerHTML("连接成功!");}//接收到消息的回调方法websocket.onmessage = function(event){setMessageInnerHTML(event.data);}//连接关闭的回调方法websocket.onclose = function(){setMessageInnerHTML("连接关闭!");}//监听窗口关闭事件,当窗口关闭时,主动去关闭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>

进阶示例代码

之前的例子是实现单个客户端向服务端发送信息,但是如果服务端向指定的客户端发消息应该怎么做呢。那么请看下面的代码:

建议大家将代码复制到IDE中,便于查看,代码中有详细注释便于理解。

Spring Boot服务端

自动注册@ServerEndpoint注解

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configurationpublic class WebSocketConfig {/*** ServerEndpointExporter 作用* 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint* @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

编写服务端代码

这里我们在主要的四大监听方法之外加了一些属性和方法。大家可以新建一个Spring boot项目来进行下面的项目。

import com.alibaba.fastjson.JSONObject;import com.example.demo.zo.Xiao;import com.example.demo.zo.Zhe;import org.ponent;import javax.websocket.*;import javax.websocket.server.ServerEndpoint;import java.io.IOException;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;@ServerEndpoint("/websocketdemoxiaozhe")@Componentpublic class MyServer {//将所有客户端对象储存到Map集合中private static Map<String, MyServer> clients = new ConcurrentHashMap<String, MyServer>();//会话private Session session;//会话唯一标识,使用cid来确定唯一的private String cid;/*** 百度搜索:程序员小哲* 建立连接成功调用* @param session*/@OnOpenpublic void onOpen(Session session) {System.out.println("连接成功!");}/*** 百度搜索:程序员小哲* 关闭连接时调用* @param session*/@OnClosepublic void onClose(Session session) {System.out.println("关闭连接!");}/*** 百度搜索:程序员小哲* 收到客户端消息后调用的方法* @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(Session session,String message) {// message是一个json// 将message进行反序列化// 详见我的另一篇博客:/xiaozhezhe0470/article/details/11065JSONObject jsonObject = JSONObject.parseObject(message);Zhe zhe = JSONObject.toJavaObject(jsonObject, Zhe.class);//由于我们是在创建之后才提交cid,所以我们需要在获取提交的信息的时候进行判断,查看是哪一次的请求if (zhe.getHi() != null){//第二次之后的请求System.out.println(zhe.getHi());}else {//第一次请求Xiao xiao = JSONObject.toJavaObject(jsonObject, Xiao.class);System.out.println(xiao);this.cid = xiao.getCid();this.session = session;clients.put(cid,this);try {//将信息返回到指定用户的页面中sendMessageTo("恭喜"+xiao.getWork()+xiao.getCname()+"注册成功!您的账号为:"+cid,cid);} catch (IOException e) {e.printStackTrace();}}}/*** 百度搜索:程序员小哲* @param session* @param throwable*/@OnErrorpublic void onError(Session session, Throwable throwable) {System.out.println("连接异常:{}"+throwable);}/*** 百度搜索:程序员小哲* 向指定的客户端发送数据* @param message 推送的信息* @param cid 客户id*/public void sendMessageTo(String message, String cid) throws IOException {MyServer myWebSocket = clients.get(cid);myWebSocket.session.getAsyncRemote().sendText(message);}/*** 百度搜索:程序员小哲* 给所有用户进行推送信息* @param message 推送的信息*/public void sendMessageAll(String message) throws IOException {for (MyServer item : clients.values()) {item.session.getAsyncRemote().sendText(message);}}}

向客户端推送请求

在这里我们新加了一个基础代码里面没有的类,就是给指定的用户推送消息。

import com.example.demo.config.MyServer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.io.IOException;@RestControllerpublic class ServiceToClientDemo {@Autowiredpublic MyServer myServer;/*** 给指定的用户推送信息* @param cid 用户注册后弹出的cid* @param message 想要推送给用户的信息*/@GetMapping("/sendToClient")public void sendTo(String cid,String message) throws IOException {myServer.sendMessageTo(message,cid);}/*** 给所有用户推送信息* @param msg 想要推送给用户的信息*/@GetMapping("/sendAllClient")public void sendAll(String msg) throws IOException {myServer.sendMessageAll(msg);}}

所用实体类

引入依赖

使用实体类之前需要引入@Data的依赖

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>

第一次请求实体类

import lombok.Data;@Datapublic class Xiao {private String cid;private String work;private String cname;}

第二次请求实体类

import lombok.Data;@Datapublic class Zhe {private String hi;}

HTML客户端

与基础代码相比,多了一个登陆认证。这里需要注意的是,我们需要先创建连接,然后登陆认证,最后在向服务端发送数据,这里没有加验证,不按照顺序来会报错的。

再有一个就是我在两个文本框里面加了默认的JSON大家直接点击即可,方便大家操作。

<!DOCTYPE HTML><html><head><title>Test My WebSocket</title></head><body><button onclick="oppen()">创建连接</button><button onclick="closeWebSocket()">断开连接</button><hr><input id="text01" type="text" value="{ 'cid': '713', 'cname': '小哲', 'work': '程序员' }"/><button onclick="first()">登陆认证</button><hr><input id="text" type="text" value="{ 'hi': '你好呀' }" /><button onclick="send()">向服务器发送数据</button><div id="message"></div></body><script type="text/javascript">var websocket = null;//创建连接function oppen(){//判断当前浏览器是否支持WebSocketif('WebSocket' in window){//var message01 = document.getElementById('text01').value;//连接WebSocket节点websocket = new WebSocket("ws://localhost:8080/websocketdemoxiaozhe");}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 first(){var message01 = document.getElementById('text01').value;websocket.send(message01);}//发送消息function send(){var message = document.getElementById('text').value;websocket.send(message);}</script></html>

超级进阶示例代码

大家有没有觉得每次创建连接在进行注册非常的麻烦,有没有一种办法可以直接在连接的时候就进行注册呢?那么请看下面的代码。

Spring Boot服务端代码

改动之处

一、 @ServerEndpoint("/websocketdemoxiaozhe01/{cid}")

在这里我们在后面加上了一个参数,就是我们的唯一标识cid。

二、 public void onOpen(@PathParam(“cid”) String cid, Session session) {…}

我们在onOpen方法里面多加了一个参数,注意第一个参数一定要用@PathParam修饰,不然项目跑不起来

然后就没有什么不一样了。直接上代码copy到开发工具上。

maven引入依赖

<!--WebSocket核心依赖包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.4.1</version><scope>compile</scope></dependency>

自动注册@ServerEndpoint注解

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configurationpublic class WebSocketConfig {/*** ServerEndpointExporter 作用* 这个Bean会自动注册使用@ServerEndpoint注解声明的websocket endpoint* @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

开启服务端代码

import org.ponent;import javax.websocket.*;import javax.websocket.server.PathParam;import javax.websocket.server.ServerEndpoint;import java.io.IOException;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;@ServerEndpoint("/websocketdemoxiaozhe01/{cid}")@Componentpublic class MyDemoServer {//将当前对象储存到Map集合中private static Map<String, MyDemoServer> clients = new ConcurrentHashMap<String, MyDemoServer>();//会话private Session session;//会话唯一标识private String cid;/*** 百度搜索:程序员小哲* 建立连接成功调用* @param session*/@OnOpenpublic void onOpen(@PathParam("cid") String cid, Session session) {System.out.println("连接成功!");this.cid = cid;this.session = session;clients.put(cid,this);try {//将信息返回到指定用户的页面中sendMessageTo("恭喜注册成功!您的账号为:"+cid,cid);} catch (IOException e) {e.printStackTrace();}}/*** 百度搜索:程序员小哲* 关闭连接时调用* @param session*/@OnClosepublic void onClose(Session session) {System.out.println("关闭连接!");}/*** 百度搜索:程序员小哲* 收到客户端消息后调用的方法* @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(Session session,String message) {System.out.println(message);}/*** 百度搜索:程序员小哲* @param session* @param throwable*/@OnErrorpublic void onError(Session session, Throwable throwable) {System.out.println("连接异常:{}"+throwable);}/*** 百度搜索:程序员小哲* 向指定的客户端发送数据* @param message 推送的信息* @param cid 客户id*/public void sendMessageTo(String message, String cid) throws IOException {MyDemoServer myWebSocket = clients.get(cid);myWebSocket.session.getAsyncRemote().sendText(message);}/*** 百度搜索:程序员小哲* 给所有用户进行推送信息* @param message 推送的信息*/public void sendMessageAll(String message) throws IOException {for (MyDemoServer item : clients.values()) {item.session.getAsyncRemote().sendText(message);}}}

向客户端推送请求

示例url:http://localhost:8080/sendToClient01?cid=111&message=你好

示例url:http://localhost:8080/sendAllClient01?message=你们好

import com.xiaozhe.mywebsocketserver.server.MyDemoServer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.io.IOException;@RestControllerpublic class ServiceToClientDemo {@AutowiredMyDemoServer myDemoServer;/*** 给指定的用户推送信息* @param cid 用户注册后弹出的cid* @param message 想要推送给用户的信息*/@GetMapping("/sendToClient01")public void sendTo(String cid,String message) throws IOException {myDemoServer.sendMessageTo(message,cid);}/*** 给所有用户推送信息* @param msg 想要推送给用户的信息*/@GetMapping("/sendAllClient01")public void sendAll(String msg) throws IOException {myDemoServer.sendMessageAll(msg);}}

H5 客户端代码

H5客户端唯一的区别就是在创建连接的时候将cid一起传到了后台。

websocket = new WebSocket(“ws://localhost:8080/websocketdemoxiaozhe01/” + message01);

<!DOCTYPE HTML><html><head><title>Test My WebSocket</title></head><body>websocketid<input id="text01" type="text" value="111"/><button onclick="oppen()">创建链接</button><hr><input id="text" type="text" /><button onclick="send()">向服务器发送数据</button><button onclick="closeWebSocket()">断开连接</button><div id="message"></div></body><script type="text/javascript">var websocket = null;//创建连接function oppen(){//判断当前浏览器是否支持WebSocketif('WebSocket' in window){var message01 = document.getElementById('text01').value;//连接WebSocket节点websocket = new WebSocket("ws://localhost:8080/websocketdemoxiaozhe01/" + message01);}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>

彩蛋(获取源码)

有问题可以扫码评论,我会一一进行回复。公众号以更名为:程序员小哲公众号内回复websocket领取本章源码

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。