chore: 将doc目录添加到.gitignore
- 添加doc/目录到忽略列表 - 从远程仓库中移除doc目录 - 保留本地doc文档供开发参考
This commit is contained in:
parent
68265e4652
commit
4dab78c027
3
.gitignore
vendored
3
.gitignore
vendored
@ -47,3 +47,6 @@ picture/
|
|||||||
|
|
||||||
### Local Configuration Files ###
|
### Local Configuration Files ###
|
||||||
**/application-local.yml
|
**/application-local.yml
|
||||||
|
|
||||||
|
### Documentation ###
|
||||||
|
doc/
|
||||||
|
|||||||
@ -1,240 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# OSS环境变量快速设置脚本
|
|
||||||
# 用于设置阿里云OSS所需的环境变量
|
|
||||||
|
|
||||||
echo "🔧 OSS环境变量设置工具"
|
|
||||||
echo "=================================="
|
|
||||||
|
|
||||||
# 检测操作系统
|
|
||||||
OS_TYPE=$(uname -s)
|
|
||||||
SHELL_TYPE=$(basename "$SHELL")
|
|
||||||
|
|
||||||
echo "检测到操作系统: $OS_TYPE"
|
|
||||||
echo "检测到Shell: $SHELL_TYPE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 获取当前配置文件中的值(仅用于显示)
|
|
||||||
CURRENT_KEY_ID="LTAI5t982gXi7A72gAa9yugE"
|
|
||||||
CURRENT_KEY_SECRET="Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30"
|
|
||||||
|
|
||||||
echo "📋 配置文件中的当前值:"
|
|
||||||
echo "OSS_ACCESS_KEY_ID: $CURRENT_KEY_ID"
|
|
||||||
echo "OSS_ACCESS_KEY_SECRET: ${CURRENT_KEY_SECRET:0:8}..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 选择设置方式
|
|
||||||
echo "请选择设置方式:"
|
|
||||||
echo "1. 临时设置(当前终端会话有效)"
|
|
||||||
echo "2. 永久设置(添加到Shell配置文件)"
|
|
||||||
echo "3. 创建启动脚本"
|
|
||||||
echo "4. 创建.env文件"
|
|
||||||
echo "5. 显示手动设置命令"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
read -p "请输入选项 (1-5): " choice
|
|
||||||
|
|
||||||
case $choice in
|
|
||||||
1)
|
|
||||||
echo ""
|
|
||||||
echo "🔧 临时设置环境变量..."
|
|
||||||
export OSS_ACCESS_KEY_ID="$CURRENT_KEY_ID"
|
|
||||||
export OSS_ACCESS_KEY_SECRET="$CURRENT_KEY_SECRET"
|
|
||||||
|
|
||||||
echo "✅ 环境变量已设置(当前终端会话有效)"
|
|
||||||
echo ""
|
|
||||||
echo "验证设置:"
|
|
||||||
echo "OSS_ACCESS_KEY_ID: $OSS_ACCESS_KEY_ID"
|
|
||||||
echo "OSS_ACCESS_KEY_SECRET: ${OSS_ACCESS_KEY_SECRET:0:8}..."
|
|
||||||
echo ""
|
|
||||||
echo "⚠️ 注意:这些变量只在当前终端会话中有效"
|
|
||||||
echo " 关闭终端后需要重新设置"
|
|
||||||
;;
|
|
||||||
|
|
||||||
2)
|
|
||||||
echo ""
|
|
||||||
echo "🔧 永久设置环境变量..."
|
|
||||||
|
|
||||||
# 根据Shell类型选择配置文件
|
|
||||||
if [[ "$SHELL_TYPE" == "zsh" ]]; then
|
|
||||||
CONFIG_FILE="$HOME/.zshrc"
|
|
||||||
elif [[ "$SHELL_TYPE" == "bash" ]]; then
|
|
||||||
CONFIG_FILE="$HOME/.bashrc"
|
|
||||||
else
|
|
||||||
CONFIG_FILE="$HOME/.profile"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "将添加到配置文件: $CONFIG_FILE"
|
|
||||||
|
|
||||||
# 检查是否已经存在
|
|
||||||
if grep -q "OSS_ACCESS_KEY_ID" "$CONFIG_FILE"; then
|
|
||||||
echo "⚠️ 配置文件中已存在OSS_ACCESS_KEY_ID,是否覆盖? (y/N)"
|
|
||||||
read -p "" overwrite
|
|
||||||
if [[ "$overwrite" != "y" && "$overwrite" != "Y" ]]; then
|
|
||||||
echo "取消设置"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
# 移除现有配置
|
|
||||||
sed -i.bak '/OSS_ACCESS_KEY_ID/d' "$CONFIG_FILE"
|
|
||||||
sed -i.bak '/OSS_ACCESS_KEY_SECRET/d' "$CONFIG_FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 添加新配置
|
|
||||||
echo "" >> "$CONFIG_FILE"
|
|
||||||
echo "# OSS环境变量 - 由setup-env.sh添加" >> "$CONFIG_FILE"
|
|
||||||
echo "export OSS_ACCESS_KEY_ID=\"$CURRENT_KEY_ID\"" >> "$CONFIG_FILE"
|
|
||||||
echo "export OSS_ACCESS_KEY_SECRET=\"$CURRENT_KEY_SECRET\"" >> "$CONFIG_FILE"
|
|
||||||
|
|
||||||
echo "✅ 环境变量已添加到 $CONFIG_FILE"
|
|
||||||
echo ""
|
|
||||||
echo "请执行以下命令使配置生效:"
|
|
||||||
echo "source $CONFIG_FILE"
|
|
||||||
echo ""
|
|
||||||
echo "或者重新打开终端"
|
|
||||||
;;
|
|
||||||
|
|
||||||
3)
|
|
||||||
echo ""
|
|
||||||
echo "🔧 创建启动脚本..."
|
|
||||||
|
|
||||||
SCRIPT_FILE="start-app-with-oss.sh"
|
|
||||||
|
|
||||||
cat > "$SCRIPT_FILE" << 'EOF'
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# 应用程序启动脚本(包含OSS环境变量)
|
|
||||||
# 自动生成于 $(date)
|
|
||||||
|
|
||||||
echo "🚀 启动应用程序(OSS模式)..."
|
|
||||||
echo "=================================="
|
|
||||||
|
|
||||||
# 设置OSS环境变量
|
|
||||||
export OSS_ACCESS_KEY_ID="LTAI5t982gXi7A72gAa9yugE"
|
|
||||||
export OSS_ACCESS_KEY_SECRET="Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30"
|
|
||||||
|
|
||||||
echo "✅ OSS环境变量已设置"
|
|
||||||
echo "OSS_ACCESS_KEY_ID: $OSS_ACCESS_KEY_ID"
|
|
||||||
echo "OSS_ACCESS_KEY_SECRET: ${OSS_ACCESS_KEY_SECRET:0:8}..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 切换到项目目录
|
|
||||||
PROJECT_DIR="/Users/leocoder/leocoder/develop/templates/coder-common-thin/coder-common-thin-backend"
|
|
||||||
if [ -d "$PROJECT_DIR" ]; then
|
|
||||||
cd "$PROJECT_DIR"
|
|
||||||
echo "📁 切换到项目目录: $PROJECT_DIR"
|
|
||||||
else
|
|
||||||
echo "❌ 项目目录不存在: $PROJECT_DIR"
|
|
||||||
echo "请修改脚本中的PROJECT_DIR变量"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 检查JAR文件是否存在
|
|
||||||
JAR_FILE="coder-common-thin-web/target/coder-common-thin-web-1.0.0.jar"
|
|
||||||
if [ -f "$JAR_FILE" ]; then
|
|
||||||
echo "📦 找到JAR文件: $JAR_FILE"
|
|
||||||
else
|
|
||||||
echo "❌ JAR文件不存在: $JAR_FILE"
|
|
||||||
echo "请先编译项目: mvn clean package -DskipTests"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 启动应用程序
|
|
||||||
echo ""
|
|
||||||
echo "🚀 启动Spring Boot应用程序..."
|
|
||||||
echo "访问地址: http://localhost:18099"
|
|
||||||
echo "API文档: http://localhost:18099/swagger-ui.html"
|
|
||||||
echo ""
|
|
||||||
echo "按 Ctrl+C 停止应用程序"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
java -jar "$JAR_FILE"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x "$SCRIPT_FILE"
|
|
||||||
|
|
||||||
echo "✅ 启动脚本已创建: $SCRIPT_FILE"
|
|
||||||
echo ""
|
|
||||||
echo "使用方法:"
|
|
||||||
echo "./$SCRIPT_FILE"
|
|
||||||
;;
|
|
||||||
|
|
||||||
4)
|
|
||||||
echo ""
|
|
||||||
echo "🔧 创建.env文件..."
|
|
||||||
|
|
||||||
ENV_FILE=".env"
|
|
||||||
|
|
||||||
cat > "$ENV_FILE" << EOF
|
|
||||||
# OSS环境变量配置
|
|
||||||
# 创建时间: $(date)
|
|
||||||
# 注意: 此文件包含敏感信息,不要提交到版本控制
|
|
||||||
|
|
||||||
OSS_ACCESS_KEY_ID=$CURRENT_KEY_ID
|
|
||||||
OSS_ACCESS_KEY_SECRET=$CURRENT_KEY_SECRET
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "✅ .env文件已创建: $ENV_FILE"
|
|
||||||
echo ""
|
|
||||||
echo "使用方法:"
|
|
||||||
echo "1. 使用dotenv工具: dotenv java -jar app.jar"
|
|
||||||
echo "2. 手动加载: source .env && java -jar app.jar"
|
|
||||||
echo "3. 在IDE中配置Environment Variables"
|
|
||||||
echo ""
|
|
||||||
echo "⚠️ 重要提醒:"
|
|
||||||
echo "• 将.env添加到.gitignore文件中"
|
|
||||||
echo "• 不要将.env文件提交到版本控制"
|
|
||||||
|
|
||||||
# 检查并添加到.gitignore
|
|
||||||
if [ -f ".gitignore" ]; then
|
|
||||||
if ! grep -q "\.env" .gitignore; then
|
|
||||||
echo ".env" >> .gitignore
|
|
||||||
echo "✅ .env已添加到.gitignore"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo ".env" > .gitignore
|
|
||||||
echo "✅ 已创建.gitignore并添加.env"
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
5)
|
|
||||||
echo ""
|
|
||||||
echo "📋 手动设置命令:"
|
|
||||||
echo "=================================="
|
|
||||||
echo ""
|
|
||||||
echo "🐧 Linux/macOS (Bash):"
|
|
||||||
echo "export OSS_ACCESS_KEY_ID=\"$CURRENT_KEY_ID\""
|
|
||||||
echo "export OSS_ACCESS_KEY_SECRET=\"$CURRENT_KEY_SECRET\""
|
|
||||||
echo ""
|
|
||||||
echo "🐧 Linux/macOS (Zsh):"
|
|
||||||
echo "export OSS_ACCESS_KEY_ID=\"$CURRENT_KEY_ID\""
|
|
||||||
echo "export OSS_ACCESS_KEY_SECRET=\"$CURRENT_KEY_SECRET\""
|
|
||||||
echo ""
|
|
||||||
echo "🪟 Windows (CMD):"
|
|
||||||
echo "set OSS_ACCESS_KEY_ID=$CURRENT_KEY_ID"
|
|
||||||
echo "set OSS_ACCESS_KEY_SECRET=$CURRENT_KEY_SECRET"
|
|
||||||
echo ""
|
|
||||||
echo "🪟 Windows (PowerShell):"
|
|
||||||
echo "\$env:OSS_ACCESS_KEY_ID=\"$CURRENT_KEY_ID\""
|
|
||||||
echo "\$env:OSS_ACCESS_KEY_SECRET=\"$CURRENT_KEY_SECRET\""
|
|
||||||
echo ""
|
|
||||||
echo "🐳 Docker:"
|
|
||||||
echo "docker run -e OSS_ACCESS_KEY_ID=\"$CURRENT_KEY_ID\" -e OSS_ACCESS_KEY_SECRET=\"$CURRENT_KEY_SECRET\" your-app"
|
|
||||||
echo ""
|
|
||||||
echo "☕ Java启动命令:"
|
|
||||||
echo "OSS_ACCESS_KEY_ID=\"$CURRENT_KEY_ID\" OSS_ACCESS_KEY_SECRET=\"$CURRENT_KEY_SECRET\" java -jar app.jar"
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
echo "❌ 无效选项,请选择1-5"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🧪 验证环境变量设置:"
|
|
||||||
echo "--------------------------------"
|
|
||||||
echo "echo \$OSS_ACCESS_KEY_ID"
|
|
||||||
echo "echo \$OSS_ACCESS_KEY_SECRET"
|
|
||||||
echo ""
|
|
||||||
echo "📖 详细文档: doc/oss/环境变量设置指南.md"
|
|
||||||
echo "🚀 测试脚本: doc/oss/修复后验证测试.sh"
|
|
||||||
@ -1,271 +0,0 @@
|
|||||||
# 环境变量设置指南
|
|
||||||
|
|
||||||
## 📋 需要设置的环境变量
|
|
||||||
|
|
||||||
根据你的配置文件,需要设置以下环境变量:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
OSS_ACCESS_KEY_ID=your_access_key_id
|
|
||||||
OSS_ACCESS_KEY_SECRET=your_access_key_secret
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🖥️ 不同操作系统的设置方法
|
|
||||||
|
|
||||||
### 1. macOS / Linux
|
|
||||||
|
|
||||||
#### 方法1:临时设置(当前终端会话有效)
|
|
||||||
```bash
|
|
||||||
export OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE
|
|
||||||
export OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 方法2:永久设置(添加到配置文件)
|
|
||||||
|
|
||||||
**对于 Bash 用户:**
|
|
||||||
```bash
|
|
||||||
# 编辑 ~/.bashrc 或 ~/.bash_profile
|
|
||||||
echo 'export OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE' >> ~/.bashrc
|
|
||||||
echo 'export OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30' >> ~/.bashrc
|
|
||||||
|
|
||||||
# 重新加载配置
|
|
||||||
source ~/.bashrc
|
|
||||||
```
|
|
||||||
|
|
||||||
**对于 Zsh 用户(macOS 默认):**
|
|
||||||
```bash
|
|
||||||
# 编辑 ~/.zshrc
|
|
||||||
echo 'export OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE' >> ~/.zshrc
|
|
||||||
echo 'export OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30' >> ~/.zshrc
|
|
||||||
|
|
||||||
# 重新加载配置
|
|
||||||
source ~/.zshrc
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Windows
|
|
||||||
|
|
||||||
#### 方法1:命令行临时设置
|
|
||||||
|
|
||||||
**CMD:**
|
|
||||||
```cmd
|
|
||||||
set OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE
|
|
||||||
set OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30
|
|
||||||
```
|
|
||||||
|
|
||||||
**PowerShell:**
|
|
||||||
```powershell
|
|
||||||
$env:OSS_ACCESS_KEY_ID="LTAI5t982gXi7A72gAa9yugE"
|
|
||||||
$env:OSS_ACCESS_KEY_SECRET="Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 方法2:系统环境变量设置
|
|
||||||
|
|
||||||
1. 右击"此电脑" → "属性"
|
|
||||||
2. 点击"高级系统设置"
|
|
||||||
3. 点击"环境变量"
|
|
||||||
4. 在"系统变量"中点击"新建"
|
|
||||||
5. 变量名:`OSS_ACCESS_KEY_ID`,变量值:`LTAI5t982gXi7A72gAa9yugE`
|
|
||||||
6. 重复步骤4-5,设置 `OSS_ACCESS_KEY_SECRET`
|
|
||||||
|
|
||||||
## 🚀 启动应用程序的方法
|
|
||||||
|
|
||||||
### 1. 直接在终端启动
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 设置环境变量
|
|
||||||
export OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE
|
|
||||||
export OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30
|
|
||||||
|
|
||||||
# 启动应用程序
|
|
||||||
cd /Users/leocoder/leocoder/develop/templates/coder-common-thin/coder-common-thin-backend
|
|
||||||
java -jar coder-common-thin-web/target/coder-common-thin-web-1.0.0.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 一行命令启动
|
|
||||||
|
|
||||||
```bash
|
|
||||||
OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30 java -jar coder-common-thin-web/target/coder-common-thin-web-1.0.0.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 使用启动脚本
|
|
||||||
|
|
||||||
创建一个启动脚本:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# 文件名: start-app.sh
|
|
||||||
|
|
||||||
# 设置环境变量
|
|
||||||
export OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE
|
|
||||||
export OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30
|
|
||||||
|
|
||||||
# 切换到项目目录
|
|
||||||
cd /Users/leocoder/leocoder/develop/templates/coder-common-thin/coder-common-thin-backend
|
|
||||||
|
|
||||||
# 启动应用程序
|
|
||||||
java -jar coder-common-thin-web/target/coder-common-thin-web-1.0.0.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
给脚本添加执行权限并运行:
|
|
||||||
```bash
|
|
||||||
chmod +x start-app.sh
|
|
||||||
./start-app.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🐳 Docker 环境
|
|
||||||
|
|
||||||
### 1. docker run 命令
|
|
||||||
```bash
|
|
||||||
docker run -d \
|
|
||||||
-e OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE \
|
|
||||||
-e OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30 \
|
|
||||||
-p 18099:18099 \
|
|
||||||
your-app-image
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. docker-compose.yml
|
|
||||||
```yaml
|
|
||||||
version: '3.8'
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
image: your-app-image
|
|
||||||
ports:
|
|
||||||
- "18099:18099"
|
|
||||||
environment:
|
|
||||||
- OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE
|
|
||||||
- OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 使用 .env 文件
|
|
||||||
```bash
|
|
||||||
# 创建 .env 文件
|
|
||||||
echo "OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE" > .env
|
|
||||||
echo "OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30" >> .env
|
|
||||||
|
|
||||||
# docker-compose 会自动读取
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔧 IDE 环境配置
|
|
||||||
|
|
||||||
### 1. IntelliJ IDEA
|
|
||||||
|
|
||||||
1. 打开 Run Configuration
|
|
||||||
2. 选择你的 Spring Boot 应用
|
|
||||||
3. 在 "Environment Variables" 中添加:
|
|
||||||
- `OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE`
|
|
||||||
- `OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30`
|
|
||||||
|
|
||||||
### 2. VS Code
|
|
||||||
|
|
||||||
在 `.vscode/launch.json` 中配置:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "java",
|
|
||||||
"name": "Spring Boot App",
|
|
||||||
"request": "launch",
|
|
||||||
"mainClass": "org.leocoder.thin.web.CoderApplication",
|
|
||||||
"env": {
|
|
||||||
"OSS_ACCESS_KEY_ID": "LTAI5t982gXi7A72gAa9yugE",
|
|
||||||
"OSS_ACCESS_KEY_SECRET": "Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Eclipse
|
|
||||||
|
|
||||||
1. 右击项目 → Run As → Run Configurations
|
|
||||||
2. 选择你的 Java Application
|
|
||||||
3. 在 "Environment" 选项卡中添加变量
|
|
||||||
|
|
||||||
## 🔐 安全最佳实践
|
|
||||||
|
|
||||||
### 1. 使用 .env 文件(推荐)
|
|
||||||
|
|
||||||
创建 `.env` 文件(不要提交到版本控制):
|
|
||||||
```bash
|
|
||||||
# .env 文件
|
|
||||||
OSS_ACCESS_KEY_ID=LTAI5t982gXi7A72gAa9yugE
|
|
||||||
OSS_ACCESS_KEY_SECRET=Mi9ZsSWLGkvFoMiLNiZ71hHFzVso30
|
|
||||||
```
|
|
||||||
|
|
||||||
在 `.gitignore` 中添加:
|
|
||||||
```
|
|
||||||
.env
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 使用系统密钥管理
|
|
||||||
|
|
||||||
**macOS Keychain:**
|
|
||||||
```bash
|
|
||||||
# 存储到 Keychain
|
|
||||||
security add-generic-password -s "oss-access-key" -a "your-app" -w "LTAI5t982gXi7A72gAa9yugE"
|
|
||||||
|
|
||||||
# 从 Keychain 读取
|
|
||||||
OSS_ACCESS_KEY_ID=$(security find-generic-password -s "oss-access-key" -a "your-app" -w)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Linux Secret Service:**
|
|
||||||
```bash
|
|
||||||
# 使用 secret-tool
|
|
||||||
secret-tool store --label="OSS Access Key" service oss-access-key LTAI5t982gXi7A72gAa9yugE
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 配置文件最佳实践
|
|
||||||
|
|
||||||
修改 `application-dev.yml`:
|
|
||||||
```yaml
|
|
||||||
coder:
|
|
||||||
oss:
|
|
||||||
# 只从环境变量读取,不设置默认值
|
|
||||||
access-key-id: ${OSS_ACCESS_KEY_ID}
|
|
||||||
access-key-secret: ${OSS_ACCESS_KEY_SECRET}
|
|
||||||
```
|
|
||||||
|
|
||||||
## ✅ 验证环境变量
|
|
||||||
|
|
||||||
### 1. 检查环境变量是否设置成功
|
|
||||||
```bash
|
|
||||||
# Linux/macOS
|
|
||||||
echo $OSS_ACCESS_KEY_ID
|
|
||||||
echo $OSS_ACCESS_KEY_SECRET
|
|
||||||
|
|
||||||
# Windows CMD
|
|
||||||
echo %OSS_ACCESS_KEY_ID%
|
|
||||||
echo %OSS_ACCESS_KEY_SECRET%
|
|
||||||
|
|
||||||
# Windows PowerShell
|
|
||||||
echo $env:OSS_ACCESS_KEY_ID
|
|
||||||
echo $env:OSS_ACCESS_KEY_SECRET
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 在应用程序中验证
|
|
||||||
|
|
||||||
在 Java 代码中临时添加日志:
|
|
||||||
```java
|
|
||||||
@PostConstruct
|
|
||||||
public void logOssConfig() {
|
|
||||||
log.info("OSS_ACCESS_KEY_ID: {}", System.getenv("OSS_ACCESS_KEY_ID"));
|
|
||||||
log.info("OSS_ACCESS_KEY_SECRET: {}",
|
|
||||||
System.getenv("OSS_ACCESS_KEY_SECRET") != null ? "已设置" : "未设置");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚨 注意事项
|
|
||||||
|
|
||||||
1. **不要在版本控制中提交真实的密钥**
|
|
||||||
2. **定期轮换访问密钥**
|
|
||||||
3. **使用最小权限原则配置OSS权限**
|
|
||||||
4. **在生产环境中使用更安全的密钥管理方案**
|
|
||||||
5. **重启应用程序后环境变量才会生效**
|
|
||||||
|
|
||||||
## 📝 快速设置脚本
|
|
||||||
|
|
||||||
我已经为你准备了一个快速设置脚本,运行即可:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 当前目录下创建 setup-env.sh
|
|
||||||
chmod +x setup-env.sh
|
|
||||||
./setup-env.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
按照这个指南设置环境变量后,你的OSS功能就可以正常使用了!
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,727 +0,0 @@
|
|||||||
# WebSocket权限实时推送技术方案设计
|
|
||||||
|
|
||||||
## 📋 项目背景
|
|
||||||
|
|
||||||
在当前的权限管理系统中,管理员修改用户权限后,用户需要重新登录才能获得最新权限,这严重影响了用户体验。为了解决这个问题,我们设计了基于WebSocket的权限实时推送方案,让权限变更能够立即生效。
|
|
||||||
|
|
||||||
## 🎯 整体架构设计
|
|
||||||
|
|
||||||
### 系统架构图
|
|
||||||
```
|
|
||||||
┌─────────────────┐ WebSocket ┌─────────────────┐ 数据库操作 ┌─────────────────┐
|
|
||||||
│ 前端应用 │ ←──────────→ │ Spring Boot │ ←──────────→ │ MySQL数据库 │
|
|
||||||
│ │ │ 后端服务 │ │ │
|
|
||||||
│ - 权限缓存 │ │ - WebSocket服务 │ │ - 用户权限表 │
|
|
||||||
│ - 实时更新 │ │ - 权限管理 │ │ - 权限变更记录 │
|
|
||||||
│ - 用户界面 │ │ - 消息推送 │ │ │
|
|
||||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### 核心目标
|
|
||||||
- ✅ 权限变更实时生效,无需重新登录
|
|
||||||
- ✅ 支持多标签页同步更新
|
|
||||||
- ✅ 安全可靠的消息推送机制
|
|
||||||
- ✅ 良好的用户体验和性能表现
|
|
||||||
|
|
||||||
## 🔧 后端技术方案设计
|
|
||||||
|
|
||||||
### 1. WebSocket服务架构
|
|
||||||
|
|
||||||
#### 1.1 技术栈选择
|
|
||||||
```
|
|
||||||
Spring Boot + Spring WebSocket + SaToken + Redis + MySQL
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 1.2 核心组件设计
|
|
||||||
```
|
|
||||||
┌── WebSocket管理层
|
|
||||||
│ ├── WebSocketConfig (配置)
|
|
||||||
│ ├── WebSocketHandler (连接处理)
|
|
||||||
│ └── WebSocketInterceptor (权限验证)
|
|
||||||
│
|
|
||||||
├── 权限推送服务层
|
|
||||||
│ ├── PermissionPushService (权限推送核心服务)
|
|
||||||
│ ├── UserSessionManager (用户会话管理)
|
|
||||||
│ └── MessageBroadcaster (消息广播器)
|
|
||||||
│
|
|
||||||
├── 权限监听层
|
|
||||||
│ ├── PermissionChangeListener (权限变更监听)
|
|
||||||
│ ├── RoleChangeListener (角色变更监听)
|
|
||||||
│ └── MenuChangeListener (菜单变更监听)
|
|
||||||
│
|
|
||||||
└── 数据存储层
|
|
||||||
├── Redis (会话存储 + 消息队列)
|
|
||||||
└── MySQL (权限数据 + 变更记录)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 核心服务设计
|
|
||||||
|
|
||||||
#### 2.1 WebSocket连接管理
|
|
||||||
```java
|
|
||||||
// 连接管理策略
|
|
||||||
- 用户登录后自动建立WebSocket连接
|
|
||||||
- 一个用户可以有多个连接(多标签页支持)
|
|
||||||
- 连接断开后自动重连机制
|
|
||||||
- 连接状态持久化到Redis
|
|
||||||
|
|
||||||
// 会话存储结构
|
|
||||||
Key: "websocket:user:{userId}"
|
|
||||||
Value: {
|
|
||||||
"connections": [
|
|
||||||
{
|
|
||||||
"sessionId": "session-123",
|
|
||||||
"connectTime": 1640995200000,
|
|
||||||
"lastHeartbeat": 1640995800000,
|
|
||||||
"browser": "Chrome",
|
|
||||||
"ip": "192.168.1.100"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.2 权限变更监听机制
|
|
||||||
```java
|
|
||||||
// 监听触发点
|
|
||||||
1. 用户角色分配/取消
|
|
||||||
2. 角色权限修改
|
|
||||||
3. 菜单权限调整
|
|
||||||
4. 用户状态变更
|
|
||||||
|
|
||||||
// 变更事件设计
|
|
||||||
@EventListener
|
|
||||||
public class PermissionChangeListener {
|
|
||||||
// 用户角色变更
|
|
||||||
@Async
|
|
||||||
public void handleUserRoleChange(UserRoleChangeEvent event)
|
|
||||||
|
|
||||||
// 角色权限变更
|
|
||||||
@Async
|
|
||||||
public void handleRolePermissionChange(RolePermissionChangeEvent event)
|
|
||||||
|
|
||||||
// 菜单权限变更
|
|
||||||
@Async
|
|
||||||
public void handleMenuPermissionChange(MenuPermissionChangeEvent event)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.3 消息推送策略
|
|
||||||
```java
|
|
||||||
// 消息类型设计
|
|
||||||
enum MessageType {
|
|
||||||
PERMISSION_UPDATE, // 权限更新
|
|
||||||
ROLE_CHANGE, // 角色变更
|
|
||||||
FORCE_LOGOUT, // 强制退出
|
|
||||||
SYSTEM_NOTICE // 系统通知
|
|
||||||
}
|
|
||||||
|
|
||||||
// 推送策略
|
|
||||||
1. 精准推送:只推送给受影响的用户
|
|
||||||
2. 批量推送:角色权限变更时推送给该角色的所有用户
|
|
||||||
3. 广播推送:系统级权限调整时推送给所有在线用户
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 数据库设计扩展
|
|
||||||
|
|
||||||
#### 3.1 权限变更记录表
|
|
||||||
```sql
|
|
||||||
CREATE TABLE sys_permission_change_log (
|
|
||||||
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
change_type VARCHAR(50) NOT NULL, -- USER_ROLE, ROLE_PERMISSION, MENU_PERMISSION
|
|
||||||
target_user_id BIGINT, -- 目标用户ID(如果是用户级变更)
|
|
||||||
target_role_id BIGINT, -- 目标角色ID(如果是角色级变更)
|
|
||||||
operator_id BIGINT NOT NULL, -- 操作者ID
|
|
||||||
change_detail JSON, -- 变更详情
|
|
||||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
INDEX idx_user_time (target_user_id, create_time),
|
|
||||||
INDEX idx_role_time (target_role_id, create_time)
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3.2 WebSocket会话表
|
|
||||||
```sql
|
|
||||||
CREATE TABLE sys_websocket_session (
|
|
||||||
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
user_id BIGINT NOT NULL,
|
|
||||||
session_id VARCHAR(100) NOT NULL UNIQUE,
|
|
||||||
connect_time DATETIME NOT NULL,
|
|
||||||
disconnect_time DATETIME,
|
|
||||||
client_info JSON, -- 客户端信息
|
|
||||||
status TINYINT DEFAULT 1, -- 1:连接中 0:已断开
|
|
||||||
INDEX idx_user_status (user_id, status)
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 后端核心接口设计
|
|
||||||
|
|
||||||
#### 4.1 WebSocket端点配置
|
|
||||||
```java
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSocket
|
|
||||||
public class WebSocketConfig implements WebSocketConfigurer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
|
|
||||||
registry.addHandler(new PermissionWebSocketHandler(), "/ws/permission")
|
|
||||||
.setAllowedOrigins("*")
|
|
||||||
.addInterceptors(new WebSocketAuthInterceptor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4.2 权限推送服务接口
|
|
||||||
```java
|
|
||||||
@Component
|
|
||||||
public class PermissionPushService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 推送权限更新消息给指定用户
|
|
||||||
*/
|
|
||||||
public void pushPermissionUpdate(Long userId, List<String> newPermissions);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 推送角色变更消息给指定用户
|
|
||||||
*/
|
|
||||||
public void pushRoleChange(Long userId, List<String> newRoles);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 批量推送权限更新(角色权限变更时)
|
|
||||||
*/
|
|
||||||
public void batchPushPermissionUpdate(Long roleId, List<String> newPermissions);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 强制用户下线
|
|
||||||
*/
|
|
||||||
public void forceUserLogout(Long userId, String reason);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4.3 消息格式定义
|
|
||||||
```java
|
|
||||||
@Data
|
|
||||||
public class WebSocketMessage {
|
|
||||||
private String type; // 消息类型
|
|
||||||
private Long userId; // 目标用户ID
|
|
||||||
private Long timestamp; // 时间戳
|
|
||||||
private Object data; // 消息数据
|
|
||||||
private String messageId; // 消息ID
|
|
||||||
private String operator; // 操作者
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class PermissionUpdateData {
|
|
||||||
private List<String> permissions; // 新权限列表
|
|
||||||
private List<String> roles; // 新角色列表
|
|
||||||
private String updateType; // 更新类型:ADD, REMOVE, REPLACE
|
|
||||||
private String reason; // 变更原因
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🌐 前端技术方案设计
|
|
||||||
|
|
||||||
### 1. WebSocket客户端架构
|
|
||||||
|
|
||||||
#### 1.1 技术栈
|
|
||||||
```
|
|
||||||
Vue3 + TypeScript + Pinia + WebSocket API
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 1.2 组件设计
|
|
||||||
```
|
|
||||||
┌── WebSocket管理层
|
|
||||||
│ ├── WebSocketService (核心WebSocket服务)
|
|
||||||
│ ├── ConnectionManager (连接管理器)
|
|
||||||
│ └── MessageHandler (消息处理器)
|
|
||||||
│
|
|
||||||
├── 权限更新层
|
|
||||||
│ ├── PermissionUpdateService (权限更新服务)
|
|
||||||
│ ├── PermissionSyncManager (权限同步管理)
|
|
||||||
│ └── PermissionNotification (权限通知)
|
|
||||||
│
|
|
||||||
└── 用户界面层
|
|
||||||
├── PermissionUpdateNotify (权限更新提示组件)
|
|
||||||
├── ConnectionStatus (连接状态组件)
|
|
||||||
└── WebSocketDebugPanel (调试面板)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. WebSocket服务设计
|
|
||||||
|
|
||||||
#### 2.1 连接管理策略
|
|
||||||
```typescript
|
|
||||||
class WebSocketService {
|
|
||||||
// 连接策略
|
|
||||||
- 用户登录成功后自动连接
|
|
||||||
- 连接断开后指数退避重连
|
|
||||||
- 页面可见性变化时管理连接
|
|
||||||
- 网络状态变化时重连
|
|
||||||
|
|
||||||
// 连接状态管理
|
|
||||||
enum ConnectionState {
|
|
||||||
DISCONNECTED = 'disconnected',
|
|
||||||
CONNECTING = 'connecting',
|
|
||||||
CONNECTED = 'connected',
|
|
||||||
RECONNECTING = 'reconnecting',
|
|
||||||
ERROR = 'error'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2.2 消息处理机制
|
|
||||||
```typescript
|
|
||||||
// 消息类型定义
|
|
||||||
interface WebSocketMessage {
|
|
||||||
type: 'PERMISSION_UPDATE' | 'ROLE_CHANGE' | 'FORCE_LOGOUT' | 'SYSTEM_NOTICE'
|
|
||||||
userId: number
|
|
||||||
timestamp: number
|
|
||||||
data: any
|
|
||||||
messageId: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// 消息处理器
|
|
||||||
class MessageHandler {
|
|
||||||
handlePermissionUpdate() // 处理权限更新
|
|
||||||
handleRoleChange() // 处理角色变更
|
|
||||||
handleForceLogout() // 处理强制退出
|
|
||||||
handleSystemNotice() // 处理系统通知
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 权限同步机制
|
|
||||||
|
|
||||||
#### 3.1 同步策略
|
|
||||||
```typescript
|
|
||||||
class PermissionSyncManager {
|
|
||||||
// 同步时机
|
|
||||||
1. 收到权限更新消息时立即同步
|
|
||||||
2. 连接重建后检查权限版本
|
|
||||||
3. 页面激活时检查权限一致性
|
|
||||||
|
|
||||||
// 同步方式
|
|
||||||
async syncPermissions(updateType: string) {
|
|
||||||
// 1. 请求最新权限数据
|
|
||||||
// 2. 更新本地权限缓存
|
|
||||||
// 3. 触发UI重新渲染
|
|
||||||
// 4. 显示权限更新通知
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3.2 冲突处理
|
|
||||||
```typescript
|
|
||||||
// 权限冲突处理策略
|
|
||||||
1. 权限被收回:立即隐藏相关UI,显示权限不足提示
|
|
||||||
2. 权限被授予:立即显示新的功能按钮,显示权限获得提示
|
|
||||||
3. 强制退出:清理本地数据,跳转到登录页
|
|
||||||
4. 操作中断:保存用户操作状态,权限恢复后继续
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 前端核心服务设计
|
|
||||||
|
|
||||||
#### 4.1 WebSocket服务接口
|
|
||||||
```typescript
|
|
||||||
export interface IWebSocketService {
|
|
||||||
// 连接管理
|
|
||||||
connect(): Promise<void>
|
|
||||||
disconnect(): void
|
|
||||||
reconnect(): Promise<void>
|
|
||||||
|
|
||||||
// 消息发送
|
|
||||||
sendMessage(message: WebSocketMessage): void
|
|
||||||
|
|
||||||
// 事件监听
|
|
||||||
onMessage(callback: (message: WebSocketMessage) => void): void
|
|
||||||
onConnected(callback: () => void): void
|
|
||||||
onDisconnected(callback: () => void): void
|
|
||||||
onError(callback: (error: Error) => void): void
|
|
||||||
|
|
||||||
// 状态查询
|
|
||||||
isConnected(): boolean
|
|
||||||
getConnectionState(): ConnectionState
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4.2 权限更新服务接口
|
|
||||||
```typescript
|
|
||||||
export interface IPermissionUpdateService {
|
|
||||||
// 权限同步
|
|
||||||
syncPermissions(): Promise<void>
|
|
||||||
updateLocalPermissions(permissions: string[]): void
|
|
||||||
|
|
||||||
// 通知管理
|
|
||||||
showPermissionUpdateNotification(updateInfo: PermissionUpdateInfo): void
|
|
||||||
showPermissionRevokedWarning(revokedPermissions: string[]): void
|
|
||||||
|
|
||||||
// 权限检查
|
|
||||||
checkPermissionChange(): Promise<boolean>
|
|
||||||
validateCurrentPermissions(): boolean
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🔐 安全性设计
|
|
||||||
|
|
||||||
### 1. 连接安全
|
|
||||||
```java
|
|
||||||
// Token验证
|
|
||||||
- WebSocket握手时验证JWT Token
|
|
||||||
- 定期验证Token有效性
|
|
||||||
- Token过期时自动断开连接
|
|
||||||
|
|
||||||
// 权限验证
|
|
||||||
- 连接建立时验证用户权限
|
|
||||||
- 消息发送前验证操作权限
|
|
||||||
- 防止权限越权操作
|
|
||||||
|
|
||||||
// 示例:WebSocket拦截器
|
|
||||||
@Component
|
|
||||||
public class WebSocketAuthInterceptor implements HandshakeInterceptor {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean beforeHandshake(ServerHttpRequest request,
|
|
||||||
ServerHttpResponse response,
|
|
||||||
WebSocketHandler wsHandler,
|
|
||||||
Map<String, Object> attributes) {
|
|
||||||
// 1. 提取Token
|
|
||||||
String token = extractTokenFromRequest(request);
|
|
||||||
|
|
||||||
// 2. 验证Token有效性
|
|
||||||
if (!saTokenUtil.isValidToken(token)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 获取用户信息
|
|
||||||
Long userId = saTokenUtil.getUserIdFromToken(token);
|
|
||||||
attributes.put("userId", userId);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 消息安全
|
|
||||||
```java
|
|
||||||
// 消息加密
|
|
||||||
- 敏感消息内容加密传输
|
|
||||||
- 消息完整性校验
|
|
||||||
- 防止消息重放攻击
|
|
||||||
|
|
||||||
// 频率限制
|
|
||||||
- 连接频率限制
|
|
||||||
- 消息发送频率限制
|
|
||||||
- 异常连接自动断开
|
|
||||||
|
|
||||||
// 示例:消息安全处理
|
|
||||||
@Component
|
|
||||||
public class MessageSecurityHandler {
|
|
||||||
|
|
||||||
public WebSocketMessage encryptMessage(WebSocketMessage message) {
|
|
||||||
// 对敏感数据进行加密
|
|
||||||
if (message.getType().equals("PERMISSION_UPDATE")) {
|
|
||||||
String encryptedData = aesUtil.encrypt(message.getData().toString());
|
|
||||||
message.setData(encryptedData);
|
|
||||||
}
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean validateMessageIntegrity(WebSocketMessage message) {
|
|
||||||
// 验证消息完整性
|
|
||||||
String expectedHash = calculateMessageHash(message);
|
|
||||||
return expectedHash.equals(message.getHash());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 访问控制
|
|
||||||
```java
|
|
||||||
// 用户隔离
|
|
||||||
- 确保用户只能接收自己的权限变更消息
|
|
||||||
- 防止跨用户信息泄露
|
|
||||||
- 管理员权限特殊处理
|
|
||||||
|
|
||||||
// 示例:消息权限验证
|
|
||||||
@Component
|
|
||||||
public class MessagePermissionValidator {
|
|
||||||
|
|
||||||
public boolean canReceiveMessage(Long userId, WebSocketMessage message) {
|
|
||||||
// 1. 检查消息是否发给该用户
|
|
||||||
if (!message.getUserId().equals(userId)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 检查用户是否有权限接收该类型消息
|
|
||||||
return hasPermissionToReceiveMessageType(userId, message.getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚀 性能优化方案
|
|
||||||
|
|
||||||
### 1. 连接优化
|
|
||||||
```java
|
|
||||||
// 连接池管理
|
|
||||||
- 合理设置连接数上限
|
|
||||||
- 空闲连接自动清理
|
|
||||||
- 连接状态监控
|
|
||||||
|
|
||||||
// 内存优化
|
|
||||||
- 及时清理断开的连接
|
|
||||||
- 消息队列大小限制
|
|
||||||
- 定期清理过期数据
|
|
||||||
|
|
||||||
// 示例:连接池配置
|
|
||||||
@Configuration
|
|
||||||
public class WebSocketPoolConfig {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public WebSocketConnectionPool connectionPool() {
|
|
||||||
return WebSocketConnectionPool.builder()
|
|
||||||
.maxConnections(10000) // 最大连接数
|
|
||||||
.maxConnectionsPerUser(5) // 每用户最大连接数
|
|
||||||
.idleTimeout(Duration.ofMinutes(30)) // 空闲超时
|
|
||||||
.cleanupInterval(Duration.ofMinutes(5)) // 清理间隔
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 推送优化
|
|
||||||
```java
|
|
||||||
// 批量推送
|
|
||||||
- 相同类型消息合并推送
|
|
||||||
- 延迟推送策略
|
|
||||||
- 推送优先级管理
|
|
||||||
|
|
||||||
// 缓存优化
|
|
||||||
- Redis缓存权限数据
|
|
||||||
- 权限变更增量推送
|
|
||||||
- 本地权限缓存
|
|
||||||
|
|
||||||
// 示例:批量推送实现
|
|
||||||
@Component
|
|
||||||
public class BatchMessagePusher {
|
|
||||||
|
|
||||||
private final Map<String, List<WebSocketMessage>> messageBatches = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@Scheduled(fixedDelay = 1000) // 每秒批量推送一次
|
|
||||||
public void flushMessageBatches() {
|
|
||||||
messageBatches.forEach((batchKey, messages) -> {
|
|
||||||
WebSocketMessage batchMessage = mergeMess
|
|
||||||
ages(messages);
|
|
||||||
webSocketHandler.broadcast(batchMessage);
|
|
||||||
});
|
|
||||||
messageBatches.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 数据库优化
|
|
||||||
```sql
|
|
||||||
-- 权限查询优化
|
|
||||||
CREATE INDEX idx_user_permission_version ON sys_login_user(user_id, permission_version);
|
|
||||||
CREATE INDEX idx_role_permission_update ON sys_role_menu(role_id, update_time);
|
|
||||||
|
|
||||||
-- 会话查询优化
|
|
||||||
CREATE INDEX idx_websocket_user_status ON sys_websocket_session(user_id, status, connect_time);
|
|
||||||
|
|
||||||
-- 变更日志查询优化
|
|
||||||
CREATE INDEX idx_permission_log_target ON sys_permission_change_log(target_user_id, target_role_id, create_time);
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📊 监控和日志
|
|
||||||
|
|
||||||
### 1. 连接监控
|
|
||||||
```java
|
|
||||||
// 监控指标
|
|
||||||
- 当前连接数
|
|
||||||
- 连接成功率
|
|
||||||
- 连接断开原因统计
|
|
||||||
- 消息推送成功率
|
|
||||||
|
|
||||||
// 示例:监控服务
|
|
||||||
@Component
|
|
||||||
public class WebSocketMonitorService {
|
|
||||||
|
|
||||||
private final MeterRegistry meterRegistry;
|
|
||||||
|
|
||||||
public void recordConnection(String result) {
|
|
||||||
Counter.builder("websocket.connections")
|
|
||||||
.tag("result", result)
|
|
||||||
.register(meterRegistry)
|
|
||||||
.increment();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void recordMessagePush(String type, String result) {
|
|
||||||
Counter.builder("websocket.messages")
|
|
||||||
.tag("type", type)
|
|
||||||
.tag("result", result)
|
|
||||||
.register(meterRegistry)
|
|
||||||
.increment();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 错误处理和日志
|
|
||||||
```java
|
|
||||||
// 日志记录
|
|
||||||
- 连接建立/断开日志
|
|
||||||
- 消息推送日志
|
|
||||||
- 错误异常日志
|
|
||||||
- 性能统计日志
|
|
||||||
|
|
||||||
// 示例:日志配置
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class WebSocketLogger {
|
|
||||||
|
|
||||||
public void logConnection(Long userId, String action, String result) {
|
|
||||||
log.info("WebSocket连接 - 用户:{}, 操作:{}, 结果:{}", userId, action, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void logMessagePush(Long userId, String messageType, String result) {
|
|
||||||
log.info("消息推送 - 用户:{}, 类型:{}, 结果:{}", userId, messageType, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void logError(String operation, Exception e) {
|
|
||||||
log.error("WebSocket错误 - 操作:{}, 异常:", operation, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📋 实施步骤
|
|
||||||
|
|
||||||
### 第一阶段:基础WebSocket服务(1-2周)
|
|
||||||
1. **后端WebSocket服务搭建**
|
|
||||||
- 创建WebSocket配置类
|
|
||||||
- 实现WebSocket处理器
|
|
||||||
- 添加权限验证拦截器
|
|
||||||
- 基础连接管理功能
|
|
||||||
|
|
||||||
2. **前端WebSocket客户端**
|
|
||||||
- 创建WebSocket服务类
|
|
||||||
- 实现连接管理逻辑
|
|
||||||
- 添加重连机制
|
|
||||||
- 基础消息收发功能
|
|
||||||
|
|
||||||
3. **基础测试**
|
|
||||||
- 连接建立测试
|
|
||||||
- 消息收发测试
|
|
||||||
- 断线重连测试
|
|
||||||
|
|
||||||
### 第二阶段:权限推送核心功能(2-3周)
|
|
||||||
1. **权限变更监听**
|
|
||||||
- 实现用户角色变更监听
|
|
||||||
- 实现角色权限变更监听
|
|
||||||
- 实现菜单权限变更监听
|
|
||||||
- 创建权限变更事件
|
|
||||||
|
|
||||||
2. **消息推送逻辑**
|
|
||||||
- 实现权限更新消息推送
|
|
||||||
- 实现角色变更消息推送
|
|
||||||
- 实现批量推送逻辑
|
|
||||||
- 添加消息去重机制
|
|
||||||
|
|
||||||
3. **前端权限同步**
|
|
||||||
- 实现权限数据更新
|
|
||||||
- 实现UI实时刷新
|
|
||||||
- 添加权限变更通知
|
|
||||||
- 处理权限冲突场景
|
|
||||||
|
|
||||||
### 第三阶段:高级功能和优化(2-3周)
|
|
||||||
1. **安全性增强**
|
|
||||||
- 添加消息加密
|
|
||||||
- 实现访问控制
|
|
||||||
- 添加频率限制
|
|
||||||
- 防止攻击机制
|
|
||||||
|
|
||||||
2. **性能优化**
|
|
||||||
- 实现连接池管理
|
|
||||||
- 添加消息批量处理
|
|
||||||
- 优化数据库查询
|
|
||||||
- 添加缓存机制
|
|
||||||
|
|
||||||
3. **用户体验优化**
|
|
||||||
- 完善重连策略
|
|
||||||
- 优化通知交互
|
|
||||||
- 添加调试面板
|
|
||||||
- 处理边界情况
|
|
||||||
|
|
||||||
### 第四阶段:生产环境适配(1-2周)
|
|
||||||
1. **集群部署支持**
|
|
||||||
- Redis消息队列
|
|
||||||
- 负载均衡配置
|
|
||||||
- 会话共享机制
|
|
||||||
|
|
||||||
2. **监控和运维**
|
|
||||||
- 添加监控指标
|
|
||||||
- 完善日志记录
|
|
||||||
- 配置告警机制
|
|
||||||
- 制定运维手册
|
|
||||||
|
|
||||||
3. **测试和部署**
|
|
||||||
- 压力测试
|
|
||||||
- 兼容性测试
|
|
||||||
- 生产环境部署
|
|
||||||
- 回滚方案准备
|
|
||||||
|
|
||||||
## 🔍 风险评估和应对方案
|
|
||||||
|
|
||||||
### 1. 技术风险
|
|
||||||
| 风险项 | 影响度 | 概率 | 应对方案 |
|
|
||||||
|--------|--------|------|----------|
|
|
||||||
| WebSocket连接不稳定 | 高 | 中 | 完善重连机制,降级到轮询 |
|
|
||||||
| 消息推送延迟 | 中 | 低 | 优化推送逻辑,添加超时机制 |
|
|
||||||
| 内存泄漏 | 高 | 低 | 定期清理,添加监控 |
|
|
||||||
| 安全漏洞 | 高 | 低 | 安全审计,权限校验 |
|
|
||||||
|
|
||||||
### 2. 业务风险
|
|
||||||
| 风险项 | 影响度 | 概率 | 应对方案 |
|
|
||||||
|--------|--------|------|----------|
|
|
||||||
| 权限同步失败 | 高 | 中 | 手动刷新机制,错误提示 |
|
|
||||||
| 用户体验下降 | 中 | 低 | 渐进式升级,用户反馈 |
|
|
||||||
| 系统复杂度增加 | 中 | 高 | 完善文档,团队培训 |
|
|
||||||
|
|
||||||
### 3. 运维风险
|
|
||||||
| 风险项 | 影响度 | 概率 | 应对方案 |
|
|
||||||
|--------|--------|------|----------|
|
|
||||||
| 服务器压力增加 | 中 | 中 | 性能监控,扩容预案 |
|
|
||||||
| 故障排查困难 | 中 | 中 | 详细日志,监控告警 |
|
|
||||||
| 部署复杂度增加 | 低 | 高 | 自动化部署,回滚机制 |
|
|
||||||
|
|
||||||
## 📈 预期效果
|
|
||||||
|
|
||||||
### 1. 用户体验提升
|
|
||||||
- ✅ 权限变更即时生效,无需重新登录
|
|
||||||
- ✅ 多标签页权限状态同步
|
|
||||||
- ✅ 清晰的权限变更通知
|
|
||||||
|
|
||||||
### 2. 系统性能
|
|
||||||
- ✅ 减少不必要的接口调用
|
|
||||||
- ✅ 提高权限检查效率
|
|
||||||
- ✅ 降低服务器负载
|
|
||||||
|
|
||||||
### 3. 管理效率
|
|
||||||
- ✅ 权限管理操作即时生效
|
|
||||||
- ✅ 减少用户投诉和支持工作
|
|
||||||
- ✅ 提高系统管理效率
|
|
||||||
|
|
||||||
## 📚 相关技术文档
|
|
||||||
|
|
||||||
1. [Spring WebSocket官方文档](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#websocket)
|
|
||||||
2. [Vue3 WebSocket最佳实践](https://vuejs.org/guide/extras/web-components.html)
|
|
||||||
3. [SaToken权限认证文档](https://sa-token.dev33.cn/)
|
|
||||||
4. [Redis消息队列使用指南](https://redis.io/docs/manual/pubsub/)
|
|
||||||
|
|
||||||
## 👥 团队分工建议
|
|
||||||
|
|
||||||
| 角色 | 职责 | 时间投入 |
|
|
||||||
|------|------|----------|
|
|
||||||
| 后端开发 | WebSocket服务、权限监听、消息推送 | 60% |
|
|
||||||
| 前端开发 | WebSocket客户端、权限同步、UI更新 | 40% |
|
|
||||||
| 测试工程师 | 功能测试、性能测试、安全测试 | 全程参与 |
|
|
||||||
| 运维工程师 | 部署配置、监控告警、性能调优 | 后期参与 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**文档版本**: v1.0
|
|
||||||
**创建时间**: 2025-01-07
|
|
||||||
**更新时间**: 2025-01-07
|
|
||||||
**负责人**: 系统架构团队
|
|
||||||
**审核人**: 技术负责人
|
|
||||||
Loading…
Reference in New Issue
Block a user