This commit is contained in:
2026-06-08 10:20:45 +08:00
parent b3c0452621
commit 9c11e484f3
5 changed files with 162 additions and 4 deletions

View File

@@ -22,8 +22,8 @@ export const routers = [
items: [
{ text: 'Spring IOC简介', link: '/Web/SpringBoot/Spring-IOC' },
{ text: 'Spring AOP简介', link: '/Web/SpringBoot/Spring-AOP' },
{ text: 'SpringBoot启动流程', link: '/Web/SpringBoot/SpringBoot-Start-Process' },
{ text: 'Spring MVC简介', link: '/Web/SpringBoot/Spring-MVC' },
{ text: 'SpringBoot启动流程', link: '/Web/SpringBoot/SpringBoot-Start-Process' },
{ text: 'SpringBoot Starter原理', link: '/Web/SpringBoot/SpringBoot-Starter' },
{ text: 'SpringBoot Bean简介', link: '/Web/SpringBoot/SpringBoot-Bean' },
{ text: 'SpringBoot注解', link: '/Web/SpringBoot/SpringBoot-Annotation' },
@@ -31,6 +31,7 @@ export const routers = [
{ text: 'SpringBoot技巧', link: '/Web/SpringBoot/SpringBoot-Skills' },
{ text: 'SpringBoot RestClient简介', link: '/Web/SpringBoot/SpringBoot-RestClient' },
{ text: 'SpringBoot Redis简介和使用', link: '/Web/SpringBoot/SpringBoot-Redis' },
{ text: 'SpringBoot WebSocket使用', link: '/Web/SpringBoot/SpringBoot-WebSocket' },
{ text: 'SpringBoot 线程与事件', link: '/Web/SpringBoot/SpringBoot-Thread' }
]
},

View File

@@ -23,6 +23,7 @@
| 返回通知AfterReturning | 目标方法正常返回后执行 |
| 异常通知AfterThrowing | 目标方法抛出异常后执行 |
| 环绕通知Around | 包裹目标方法执行,可自定义目标方法执行前后的逻辑(功能最强) |
  [AOP API](https://docs.springjava.cn/spring-framework/reference/core/aop-api.html)
# 二、原理
  Spring AOP 基于动态代理实现,分为两种方式:

View File

@@ -5,6 +5,7 @@
# 一、IOC
  Spring框架的核心是IOC控制反转容器它负责管理应用程序中的对象称为Bean的创建、配置和组装。
  [IoC 容器](https://docs.springjava.cn/spring-framework/reference/core/beans.html)
# 二、Bean
## 2.1 定义

View File

@@ -5,6 +5,7 @@
# 一、基础概念
  Spring MVCSpring Model-View-Controller是 Spring Framework 中的一部分,它是一个基于 **请求驱动** 的 Web 框架,主要用于构建 Web 应用程序,并且遵循 MVC模型-视图-控制器) 设计模式。它将 Web 应用的业务逻辑、用户界面和请求处理分离,使得代码更加模块化和可维护。
  [Spring Web MVC](https://docs.springjava.cn/spring-framework/reference/web/webmvc.html)
# 二、具体流程
![暂无图片](https://cxx0822.iepose.cn/rustfs/blog/04fb16a3e32f247bbf0bb7e176de8444.png '具体流程.png')

View File

@@ -0,0 +1,154 @@
---
title: SpringBoot WebSocket使用
date: 2026-06-08
---
# 一、简介
  [WebSocket API](https://docs.springjava.cn/spring-framework/reference/web/websocket/server.html)
# 二、安装
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
```
# 三、使用
## 3.1 定义WebSocketHandler
```java
@Component
public class GenericWebSocketHandler extends TextWebSocketHandler {
private static final Map<String, WebSocketSession> SESSION_MAP =
new ConcurrentHashMap<>();
@Override
public void afterConnectionEstablished(WebSocketSession session) {
String userId = getUserId(session);
SESSION_MAP.put(userId, session);
log("用户连接成功:" + userId);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
String userId = getUserId(session);
SESSION_MAP.remove(userId);
log("用户断开连接:" + userId);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
String payload = message.getPayload();
// 心跳处理
if ("PING".equalsIgnoreCase(payload)) {
session.sendMessage(new TextMessage("PONG"));
return;
}
// 普通消息(可按 JSON 协议扩展)
log("收到消息:" + payload);
session.sendMessage(new TextMessage("服务端已收到:" + payload));
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
log("传输异常:" + exception.getMessage());
}
/** 从 session 中获取用户标识(握手阶段放入) */
private String getUserId(WebSocketSession session) {
return (String) session.getAttributes().getOrDefault("userId", session.getId());
}
/** 单发 */
public void sendToUser(String userId, String msg) throws IOException {
WebSocketSession session = SESSION_MAP.get(userId);
if (session != null && session.isOpen()) {
session.sendMessage(new TextMessage(msg));
}
}
/** 广播 */
public void broadcast(String msg) throws IOException {
for (WebSocketSession session : SESSION_MAP.values()) {
if (session.isOpen()) {
session.sendMessage(new TextMessage(msg));
}
}
}
/** 在线人数 */
public int onlineCount() {
return SESSION_MAP.size();
}
}
```
## 3.2 定义HandshakeInterceptor
```java
@Component
public class GenericHandshakeInterceptor implements HandshakeInterceptor {
/**
* 握手前执行
*/
@Override
public boolean beforeHandshake(
ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler wsHandler,
Map<String, Object> attributes) {
// 从请求中URL中获取id
// 例如ws://localhost:8080/ws?userId=123多个参数用&连接
String userId = servletRequest.getServletRequest().getParameter("userId");
if (userId == null) {
// 返回 false → 握手失败 → 连接被拒绝
return false;
}
// 放入 attributes 中,方便下次获取
attributes.put("userId", userId);
return true;
}
/**
* 握手完成后执行(一般不用写)
*/
@Override
public void afterHandshake(
ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler wsHandler,
Exception exception) {
}
}
```
## 3.3 配置WebSocketConfigurer
```java
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Resource
private GenericWebSocketHandler genericWebSocketHandler;
@Resource
private GenericHandshakeInterceptor genericHandshakeInterceptor;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(genericWebSocketHandler, "/ws")
.addInterceptors(genericHandshakeInterceptor)
.setAllowedOrigins("*");
}
}
```
&emsp;&emsp;WebSocket连接地址ip:port/ws?userId=123。
# 四、前端使用
&emsp;&emsp;参考:[useWebSocket](../Vue/VueUse.md)