SpringBoot如何添加WebSocket的方法示例

网友投稿 662 2023-03-18

SpringBoot如何添加WebSocket的方法示例

SpringBoot如何添加WebSocket的方法示例

一、WebSocket介绍

网站上的即时通讯是很常见的,比如网页的QQ,聊天系统等。按照以往的技术能力通常是采用轮询、Comet技术解决。

HTTP协议是非持久化的,单向的网络协议,在建立连接后只允许浏览器向服务器发出请求后,服务器才能返回相应的数据。当需要即时通讯时,通过轮询在特定的时间间隔(如1秒),由浏览器向服务器发送Request请求,然后将最新的数据返回给浏览器。这样的方法最明显的缺点就是需要不断的发送请求,而且通常HTTP request的Header是非常长的,为了传输一个很小的数据 需要付出巨大的代价,是很不合算的,占用了很多的宽带。

缺点:会导致过多不必要的请求,浪费流量和服务器资源,每一次请求、应答,都浪费了一定流量在相同的头部信息上

然而WebSocket的出现可以弥补这一缺点。在WebSocket中,只需要服务器和浏览器通过HTTP协议进行一个握手的动作,然后单独建立一条TCP的通信通道进行数据的传送。

二、WebSocket运行机制

WebSocket 是 HTML5 一种新的协议,也是一个典型的应用层协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是:

WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;

WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。

非 WebSocket 模式传统http:// HTTP 客户端与服务器的交互如下图所示:

使用 WebSocket 模式客户端与服务器的交互如下图:

三、WebSocket实现

这里通过一个简单的聊天例程,实现spring boot +websocket代码的演示。

引入maven

org.springframework.boot

spring-boot-starter-websocket

2.3.4.RELEASE

配置类WebConfig

package org.antry.config;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**

* @ClassName WebSocketConfig

* @Description TODO

* @Autor TT

* @Date 2020/10/9 23:00

* @Version 1.0

*/

@Configuration

public class WebSocketConfig {

@Bean

public ServerEndpointExporter serverEndpointExporter() {

return new ServerEndpointExporter();

}

}

WebSocket类

在这个类里,有一个集合,用来存放所有连接。

当有新的连接进来时,在onOpen()方法中,我们每个连接都会存下对应id作为标识。假设这个id已经存过,则会关闭此连接,防止同一个id多处登录。

连接断开时,在onClose()方法中,将此连接移出集合。

当有新的消息发送过来时,会去遍历连接,找到对应接收人id的连接,然后把消息推送给接收人。

package org.antry.websocket;

import org.springframework.stereotype.Component;

import javax.websocket.OnClose;

import javax.websocket.OnMessage;

import javax.websocket.OnOpen;

import javax.websocket.Session;

import javax.websocket.server.PathParam;

import javax.websocket.server.ServerEndpoint;

import java.io.IOException;

import java.util.List;

import java.util.concurrent.CopyOnWriteArrayList;

import java.util.concurrent.atomic.AtomicInteger;

/**

* @ClassName MyWebsocket

* @Description TODO

* @Autor TT

* @Date 2020/10/10 11:02

* @Version 1.0

*/

@ServerEndpoint(value = "/websocket/{user}")

@Component

public class MyWebsocket {

// 通过类似GET请求方式传递参数的方法(服务端采用第二种方法"WebSocketHandler"实现)

// websocket = new WebSocket("ws://127.0.0.1:18080/testWebsocket?id=23&name=Lebron");

/**

* 在线人数

*/

public static AtomicInteger onlineNumber = new AtomicInteger(0);

/**

* 所有的对象,每次连接建立,都会将我们自己定义的MyWebsocket存放到List中,

*/

public static List webSockets = new CopyOnWriteArrayList();

/**

* 会话,与某个客户端的连接会话,需要通过它来给客户端发送数据

*/

private Session session;

/**

* 每个会话的用户

*/

private String user;

/**

* 建立连接

*

* @param session

*/

@OnOpen

public void onOpen(Session session, @PathParam("user") String user) {

System.err.println(user);

if (user == null || "".equals(user)) {

try {

session.close();

} catch (IOException e) {

e.printStackTrace();

}

return;

}

onlineNumber.incrementAndGet();

for (MyWebsocket MyWebsocket : webSockets) {

if (user.equals(MyWebsocket.user)) {

try {

session.close();

} catch (IOException e) {

e.printStackTrace();

}

return;

}

}

this.session = session;

this.user = user;

webSockets.add(this);

}

/**

* 连接关闭

*/

@OnClose

public void onClose() {

onlineNumber.decrementAndGet();

webSockets.remove(this);

}

/**

* 收到客户端的消息

*

* @param message 消息

* @param session 会话

*/

@OnMessage

public void onMessage(String message, Session session, @PathParam("user") String user) {

System.err.println(message);

String[] strArr = message.split("~");

pushMessage(user,strArr[0],strArr[1]);

}

/**

* 发送消息

*

* @param message 消息

*/

public void sendMessage(String message) {

try {

session.getBasicRemote().sendText(message);

} catch (IOException e) {

e.printStackTrace();

}

}

/**

* 消息推送

*

* @param message

* @param uuid uuid为空则推送全部人员

*/

public static void pushMessage(String user, String message, String uuid) {

if (uuid == null || "".equals(uuid)) {

for (MyWebsocket MyWebsocket : webSockets) {

MyWebsocket.sendMessage(user + ":" + message);

}

} else {

for (MyWebsocket MyWebsocket : webSockets) {

if (uuid.equals(MyWebsocket.user)) {

MyWebsocket.sendMessage(message);

}

}

}

}

}

两个简单的前端页面,他们的不同是,接收id和发送id不同。

testOne.html

testOne.js

var websocket = null;

var sendId = 0;

var receiveId = 1;

//---------------------------

/**

* 初始化websocket

* @param id

*/

doInit(sendId)

function doInit(sendId){

if ('WebSocket' in window) {

websocket = new WebSocket("ws:localhost:10086/websocket/" + sendId);

} else {

alert("浏览器不支持");

}

websocket.onopen = function () {

addMessage("webscoket已经连接成功");

};

websocket.onclose = function () {

addMessage("webscoket连接失败");

};

websocket.onmessage = function (event) {

alert("收到消息:"+event.data);

};

websocket.onerror = function () {

addMessage("webscoket连接失败");

};

}

/**

* 发送一条消息

*/

function send(){

http:// websocket.send(value('msg')+"~"+receiveId);

}

/**

* 测试打印调试信息用

* @param msg

*/

function addMessage(msg) {

console.log(msg)

}

testTwo.html

testTwo.js

var websocket = null;

var sendId = 1;

var receiveId = 0;

//---------------------------

/**

* 初始化websocket

* @param id

*/

doInit(sendId)

function doInit(receiveId){

if ('WebSocket' in window) {

websocket = new WebSocket("ws:localhost:10086/websocket/" + sendId);

} else {

alert("浏览器不支持");

}

websocket.onopen = function () {

addMessage("webscoket已经连接成功");

};

websocket.onclose = function () {

addMessage("webscoket连接失败");

};

websocket.onmessage = function (event) {

alert("收到消息:"+event.data);

};

websocket.onerror = function () {

addMessage("webscoket连接失败");

};

}

/**

* 发送一条消息

*/

function send(){

websocket.send(value('msg')+"~"+receiveId);

}

/**

* 测试打印调试信息用

* @param msg

*/

function addMessage(msg) {

console.log(msg)

}

分别用两个浏览器,打开这两个页面进行访问。结果如下

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:IDEA怎么设置maven配置
下一篇:Springboot主程序类注解配置过程图解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~