From aa0603efff8ff0209f68a26ad7788f9e4617abc6 Mon Sep 17 00:00:00 2001
From: Cxx0822 <1556464090@qq.com>
Date: Sat, 29 Nov 2025 21:49:12 +0800
Subject: [PATCH] =?UTF-8?q?feat:=E6=9B=B4=E6=96=B0=E5=8D=9A=E5=AE=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/.vitepress/config.mts | 15 ++
docs/.vitepress/theme/index.ts | 19 ++-
docs/.vitepress/theme/style.css | 16 +-
docs/.vitepress/theme/style/var.css | 13 ++
docs/.vitepress/theme/style/vp-code.css | 40 +++++
docs/FastAPI/OAuth2.md | 165 ++++++++++++++++++++
docs/FastAPI/index.md | 8 +
docs/Flutter/index.md | 6 +
docs/SpringBoot/SpringBoot-Start-Process.md | 17 +-
docs/SpringBoot/SpringBootBean.md | 60 +++----
docs/SpringBoot/SpringIOC.md | 2 +-
docs/Web-Front/index.md | 6 +
docs/index.md | 6 +-
package.json | 1 +
pnpm-lock.yaml | 8 +
15 files changed, 331 insertions(+), 51 deletions(-)
create mode 100644 docs/.vitepress/theme/style/vp-code.css
create mode 100644 docs/FastAPI/OAuth2.md
create mode 100644 docs/FastAPI/index.md
create mode 100644 docs/Flutter/index.md
create mode 100644 docs/Web-Front/index.md
diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index d813247..861febf 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -20,9 +20,12 @@ export default defineConfig({
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: 'Home', link: '/' },
+ { text: 'Web前端', link: '/Web-Front/' },
{ text: 'Web后端', link: '/Web-Backend/' },
{ text: 'DevOps', link: '/DevOps/' },
{ text: 'SpringBoot', link: '/SpringBoot/' },
+ { text: 'FastAPI', link: '/FastAPI/' },
+ { text: 'Flutter', link: '/Flutter/' },
],
sidebar: {
'/Web-Backend/': [
@@ -57,6 +60,14 @@ export default defineConfig({
{ text: 'SpringBoot3原生镜像', link: '/SpringBoot/SpringBoot3-GraalVM' }
]
}
+ ],
+ '/FastAPI/': [
+ {
+ text: 'FastAPI',
+ items: [
+ { text: '基于OAuth2的FastApi安全验证', link: '/FastAPI/OAuth2' }
+ ]
+ }
]
},
@@ -112,4 +123,8 @@ export default defineConfig({
},
lastUpdated: true,
+
+ markdown: {
+ lineNumbers: true
+ },
})
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
index 188d91f..b77c3c3 100644
--- a/docs/.vitepress/theme/index.ts
+++ b/docs/.vitepress/theme/index.ts
@@ -1,12 +1,29 @@
import DefaultTheme from 'vitepress/theme'
import Confetti from "./components/Confetti.vue";
import type { EnhanceAppContext } from 'vitepress'
-
+import { onMounted, watch, nextTick } from 'vue'
+import { useRoute } from 'vitepress'
+import mediumZoom from 'medium-zoom'
import '../theme/style.css'
import './style/var.css'
+import './style/vp-code.css'
export default {
extends: DefaultTheme,
+ setup() {
+ const route = useRoute()
+ const initZoom = () => {
+ // 为所有图片增加缩放功能
+ mediumZoom('.main img', { background: 'var(--vp-c-bg)' })
+ }
+ onMounted(() => {
+ initZoom()
+ })
+ watch(
+ () => route.path,
+ () => nextTick(() => initZoom())
+ )
+ },
enhanceApp({ app }: EnhanceAppContext) {
app.component("Confetti", Confetti);
},
diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css
index 019bd18..39ea8fb 100644
--- a/docs/.vitepress/theme/style.css
+++ b/docs/.vitepress/theme/style.css
@@ -1,19 +1,19 @@
@font-face {
font-family: 'CustomFont';
src: url('./fonts/custom.woff2') format('woff2');
+ font-weight: normal;
+ font-style: normal;
font-display: swap;
}
:root {
--vp-font-family-base: 'CustomFont', -apple-system, BlinkMacSystemFont,
- 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
- --vp-font-family-mono: 'CustomFont', 'Fira Code', 'Consolas', monospace;
+ 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+
+ --vp-font-family-mono: 'CustomFont', Courier, monospace;
}
-:root {
- --vp-c-brand: #10b981;
- --vp-c-brand-light: #34d399;
- --vp-c-brand-lighter: #6ee7b7;
- --vp-c-brand-dark: #059669;
- --vp-c-brand-darker: #047857;
+strong, b {
+ font-weight: bold;
+ font-synthesis: weight;
}
\ No newline at end of file
diff --git a/docs/.vitepress/theme/style/var.css b/docs/.vitepress/theme/style/var.css
index fb24a6d..e12cc4b 100644
--- a/docs/.vitepress/theme/style/var.css
+++ b/docs/.vitepress/theme/style/var.css
@@ -37,3 +37,16 @@
filter: drop-shadow(-2px 4px 6px #0003);
padding: 18px;
}
+
+.medium-zoom-overlay {
+ background-color: var(--vp-c-bg) !important;
+ z-index: 100;
+}
+
+.medium-zoom-overlay ~ img {
+ z-index: 101;
+}
+
+.medium-zoom--opened .medium-zoom-overlay {
+ opacity: 0.9 !important;
+}
\ No newline at end of file
diff --git a/docs/.vitepress/theme/style/vp-code.css b/docs/.vitepress/theme/style/vp-code.css
new file mode 100644
index 0000000..fb7557b
--- /dev/null
+++ b/docs/.vitepress/theme/style/vp-code.css
@@ -0,0 +1,40 @@
+/* 代码块:增加留空边距 增加阴影 */
+.vp-doc div[class*=language-] {
+ box-shadow: 0 10px 15px 0 rgb(0 0 0 / 20%);
+ padding-top: 20px;
+}
+
+/* 代码块:添加macOS风格的小圆点 */
+.vp-doc div[class*=language-]::before {
+ content: "";
+ display: block;
+ position: absolute;
+ top: 12px;
+ left: 12px;
+ width: 12px;
+ height: 12px;
+ background-color: #ff5f56;
+ border-radius: 50%;
+ box-shadow: 20px 0 0 #ffbd2e, 40px 0 0 #27c93f;
+ z-index: 1;
+}
+
+/* 代码块:下移行号 隐藏右侧竖线 */
+.vp-doc .line-numbers-wrapper {
+ padding-top: 40px;
+ border-right: none;
+}
+
+/* 代码块:重建行号右侧竖线 */
+.vp-doc .line-numbers-wrapper::after {
+ content: "";
+ position: absolute;
+ top: 40px;
+ right: 0;
+ border-right: 1px solid var(--vp-code-block-divider-color);
+ height: calc(100% - 60px);
+}
+
+.vp-doc div[class*='language-'].line-numbers-mode {
+ margin-bottom: 20px;
+}
\ No newline at end of file
diff --git a/docs/FastAPI/OAuth2.md b/docs/FastAPI/OAuth2.md
new file mode 100644
index 0000000..b786fd0
--- /dev/null
+++ b/docs/FastAPI/OAuth2.md
@@ -0,0 +1,165 @@
+# 一、基础概念
+## 1.1 OAuth2 Password Bearer 模式
+ 用于**用户名+密码**登录,获取**access_token**。
+
+## 1.2 FastAPI 的 OAuth2PasswordBearer
+ 从请求头**Authorization**中提取Token,Token格式为 **Bearer Token**,必须是这个格式,如果不是则会提示**401 Unauthorized**错误。
+
+# 二、核心流程
+## 2.1 获取Token
+```python
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="session")
+
+@app.post("/session")
+async def login(form_data: OAuth2PasswordRequestForm = Depends()):
+ # 1. 验证用户名和密码
+ # 2. 返回 Token
+ return Token
+```
+
+ 这里的**tokenUrl="session"** 对应的是fastapi中的url路径(@app.post("/session")),用于Swagger文档中的Token认证。
+ 前端必须要以FormData表单的形式传递username和password,且必须是username和password字段。
+```ts
+ const data = new FormData()
+ data.append('username', username)
+ data.append('password', password)
+```
+ 在获取Token前,一般还需要进行验证用户名和密码是否和数据库中的信息一致。
+ 可以采用JWT格式封装TokenValue:
+```python
+def create_token(payload: dict, expires_delta: Optional[timedelta] = None):
+ # 复制一份
+ payload_copy = payload.copy()
+
+ # 加上有效时间
+ if expires_delta:
+ expire = datetime.now() + expires_delta
+ else:
+ expire = datetime.now() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
+ payload_copy.update({"exp": expire})
+
+ # 生成jwt Token
+ return jwt.encode(payload_copy, SECRET_KEY, algorithm=ALGORITHM)
+```
+
+## 2.2 访问接口
+```python
+@router.delete("/{blog_id}", summary="删除博客内容", response_model=bool)
+def delete_blog(blog_id: int, db: Session = Depends(get_db), _ = Depends(verify_token)):
+ return blog_service.delete_blog(db, blog_id)
+```
+ 例如访问这个删除接口,在参数中添加验证token的依赖:
+```python
+async def verify_token(token: str = Depends(oauth2_scheme)):
+ try:
+ # 1. 检验token信息
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
+ # 2. 校验payload信息
+ if not verify_payload(payload):
+ raise get_credentials_exception()
+ # 3. 校验数据库中是否存在 payload中的账户信息
+ sub = get_payload_sub(payload)
+
+ # 4. 存储账户信息
+ context_sub.set(sub)
+ except jwt.exceptions.InvalidTokenError:
+ raise get_credentials_exception()
+```
+ 该依赖又依赖于子依赖oauth2_scheme,通过调用OAuth2PasswordBearer方法从请求头Authorization中获取token值。
+ 校验Token通常包含校验格式是否正确和Token包含的账户信息是否正确。
+
+# 三、参考代码
+```python
+from contextvars import ContextVar
+from datetime import datetime, timedelta
+from typing import Optional
+
+from fastapi import Depends
+from fastapi.security import OAuth2PasswordBearer
+import jwt
+from passlib.context import CryptContext
+
+from middleware.exceptions import get_credentials_exception
+
+# 密钥和算法配置
+SECRET_KEY = "sjdi@!#3ksj2780se1283"
+ALGORITHM = "HS256"
+ACCESS_TOKEN_EXPIRE_MINUTES = 30
+
+# 密码哈希上下文
+pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
+
+# OAuth2 方案
+# 设置默认登录接口
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="session")
+
+# 请求上下文
+context_sub: ContextVar[str] = ContextVar('sub')
+
+
+# 获取数据库 加密密码
+def get_password_hash(password: str):
+ return pwd_context.hash(password)
+
+
+# 验证数据库密码
+def verify_password(plain_password: str, hashed_password: str):
+ return pwd_context.verify(plain_password, hashed_password)
+
+
+# 生成payload
+def create_payload(sub: str) -> dict:
+ return {
+ "sub": sub
+ }
+
+
+# 验证payload
+def verify_payload(payload: dict) -> bool:
+ return "sub" in payload
+
+
+# 从payload中获取用户
+def get_payload_sub(payload: dict) -> str:
+ return payload["sub"]
+
+
+# 创建token
+def create_token(payload: dict, expires_delta: Optional[timedelta] = None):
+ # 复制一份
+ payload_copy = payload.copy()
+
+ # 加上有效时间
+ if expires_delta:
+ expire = datetime.now() + expires_delta
+ else:
+ expire = datetime.now() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
+ payload_copy.update({"exp": expire})
+
+ # 生成jwt Token
+ return jwt.encode(payload_copy, SECRET_KEY, algorithm=ALGORITHM)
+
+
+# 验证token
+async def verify_token(token: str = Depends(oauth2_scheme)):
+ try:
+ # 1. 检验token信息
+ payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
+ # 2. 校验payload信息
+ if not verify_payload(payload):
+ raise get_credentials_exception()
+ # 3. 校验数据库中是否存在 payload中的账户信息
+ sub = get_payload_sub(payload)
+
+ # 4. 存储账户信息
+ context_sub.set(sub)
+ except jwt.exceptions.InvalidTokenError:
+ raise get_credentials_exception()
+```
+
+# 四、注意事项
+1. 如果整个路由模块都需要Token验证,可以在APIRouter中添加依赖:
+
+```python
+ protected_router = APIRouter(dependencies=[Depends(verify_token)])
+```
\ No newline at end of file
diff --git a/docs/FastAPI/index.md b/docs/FastAPI/index.md
new file mode 100644
index 0000000..dced5f4
--- /dev/null
+++ b/docs/FastAPI/index.md
@@ -0,0 +1,8 @@
+---
+layout: doc
+title: FastAPI
+---
+
+# 内容导航
+
+- [基于OAuth2的FastApi安全验证](/FastAPI/OAuth2)
diff --git a/docs/Flutter/index.md b/docs/Flutter/index.md
new file mode 100644
index 0000000..1ce6e3a
--- /dev/null
+++ b/docs/Flutter/index.md
@@ -0,0 +1,6 @@
+---
+layout: doc
+title: Flutter
+---
+
+# 内容导航
diff --git a/docs/SpringBoot/SpringBoot-Start-Process.md b/docs/SpringBoot/SpringBoot-Start-Process.md
index 056048f..638b3fa 100644
--- a/docs/SpringBoot/SpringBoot-Start-Process.md
+++ b/docs/SpringBoot/SpringBoot-Start-Process.md
@@ -21,7 +21,7 @@
3. BeanFactoryPostProcessor(Bean工厂后处理器)
4. AutoConfigurationImportSelector(自动配置选择器)
- Spring Boot使用SpringFactoriesLoader机制从类路径下的**META-INF/spring.factories**文件中加载各种扩展组件。**这种机制是Spring Boot自动配置的核心基础,它允许框架和开发者通过标准的配置文件来注册和发现各种扩展实现。**
+ Spring Boot使用SpringFactoriesLoader机制从类路径下的**META-INF/spring.factories**文件中加载各种扩展组件。**这种机制是Spring Boot自动配置的核心基础,它允许框架和开发者通过标准的配置文件来注册和发现各种扩展实现。**
配置文件中定义了多种类型的组件,包括**应用上下文初始化器、应用事件监听器、Bean工厂后处理器**等。这些组件将在后续的启动过程中按照特定的顺序被执行,共同完成应用的初始化工作。
**🔹 步骤1.3 - 推断Web应用类型**
@@ -34,7 +34,7 @@
🅱️ REACTIVE:响应式Web应用
©️ NONE:非Web应用
- 应用类型推断是Spring Boot自动配置的重要环节。系统会根据项目的依赖情况自动判断应用类型,这直接影响后续创建的应用上下文类型和内嵌服务器的选择。
+ 应用类型推断是Spring Boot自动配置的重要环节。系统会根据项目的依赖情况自动判断应用类型,这直接影响后续创建的应用上下文类型和内嵌服务器的选择。
**推断过程主要通过检查类路径中是否存在特定的类来完成。例如,如果存在Servlet相关的类,就推断为Web应用;如果存在WebFlux相关的类,就推断为响应式Web应用。** 这种基于类路径的自动推断机制使得开发者无需手动配置应用类型,大大简化了配置工作。
## 2.2 环境准备与配置加载
@@ -51,7 +51,7 @@ ConfigurableEnvironment(可配置环境)
└── ConversionService(类型转换服务)
```
- 环境对象是Spring Boot应用运行时的配置中心,它负责管理所有的配置属性和运行环境信息。根据应用类型的不同,Spring Boot会创建相应的环境实例。
+ 环境对象是Spring Boot应用运行时的配置中心,它负责管理所有的配置属性和运行环境信息。根据应用类型的不同,Spring Boot会创建相应的环境实例。
环境对象采用分层设计,提供了统一的属性访问接口,同时支持多种属性源的动态管理。环境对象还负责管理激活的配置文件(Profile),支持基于不同环境的配置隔离和切换。
**🔹 步骤2.2 - 配置属性源加载**
@@ -77,16 +77,17 @@ ConfigurableEnvironment(可配置环境)
3. 合并不同profile的配置项
4. 处理配置覆盖和冲突解决
- Profile机制是Spring框架提供的环境隔离解决方案,它允许开发者为不同的运行环境定义不同的配置。Spring Boot在启动时会根据激活的Profile来加载相应的配置,并处理配置之间的覆盖关系。
+ Profile机制是Spring框架提供的环境隔离解决方案,它允许开发者为不同的运行环境定义不同的配置。Spring Boot在启动时会根据激活的Profile来加载相应的配置,并处理配置之间的覆盖关系。
Profile的激活可以通过多种方式实现,包括命令行参数、系统属性、配置文件等。系统支持同时激活多个Profile,并提供了灵活的配置合并策略来处理可能出现的配置冲突。
**🔹 步骤2.4 - 配置属性绑定**
1. 属性值解析:从各种属性源中获取属性值
2. 类型转换:将字符串值转换为目标类型
3. 数据验证:基于JSR-303进行数据校验
-4. 对象绑定:将属性值设置到@ConfigurationProperties类
- 配置属性绑定是将外部配置值注入到Java对象中的过程。Spring Boot提供了强大的属性绑定功能,支持宽松的绑定规则、类型转换、数据验证等特性。
- 绑定过程首先会从环境对象中获取属性值,然后进行类型转换,将字符串类型的配置值转换为目标属性类型。如果配置了验证规则,还会执行数据验证,确保配置值的正确性。最后,将验证通过的属性值设置到目标对象中。
+4. 对象绑定:将属性值设置到@ConfigurationProperties类
+
+ 配置属性绑定是将外部配置值注入到Java对象中的过程。Spring Boot提供了强大的属性绑定功能,支持宽松的绑定规则、类型转换、数据验证等特性。
+ 绑定过程首先会从环境对象中获取属性值,然后进行类型转换,将字符串类型的配置值转换为目标属性类型。如果配置了验证规则,还会执行数据验证,确保配置值的正确性。最后,将验证通过的属性值设置到目标对象中。
## 2.3 应用上下文创建与初始化
**🔹 步骤3.1 - 创建应用上下文实例**
@@ -122,7 +123,7 @@ GenericApplicationContext/AnnotationConfigApplicationContext
3. 🔧 添加特殊的后处理器
4. 🔧 配置环境变量覆盖
- 应用上下文初始化器是Spring Boot提供的重要扩展点,允许开发者**在上下文正式刷新之前执行自定义的初始化逻辑。** **初始化器可以通过spring.factories文件注册,也可以通过SpringApplication的addInitializers方法添加。**
+ 应用上下文初始化器是Spring Boot提供的重要扩展点,允许开发者**在上下文正式刷新之前执行自定义的初始化逻辑。** **初始化器可以通过spring.factories文件注册,也可以通过SpringApplication的addInitializers方法添加。**
**初始化器的主要作用包括注册自定义的Bean定义、配置上下文特定的属性、添加特殊的后处理器等。** 通过初始化器,开发者可以深度定制应用上下文的行为,满足特殊的业务需求。
**🔹 步骤3.4 - 发布应用上下文事件**
diff --git a/docs/SpringBoot/SpringBootBean.md b/docs/SpringBoot/SpringBootBean.md
index 5df5b27..0723b74 100644
--- a/docs/SpringBoot/SpringBootBean.md
+++ b/docs/SpringBoot/SpringBootBean.md
@@ -1,60 +1,60 @@
-## 一、Bean概念
-### 1.1 定义
+# 一、Bean概念
+## 1.1 定义
Spring bean是Spring框架在运行时管理的对象,Bean是一个由Spring IoC容器实例化、组装和管理的对象。
一个 Bean 可以是任何普通的 Java 对象,例如 POJO、Service、Respository、Controller 等等。将一个类声明为 Bean 的方式可以是在类级别上使用 `@Component` 注解或其派生注解(`@Service`、`@Repository`、`@Controller`等),也可以是通过配置文件进行显式的声明。
-### 1.2 实例化
+## 1.2 实例化
Spring 容器负责实例化 Bean。当应用程序启动时,Spring 容器会根据配置信息或注解扫描的结果,找到并实例化所有被标记为 Bean 的类,并将它们加入容器中。实例化的过程由 Spring 的 IoC 容器负责。
-### 1.3 管理
+## 1.3 管理
一旦 Bean 被实例化,Spring 容器将负责管理 Bean 的生命周期和依赖关系。它会根据配置文件或注解的信息,自动解决 Bean 之间的依赖关系,确保在需要的时候正确的注入依赖。Spring 容器还会负责销毁不再需要的 Bean。
-### 1.4 依赖注入
+## 1.4 依赖注入
依赖注入是 Spring 框架的一个重要特性,它允许通过自动或显式配置的方式将 Bean 的依赖项注入到其它 Bean 中。依赖注入可以通过构造函数注入、Setter 方法注入或字段注入的方式实现,其中最常见的是使用 `@Autowired`注解进行注入。
-### 1.5 作用域
+## 1.5 作用域
Spring 框架提供了多种作用域(scope)来管理 Bean 的生命周期。常见的作用域包括单例(Singleton)、原型(Prototype)、会话(Session)、请求(Request)等。默认情况下,Bean 是单例的,即每个容器中只存在一个实例。但可以根据需要配置其它作用域。
-### 1.6 自动装配
+## 1.6 自动装配
Spring Boot 支持自动装配(Auto - wiring),它能够根据类型或名称自动解析和注入依赖关系。通过在需要注入的字段、构造函数或 Setter 方法上使用 `@Autowired` 注解,Spring 容器会自动查找并注入对应的 Bean。
-## 二、Bean生命周期
+# 二、Bean生命周期

-### 2.1 实例化
+## 2.1 实例化
指创建对象的过程,也就是说,当 Spring 容器启动时,它会扫描所有的配置文件,读取 Bean 定义,然后根据定义创建 Bean 对象的实例。这个过程中,Spring 容器会使用反射机制来调用 Bean 的构造函数来实例化对象。
-### 2.2 属性赋值
+## 2.2 属性赋值
对 Bean 的实例化对象进行属性填充;
-### 2.3 初始化
+## 2.3 初始化
指 Bean 对象被创建后,Spring 容器会根据配置文件中的定义来对其进行一系列的属性设置、依赖注入等操作,使其可以正常运行。这个过程中,Spring 容器会调用 Bean 的一些特定方法,如 set 方法、init-method 方法等来完成对象的初始化。
-### 2.4 销毁
+## 2.4 销毁
执行一些预定义的销毁方法;
-## 三、Bean注解——@Component
-### 基本概念
+# 三、Bean注解——@Component
+## 基本概念
@Component 是 Spring 框架中的一个注解,用于将类标记为 Spring 管理的组件。当一个类被 @Component 注解修饰时,Spring 会在启动时自动扫描并将该类实例化为 Bean,放入应用程序的上下文(ApplicationContext)中,以便在其他地方可以通过依赖注入使用。
-### 主要作用
+## 主要作用
1. 组件扫描:Spring 通过组件扫描机制自动发现并注册被 @Component 注解的类。
2. Bean 定义:被注解的类会被视为 Spring Bean,由 Spring 容器管理其生命周期。
3. 依赖注入:其他组件可以通过注解(如 @Autowired)注入这些 Bean。
-### 其他衍生注解
-| **注解** | **所属层** | **继承关系** | **适用场景** |
-|------------------|--------------------|-------------------|----------------------------------------------------------------------------|
-| **@Component** | 通用组件 | 基础注解 | 不适合特定层的组件(如工具类、配置类) |
-| **@Repository** | 数据访问层 (DAO) | 继承 @Component | 数据库操作类、ORM 映射类(如 JPA Repository) |
-| **@Service** | 服务层 (Service) | 继承 @Component | 业务逻辑处理(如订单处理、用户认证) |
-| **@Controller** | 控制层 (MVC/Web) | 继承 @Component | 处理 HTTP 请求的控制器(如 REST API、Web 页面控制器) |
-| **@RestController** | 控制层 (REST API) | 继承 @Controller | RESTful API 接口开发 |
+## 其他衍生注解
+| 注解 | 所属层 | 继承关系 | 适用场景 |
+|------------|------------|-------------|----------|
+| @Component | 通用组件 | 基础注解 | 不适合特定层的组件(如工具类、配置类) |
+| @Repository | 数据访问层 (DAO) | 继承 @Component | 数据库操作类、ORM 映射类(如 JPA Repository) |
+| @Service | 服务层 (Service) | 继承 @Component | 业务逻辑处理(如订单处理、用户认证) |
+| @Controller | 控制层 (MVC/Web) | 继承 @Component | 处理 HTTP 请求的控制器(如 REST API、Web 页面控制器) |
+| @RestController | 控制层 (REST API) | 继承 @Controller | RESTful API 接口开发 |
-| **注解** | **功能描述** | **Spring 自动处理特性** |
-|------------------|-----------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------|
-| **@Component** | 标记类为 Spring Bean,通过组件扫描自动注册。
无特定语义,是其他组件注解的基础。 | - Bean 生命周期管理
- 依赖注入支持 |
-| **@Repository** | 标记数据访问组件(如数据库操作类),
自动处理数据访问异常。 | - 异常转换
- DAO 组件扫描 |
-| **@Service** | 标记业务逻辑组件,负责处理业务流程、事务管理等。
提供语义化,明确该类在架构中的角色。 | - 与 @Transactional 注解默认集成
- IDE 识别为服务层组件 |
-| **@Controller** | 标记 Web 控制器,处理 HTTP 请求。
与 Spring MVC 框架紧密集成。 | - 请求映射自动注册
- 支持 @RequestMapping、@GetMapping 等注解
- 视图解析(返回视图名称或 JSON) |
-| **@RestController** | @Controller + @ResponseBody 的组合,专门用于 RESTful API,直接返回 JSON/XML 等数据。 | - 所有方法默认返回 JSON/XML(无需每个方法添加 @ResponseBody) |
\ No newline at end of file
+| 注解 | 功能描述 | Spring 自动处理特性 |
+|------------------|----------------------|-------------------|
+| @Component | 标记类为 Spring Bean,通过组件扫描自动注册。
无特定语义,是其他组件注解的基础。 | - Bean 生命周期管理
- 依赖注入支持 |
+| @Repository | 标记数据访问组件(如数据库操作类),
自动处理数据访问异常。 | - 异常转换
- DAO 组件扫描 |
+| @Service | 标记业务逻辑组件,负责处理业务流程、事务管理等。
提供语义化,明确该类在架构中的角色。 | - 与 @Transactional 注解默认集成
- IDE 识别为服务层组件 |
+| @Controller | 标记 Web 控制器,处理 HTTP 请求。
与 Spring MVC 框架紧密集成。 | - 请求映射自动注册
- 支持 @RequestMapping、@GetMapping 等注解
- 视图解析(返回视图名称或 JSON) |
+| @RestController | @Controller + @ResponseBody 的组合,专门用于 RESTful API,直接返回 JSON/XML 等数据。 | - 所有方法默认返回 JSON/XML(无需每个方法添加 @ResponseBody) |
\ No newline at end of file
diff --git a/docs/SpringBoot/SpringIOC.md b/docs/SpringBoot/SpringIOC.md
index 2b7b6d3..f4680e8 100644
--- a/docs/SpringBoot/SpringIOC.md
+++ b/docs/SpringBoot/SpringIOC.md
@@ -3,7 +3,7 @@
# 二、Bean
## 2.1 定义
- 在Spring中,Bean是指由Spring IOC容器管理的对象实例。这些对象不再由应用程序直接创建,而是由容器负责实例化、配置和组装。
+ 在Spring中,Bean是指由Spring IOC容器管理的对象实例。这些对象不再由应用程序直接创建,而是由容器负责实例化、配置和组装。
例如@Service、@Controller就是特殊的Bean。
## 2.2 特点
diff --git a/docs/Web-Front/index.md b/docs/Web-Front/index.md
new file mode 100644
index 0000000..dad279f
--- /dev/null
+++ b/docs/Web-Front/index.md
@@ -0,0 +1,6 @@
+---
+layout: doc
+title: Web前端
+---
+
+# 内容导航
diff --git a/docs/index.md b/docs/index.md
index d67e84a..855f1f8 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -9,15 +9,15 @@ hero:
src: /logo.png
alt: VitePress
actions:
+ - theme: brand
+ text: Web前端
+ link: /Web-Front/
- theme: brand
text: Web后端
link: /Web-Backend/
- theme: brand
text: DevOps
link: /DevOps/
- - theme: brand
- text: SpringBoot
- link: /SpringBoot/
features:
- title: 🚀 技术分享
diff --git a/package.json b/package.json
index 0046b3f..8319ec7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,7 @@
{
"devDependencies": {
"canvas-confetti": "^1.9.4",
+ "medium-zoom": "^1.1.0",
"vitepress": "1.6.4"
},
"scripts": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 543733a..ab3ba0e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,6 +11,9 @@ importers:
canvas-confetti:
specifier: ^1.9.4
version: 1.9.4
+ medium-zoom:
+ specifier: ^1.1.0
+ version: 1.1.0
vitepress:
specifier: 1.6.4
version: 1.6.4(@algolia/client-search@5.45.0)(@types/node@24.10.1)(postcss@8.5.6)(search-insights@2.17.3)
@@ -634,6 +637,9 @@ packages:
mdast-util-to-hast@13.2.1:
resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
+ medium-zoom@1.1.0:
+ resolution: {integrity: sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ==}
+
micromark-util-character@2.1.1:
resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
@@ -1394,6 +1400,8 @@ snapshots:
unist-util-visit: 5.0.0
vfile: 6.0.3
+ medium-zoom@1.1.0: {}
+
micromark-util-character@2.1.1:
dependencies:
micromark-util-symbol: 2.0.1