# Spring Boot 集成 WebSocket
## Spring封装
### 引入依赖
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
```
### 自定义处理器
>处理器作用类似于`@RequestMapping`注解,用于处理某一个路径的`WebSocket`连接,自定义处理器需要实现`WebSocketHandler`接口。
#### WebSocket操作类
```java
public interface WebSocket {
/**
* 会话开始回调
*
* @param session 会话
*/
void handleOpen(WebSocketSession session);
/**
* 会话结束回调
*
* @param session 会话
*/
void handleClose(WebSocketSession session);
/**
* 处理消息
*
* @param session 会话
* @param message 接收的消息
*/
void handleMessage(WebSocketSession session, String message);
/**
* 发送消息
*
* @param session 当前会话
* @param message 要发送的消息
* @throws IOException 发送io异常
*/
void sendMessage(WebSocketSession session, String message) throws IOException;
/**
* 发送消息
*
* @param userId 用户id
* @param message 要发送的消息
* @throws IOException 发送io异常
*/
void sendMessage(String userId, TextMessage message) throws IOException;
/**
* 发送消息
*
* @param userId 用户id
* @param message 要发送的消息
* @throws IOException 发送io异常
*/
void sendMessage(String userId, String message) throws IOException;
/**
* 发送消息
*
* @param session 当前会话
* @param message 要发送的消息
* @throws IOException 发送io异常
*/
void sendMessage(WebSocketSession session, TextMessage message) throws IOException;
/**
* 广播
*
* @param message 字符串消息
* @throws IOException 异常
*/
void broadCast(String message) throws IOException;
/**
* 广播
*
* @param message 文本消息
* @throws IOException 异常
*/
void broadCast(TextMessage message) throws IOException;
/**
* 处理会话异常
*
* @param session 会话
* @param error 异常
*/
void handleError(WebSocketSession session, Throwable error);
/**
* 获得所有的 websocket 会话
*
* @return 所有 websocket 会话
*/
Set<WebSocketSession> getSessions();
/**
* 得到当前连接数
*
* @return 连接数
*/
int getConnectionCount();
}
```
#### WebSocket操作实现类
```java
@Slf4j
public class WebSocketImpl implements WebSocket {
/**
* 在线连接数(线程安全)
*/
private final AtomicInteger connectionCount = new AtomicInteger(0);
/**
* 线程安全的无序集合(存储会话)
*/
private final CopyOnWriteArraySet<WebSocketSession> sessions = new CopyOnWriteArraySet<>();
@Override
public void handleOpen(WebSocketSession session) {
sessions.add(session);
int count = connectionCount.incrementAndGet();
log.info("a new connection opened,current online count:{}", count);
}
@Override
public void handleClose(WebSocketSession session) {
sessions.remove(session);
int count = connectionCount.decrementAndGet();
log.info("a new connection closed,current online count:{}", count);
}
@Override
public void handleMessage(WebSocketSession session, String message) {
// 只处理前端传来的文本消息,并且直接丢弃了客户端传来的消息
log.info("received a message:{}", message);
}
@Override
public void sendMessage(WebSocketSession session, String message) throws IOException {
this.sendMessage(session, new TextMessage(message));
}
@Override
public void sendMessage(String userId, TextMessage message) throws IOException {
Optional<WebSocketSession> userSession = sessions.stream().filter(session -> {
if (!session.isOpen()) {
return false;
}
Map<String, Object> attributes = session.getAttributes();
if (!attributes.containsKey("uid") {
return false;
}
String uid = (String) attributes.get("uid");
return uid.equals(userId);
}).findFirst();
if (userSession.isPresent()) {
userSession.get().sendMessage(message);
}
}
@Override
public void sendMessage(String userId, String message) throws IOException {
this.sendMessage(userId, new TextMessage(message));
}
@Override
public void sendMessage(WebSocketSession session, TextMessage message) throws IOException {
session.sendMessage(message);
}
@Override
public void broadCast(String message) throws IOException {
for (WebSocketSession session : sessions) {
if (!session.isOpen()) {
continue;
}
this.sendMessage(session, message);
}
}
@Override
public void broadCast(TextMessage message) throws IOException {
for (WebSocketSession session : sessions) {
if (!session.isOpen()) {
continue;
}
session.sendMessage(message);
}
}
@Override
public void handleError(WebSocketSession session, Throwable error) {
log.error("websocket error:{},session id:{}", error.getMessage(), session.getId());
log.error("", error);
}
@Override
public Set<WebSocketSession> getSessions() {
return sessions;
}
@Override
public int getConnectionCount() {
return connectionCount.get();
}
}
```
#### 自定义WebSocket处理器
```java
public class DefaultWebSocketHandler implements WebSocketHandler {
@Autowired
private WebSocket webSocket;
/**
* 建立连接
*
* @param session Session
*/
@Override
public void afterConnectionEstablished(@NonNull WebSocketSession session) {
webSocket.handleOpen(session);
}
/**
* 接收消息
*
* @param session Session
* @param message 消息
*/
@Override
public void handleMessage(@NonNull WebSocketSession session, @NonNull WebSocketMessage<?> message) {
if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
webSocket.handleMessage(session, textMessage.getPayload());
}
}
/**
* 发生错误
*
* @param session Session
* @param exception 异常
*/
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
webSocket.handleError(session, exception);
}
/**
* 关闭连接
*
* @param session Session
* @param closeStatus 关闭状态
*/
@Override
public void afterConnectionClosed(@NonNull WebSocketSession session, @NonNull CloseStatus closeStatus) {
webSocket.handleClose(session);
}
/**
* 是否支持发送部分消息
*
* @return false
*/
@Override
public boolean supportsPartialMessages() {
return false;
}
}
```
### 自定义拦截器
>自定义处理器需要实现`HandshakeInterceptor`接口
```java
public class WebSocketInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(@NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response, @NonNull WebSocketHandler wsHandler, @NonNull Map<String, Object> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) request;
// 模拟用户(通常利用JWT令牌解析用户信息)
String userId =
人人都在发奋
- 粉丝: 6348
- 资源: 2
最新资源
- labview电源测试系统简易型labview电源测试系统,提供源程序,可参考学习制作简约测试系统 这是一个简单的LabVIEW电源测试系统,它提供了源代码,供学习和参考,以制作一个简约的测试系统
- DXF解析成运动控制指令DEMO源代码,运动控制软件必备模块 支持比例缩放 支持按图层解析,各图层可按加工速度、加工参数等分开控制,各图层可选择加工或不加工 支持点、直线、圆、圆弧、多段线解析 暂
- SAP Note 2825007 SAP S/4HANA中BP跨销售区域扩展时CMD-API-100错误消息解决方案
- 智能电网中多时段多公司需求响应管理的博弈理论框架 利用博弈论建立了一个考虑公司和消费者之间相互作用的多时期多公司需求响应框架 在Stackelberg博弈中建立了相互作用的模型,公司设定价格,而消费
- 卫星俯视物体检测24-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar
- SAP Note 2483520 - BP-CVI-Values not preassigned during creation of additional sales area
- Google Earth Engine-基于MODIS NDVI数据的时序影像动态图(gif)制作
- 电网风险、风险评估、风光不确定性 考虑蒙特卡洛考虑风光不确定性的配电网运行风险 评估 软件:Matlab+matpower 介绍:由于风电光伏出力的不确定性,造成配电网运行风险,运用蒙特卡洛概率潮流计
- 卫星俯视物体检测3-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar
- 自编游戏贪吃蛇有源码有程序
- 销售数据源,用于tab制作爬取等工作
- 全新uniapp小说漫画APP小说源码会员阅读月票功能.zip
- 卫星俯视物体检测4-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord、VOC数据集合集.rar
- 全新版本码支付个人免签支付系统源码 ThinkPHP框架开发 全开源 亲测.zip
- jdk-8u431-windows-x64
- 自编游戏俄罗斯方块有源码有程序
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
评论10