基于注解开发 WebSocket
–注解就是: @OnOpen、 @OnClose 、 @OnMessage 、@OnError这些
★ WebSocket的两种开发方式
▲ Spring Boot为WebSocket提供了两种开发方式:
-
基于spring-boot-starter-websocket.jar开发WebSocket
-
基于Spring WebFlux开发WebSocket
两种方式对比:
springboot API
Socket:套接字。
插座。
在通信的两端分别建立虚拟的Socket(插座),网络协议就会负责在两个Socket之间建立虚拟线路。然后通信的两端即可通过该虚拟线路进行实时的、可靠的通信。
▲ WebSocket 就是在服务器与客户端浏览器之间的建立双向通信的Socket。从而保证服务器与客户端浏览器之间可进行实时的双向通信。
▲ 传统Web应用: 请求 - 响应。 这种模型没办法让服务器主动将数据推送客户端的浏览器。 还有比如SSE(服务器事件机制)
★ 基于Spring Boot自动配置来开发WebSocket
两步:
(1)定义一个WebSocket处理类
该处理类有两种开发方式(历史原因造成):
第一种方式: - 直接使用JDK提供的 WebSocket注解 修饰处理方法,
并使用 @ServerEndpoint 注解修饰该处理类即可。
WebSocket注解就是: @OnOpen、 @OnClose 、 @OnMessage 、@OnError这些
——这种方式下方法签名可以随便写,方法参数也可以自行定义,非常灵活。
官方也推荐尽量使用第一种方式
第二种方式: - 实现WebSocketHandler接口、并实现该接口中定义的各种处理方法。
——Java语法规定,实现接口时,实现的方法必须与接口中定义的方法有相同的方法签名。
——这种方式就不够灵活。
(2)配置或导出WebSocket处理类
如果采用注解方式开发WebSocket处理类,
这一步只需要在 Spring容器 中配置一个ServerEndpointExporter Bean (导出器)即可。
该导出器会负责将容器中所有的@ServerEndpoint注解修饰的处理Bean都导出成WebSocket。
因此无论程序有多少个WebSocket处理Bean,导出器Bean只要配置一个即可。
——非常简单、方便。
如果采用是实现接口的方式开发WebSocket处理类,
这一步就需要使用WebSocketConfigurer来配置WebSocket。
代码演示
创建项目
开发websocket的两步。
注解:@PathParam()
属于 WebSocket 的,用于获取路径上的参数。
发送消息的简单解释:
完整代码:
前端页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> 基于WebSocket的多人聊天 </title>
<script type="text/javascript">
// 定义Web Socket对象
var webSocket = null;
let sendMsg = function()
{
if (webSocket == null || webSocket.readyState != 1)
{
document.getElementById('show').innerHTML
+= "还未连接服务器,请先连接WebSocket服务器<br>";
return;
}
let inputElement = document.getElementById('msg');
// 发送消息
webSocket.send(inputElement.value);
// 清空单行文本框
inputElement.value = "";
}
let connect = function()
{
let name = document.getElementById('name').value.trim();
if (name == null || name == "")
{
document.getElementById('show').innerHTML
+= "用户名不能为空<br>";
return;
}
if (webSocket && webSocket.readyState == 1)
{
webSocket.close();
}
webSocket = new WebSocket("ws://127.0.0.1:8080/websocket/" + name);
webSocket.onopen = function()
{
document.getElementById('show').innerHTML
+= "恭喜您,连接服务器成功!<br>";
document.getElementById('name').value = "";
// 为onmessage事件绑定监听器,接收消息
webSocket.onmessage= function(event)
{
// 接收、并显示消息
document.getElementById('show').innerHTML
+= event.data + "<br>";
}
};
}
</script>
</head>
<body>
<input type="text" size="20" id="name" name="name"/>
<input type="button" value="连接" onclick="connect();"/>
<div style="width:600px;height:240px;
overflow-y:auto;border:1px solid #333;" id="show"></div>
<input type="text" size="80" id="msg" name="msg"/>
<input type="button" value="发送" onclick="sendMsg();"/>
</body>
</html>
MyWebSocketHandler 注解开发各方法
package cn.ljh.app.websocket;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
//基于注解开发 WebSocket --注解就是: @OnOpen、 @OnClose 、 @OnMessage 、@OnError这些
@Component
//这个注解需要指定指定映射地址
@ServerEndpoint("/websocket/{name}")
@Slf4j
public class MyWebSocketHandler
{
//可以用注解来修饰不同的处理方法
//假设是一个聊天室,map 中的key 是每个用户的 Session , value 是用户的name
//创建一个线程安全的map ,用这个map来保存各用户的Session与name之间的对应关系
public final static Map<Session,String> myClients = new ConcurrentHashMap<>();
//当浏览器 与 Websocket 服务器建立连接的时候触发该方法
//这个Session参数代表浏览器 与 WebSocket 服务器所建立连接会话,它用于通信。
//这个 @PathParam() 相当于spring mvc 中的 @PathVariable,
//都是用来获取路径中的参数--获取这个路径"/websocket/{name}" 中的name参数
@OnOpen
public void onOpen(Session session , @PathParam("name") String name)
{
//当用户登录的时候,把信息存进去
myClients.put(session,name);
log.debug("--------- onOpen ----------");
}
//当浏览器与WebSocket服务器 关闭的时候触发该方法
@OnClose
public void onClose(Session session)
{
//当连接关闭的时候,就将该客户端从map中删除
myClients.remove(session);
log.debug("--------- onClose ----------");
}
//当 WebSocket服务器 收到 浏览器 发送过来的消息时触发该方法
@SneakyThrows
@OnMessage
public String onMessage(Session session, String message)
{
//收到消息,把消息广播给每个客户端 keySet()-->将map中的所有key存到set集合中
for (Session client : myClients.keySet())
{
//此处的 client 就代表每个客户端
//向client 发送信息,这个 client 代表了一个浏览器
//getBasicRemote() 表示给客户端发送消息是同步的、阻塞的 , sendText() 发送消息
client.getBasicRemote().sendText(myClients.get(session)+" 说:"+message);
}
log.debug("--------- onMessage ----------"+message);
return null;
}
//但 WebSocket 服务器 与 浏览器通信出现异常时触发该方法
//这个 Throwable 参数就代表了出现的异常
@OnError
public void onError(Session session, Throwable ex)
{
//当连接出现异常的时候,将该客户端从 Map 中栅除
myClients.remove(session);
log.debug("--------- onError ----------");
}
}
MyWebSocketConfig 配置 WebSocket 导出器
package cn.ljh.app.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* author JH
* date 2023/9/7 0007 12:28
*/
@Configuration
public class MyWebSocketConfig
{
/*
*配置 WebSocket 导出器
*
* 该导出器会负责将容器中所有的 @ServerEndpoint 注解修饰的 处理Bean 都导出成 WebSocket。
* 因此无论程序有多少个 WebSocket 处理Bean,导出器Bean 只要配置一个即可。
*/
@Bean
public ServerEndpointExporter serverEndpointExporter()
{
return new ServerEndpointExporter();
}
}
application.yml 配置日志级别
#给这个包设置日志级别为debug
logging:
level:
cn:
ljh:
app:
websocket: debug
测试:
进行websocket连接
文章来源:https://www.toymoban.com/news/detail-700802.html
成功基于注解开发WebSocket 的多人聊天室
文章来源地址https://www.toymoban.com/news/detail-700802.html
到了这里,关于53、springboot对websocket的支持有两种方式-------1、基于注解开发 WebSocket ,简洁实现多人聊天界面的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!