feat
This commit is contained in:
@@ -22,7 +22,8 @@
|
||||
| 后置通知(After) | 目标方法执行后执行(无论是否抛出异常) |
|
||||
| 返回通知(AfterReturning) | 目标方法正常返回后执行 |
|
||||
| 异常通知(AfterThrowing) | 目标方法抛出异常后执行 |
|
||||
| 环绕通知(Around) | 包裹目标方法执行,可自定义目标方法执行前后的逻辑(功能最强) |
|
||||
| 环绕通知(Around) | 包裹目标方法执行,可自定义目标方法执行前后的逻辑(功能最强) |
|
||||
  [AOP API](https://docs.springjava.cn/spring-framework/reference/core/aop-api.html)
|
||||
|
||||
# 二、原理
|
||||
  Spring AOP 基于动态代理实现,分为两种方式:
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
---
|
||||
|
||||
# 一、IOC
|
||||
  Spring框架的核心是IOC(控制反转)容器,它负责管理应用程序中的对象(称为Bean)的创建、配置和组装。
|
||||
  Spring框架的核心是IOC(控制反转)容器,它负责管理应用程序中的对象(称为Bean)的创建、配置和组装。
|
||||
  [IoC 容器](https://docs.springjava.cn/spring-framework/reference/core/beans.html)
|
||||
|
||||
# 二、Bean
|
||||
## 2.1 定义
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
---
|
||||
|
||||
# 一、基础概念
|
||||
  Spring MVC(Spring Model-View-Controller)是 Spring Framework 中的一部分,它是一个基于 **请求驱动** 的 Web 框架,主要用于构建 Web 应用程序,并且遵循 MVC(模型-视图-控制器) 设计模式。它将 Web 应用的业务逻辑、用户界面和请求处理分离,使得代码更加模块化和可维护。
|
||||
  Spring MVC(Spring Model-View-Controller)是 Spring Framework 中的一部分,它是一个基于 **请求驱动** 的 Web 框架,主要用于构建 Web 应用程序,并且遵循 MVC(模型-视图-控制器) 设计模式。它将 Web 应用的业务逻辑、用户界面和请求处理分离,使得代码更加模块化和可维护。
|
||||
  [Spring Web MVC](https://docs.springjava.cn/spring-framework/reference/web/webmvc.html)
|
||||
|
||||
# 二、具体流程
|
||||

|
||||
|
||||
154
docs/Web/SpringBoot/SpringBoot-WebSocket.md
Normal file
154
docs/Web/SpringBoot/SpringBoot-WebSocket.md
Normal 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("*");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
  WebSocket连接地址:ip:port/ws?userId=123。
|
||||
|
||||
# 四、前端使用
|
||||
  参考:[useWebSocket](../Vue/VueUse.md)
|
||||
Reference in New Issue
Block a user