# 风七六本地生活服务平台全量开发规范

---

## 部署文档参考

- **阿里云开发环境部署方案
  **：[基于 Podman 的阿里云开发环境全量部署方案（完善版）](file:///d:/FzxBDSH/FzxFile/%E5%9F%BA%E4%BA%8E%20Podman%20%E7%9A%84%E9%98%BF%E9%87%8C%E4%BA%91%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E5%85%A8%E9%87%8F%E9%83%A8%E7%BD%B2%E6%96%B9%E6%A1%88%EF%BC%88%E5%AE%8C%E5%96%84%E7%89%88%EF%BC%89.md)

---

## 一、技术栈规范

### 1.1 容器技术

#### 容器运行时

- **使用 Podman** 而非 Docker
- Podman 是无守护进程的容器引擎，更安全、更轻量
- 命令兼容 Docker，但使用 `podman` 命令

#### 容器编排

- **使用 podman-compose** 而非 docker-compose
- 配置文件格式与 docker-compose 兼容
- 命令：`podman-compose up -d`、`podman-compose down`

#### 镜像仓库

- 国内镜像加速：`docker.m.daocloud.io`、`docker.1ms.run`
- 镜像命名格式：`docker.m.daocloud.io/library/<image>:<tag>`

#### Podman 与 Docker 兼容注意事项

- Podman 网络模式默认使用 bridge，需注意端口映射配置
- Podman 不支持 Docker 的 `--network host` 方式，需使用 `--network=host`
- Podman 卷挂载路径格式与 Docker 一致

### 1.2 数据库

#### 主数据库（MariaDB）

- **使用 MariaDB** 而非 MySQL（商业授权合规要求）
- MariaDB 是 MySQL 的开源分支，完全兼容 MySQL
- 版本：10.11（LTS 版本）
- 镜像：`docker.m.daocloud.io/library/mariadb:10.11`

#### 数据库连接配置

- JDBC URL 格式：`jdbc:mariadb://<host>:<port>/<database>`
- 驱动类：`org.mariadb.jdbc.Driver`
- 如果应用不支持 MariaDB 驱动，可以使用 MySQL 兼容模式：
  - JDBC URL：`jdbc:mysql://<host>:<port>/<database>`
  - 驱动类：`com.mysql.cj.jdbc.Driver`

#### PostgreSQL（用于 Kong API 网关）

- 版本：16.4
- 镜像：`postgres:16.4`

#### 数据库表/字段命名规范

- 表名：小写 + 下划线，如 `order_info`、`user_address`
- 字段名：小写 + 下划线，如 `user_mobile`、`order_amount`
- 主键：`id`（自增）或 `uuid`（分布式场景）
- 外键：`{关联表名}_id`，如 `user_id`、`order_id`

### 1.3 服务注册与配置中心（Nacos）

#### 基础配置

- 版本：2.4.3
- 镜像：`docker.1ms.run/nacos/nacos-server:v2.4.3`
- 模式：standalone（单机模式，开发环境）/ cluster（集群模式，生产环境）
- 存储：嵌入式存储（开发环境）/ MariaDB（生产环境）

#### 配置注意事项

- Nacos 2.4.3 使用 MySQL 驱动连接 MariaDB
- 环境变量命名：`MYSQL_SERVICE_*` 而非 `SPRING_DATASOURCE_*`
- 如果外部数据库配置失败，Nacos 会自动回退到嵌入式存储

#### 配置分层（Nacos）

- 公共配置：`common-{profile}.yml`（所有服务共享）
- 业务配置：`{service}-{profile}.yml`（各服务独立配置）
- 优先级：服务配置 > 公共配置 > 本地配置

### 1.4 缓存（Redis）

#### 基础配置

- 版本：7.2.4
- 镜像：`docker.m.daocloud.io/library/redis:7.2.4`
- 配置文件：`./config/redis/redis.conf`

#### 核心配置示例

```ini
# 内存限制（生产环境建议 2GB）
maxmemory 2gb
maxmemory-policy allkeys-lru

# 持久化配置
appendonly yes
appendfsync everysec

# 连接限制
maxclients 10000
timeout 0
```

### 1.5 消息队列（RocketMQ）

#### 基础配置

- 版本：5.3.1
- 镜像：`docker.1ms.run/apache/rocketmq:5.3.1`
- 组件：NameServer + Broker

#### 部署建议

- 开发环境：单节点 NameServer + 单节点 Broker
- 生产环境：双节点 NameServer + 双节点 Broker（主从）

### 1.6 API 网关（Kong）

#### 基础配置

- 版本：3.9.0
- 镜像：`docker.1ms.run/library/kong:3.9.0`
- 数据库：PostgreSQL

### 1.7 监控体系

#### Prometheus

- 版本：v2.54.1
- 镜像：`docker.1ms.run/prom/prometheus:v2.54.1`

#### Grafana

- 版本：11.2.0
- 镜像：`docker.1ms.run/grafana/grafana:11.2.0`

### 1.8 网络配置

#### 自定义网络

- 网络名称：`fzx-network`
- 驱动：bridge
- 子网：172.20.0.0/16
- 网关：172.20.0.1

#### 网络别名

- MariaDB：`mariadb`
- Redis：`redis`
- PostgreSQL：`postgres`
- Nacos：`nacos`

#### 阿里云环境网络配置（关键！）

**问题背景**：阿里云ECS默认使用`systemd-resolved`，宿主机`/etc/resolv.conf`指向`127.0.0.53`
，Podman默认bridge网络不做DNS转发，导致容器内无法解析内部服务名（如`nacos`），直接报**NXDOMAIN**。

**解决方案**：

1. **创建自定义网络**（必须！）

```bash
# 删除旧默认网络（可选）
podman network rm bridge

# 创建自定义网络（带DNS解析）
podman network create fzx-aliyun-dev-network --subnet=172.20.0.0/16 --gateway=172.20.0.1
```

2. **配置容器DNS**

```bash
# 临时：覆盖宿主机resolv.conf
echo "nameserver 223.5.5.5" > /etc/resolv.conf
echo "nameserver 119.29.29.29" >> /etc/resolv.conf

# 永久：修改podman配置
vi /etc/containers/containers.conf
# 找到 [network]，添加：
dns_servers = ["223.5.5.5", "119.29.29.29"]
```

3. **compose文件配置示例**

```yaml
networks:
  fzx-aliyun-dev-network:
    external: true
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16
          gateway: 172.20.0.1
    dns:
      - 223.5.5.5
      - 119.29.29.29
```

**避坑要点**：

- **网络不统一**：所有服务必须在**同一个自定义网络**，不能混用默认bridge
- **DNS没改**：阿里云宿主机默认`127.0.0.53`，容器用不了，必须改成**公共DNS**
- **Nacos地址别写localhost**：容器内`localhost`是容器自己，必须写**服务名nacos**或**宿主机IP**

### 1.9 数据持久化

#### 命名卷

- 使用 Podman 命名卷而非 bind mount
- 命名格式：`fzx-{service}-data`
- 示例：`fzx-mariadb-data`、`fzx-redis-data`

#### 卷配置示例

```yaml
volumes:
  mariadb-data:
    name: fzx-mariadb-data
    driver: local
```

---

## 二、开发流程规范

### 2.1 代码提交规则

#### 自动检验流程

每次修改或生成文件完成后，必须执行以下检验和提交流程：

1. **检查仓库状态**
   ```bash
   git status
   ```

2. **查看修改内容**
   ```bash
   git diff <file>
   ```

3. **本地验证清单**
  - 单元测试通过率 100%
  - 代码检查 0 错误
  - 编译无异常
  - 相关文档已更新

4. **添加修改到暂存区**
   ```bash
   git add -A
   ```

5. **提交修改**
   ```bash
   git commit -m "<type>: <subject>

   - <detail 1>
   - <detail 2>
   - <detail 3>"
   ```

6. **推送到远程仓库**
   ```bash
   git push origin develop
   ```

#### 提交信息规范

提交信息必须遵循以下格式：

```
<type>: <subject>

<body>
```

##### Type 类型

- `feat`: 新功能
- `fix`: 修复 bug
- `docs`: 文档更新
- `style`: 代码格式调整（不影响功能）
- `refactor`: 代码重构
- `perf`: 性能优化
- `test`: 测试相关
- `chore`: 构建过程或辅助工具的变动
- `ci`: CI/CD 配置
- `build`: 构建相关

##### Subject 规范

- 使用中文描述
- 不超过 50 个字
- 使用动词开头，如"添加"、"修复"、"更新"
- 结尾不加句号

##### Body 规范

- 使用中文描述
- 每行不超过 72 个字
- 详细说明修改内容和原因
- 使用列表形式列出主要修改

#### 提交限制

- 单次提交代码量不超过 500 行
- 避免超大提交，拆分逻辑相关的修改

#### 合并请求（MR/PR）审核规则

- 至少 1 人审核通过
- 审核内容包括：代码质量、安全性、命名规范、测试覆盖

#### 示例

```
feat: 添加用户登录功能

- 实现 JWT 认证机制
- 添加登录页面 UI
- 集成微信登录接口
- 添加登录状态管理
```

### 2.2 分支管理规则

#### 分支策略

- `main`: 生产环境分支（受保护）
- `develop`: 开发环境分支
- `feature/*`: 功能开发分支（从 develop 创建）
- `hotfix/*`: 紧急修复分支（从 main 创建）
- `release/*`: 发布分支（从 develop 创建）

#### 工作流程

1. 从 `develop` 分支创建功能分支：`feature/user-login`
2. 在功能分支上开发并提交
3. 完成后合并回 `develop` 分支（需 MR 审核）
4. 定期将 `develop` 分支推送到远程仓库
5. 发布前创建 `release/{version}` 分支进行测试
6. 测试通过后合并到 `main` 和 `develop`

#### 分支命名规范

- 功能分支：`feature/{功能名称}`，如 `feature/payment-integration`
- 修复分支：`hotfix/{问题描述}`，如 `hotfix/order-payment-error`
- 发布分支：`release/{版本号}`，如 `release/v1.0.0`

### 2.3 文档管理规则

#### 文档更新

- 修改代码时必须更新相关文档
- 添加新功能时必须添加使用文档
- 修改 API 时必须更新 API 文档

#### 文档位置

- 项目文档：`/docs`
- API 文档：`/docs/api`
- 部署文档：`/docs/deployment`

#### 文档格式

- 使用 Markdown 格式
- 文件名使用小写 + 中横线，如 `api-documentation.md`
- 图片存放在 `/docs/assets` 目录

### 2.4 跨团队协作规范

#### 接口联调流程

1. **需求评审**：各团队共同评审接口设计文档（API 文档需包含请求/响应格式、错误码、超时时间）
2. **契约测试**：使用 Pact 或 Spring Cloud Contract 进行接口契约测试
3. **联调环境**：在测试环境进行联合调试，确保接口互通
4. **文档同步**：接口变更需同步更新 API 文档，并通知相关团队

#### 分支合并冲突处理

1. **冲突检测**：合并前先拉取目标分支最新代码，本地解决冲突
2. **冲突分类**：
  - **代码逻辑冲突**：与相关开发人员沟通确认解决方案
  - **配置文件冲突**：保留最新配置或协商合并
  - **测试文件冲突**：运行测试验证合并结果
3. **冲突记录**：记录重大冲突及解决方案，便于后续复盘

#### 基线更新同步机制

1. **同步通知**：基线更新后 24 小时内通知所有开发人员
2. **同步时效**：开发人员需在收到通知后 48 小时内同步基线
3. **未同步风险**：未同步基线可能导致代码冲突，责任由开发人员承担

---

## 三、项目基线管理规范

### 3.1 基线定义

**clean-base** 分支为项目唯一纯净基线，是所有功能开发、bug 修复、环境部署的基础版本。

#### 基线要求

- ✅ 无编译错误
- ✅ 无未使用代码、无冗余依赖
- ✅ 无敏感配置、无本地调试代码
- ✅ 数据库、网关、服务注册发现配置统一规范
- ✅ 可直接构建、启动、部署

### 3.2 基线使用规则

- **禁止直接在 clean-base 上开发业务功能**
- **所有新功能必须从 clean-base 分支拉出开发分支**
- **基线仅接受**：架构修复、配置统一、依赖清理、代码规范修复
- **基线提交必须清晰标注**：`chore: 基线更新` / `fix: 基线修复`
- **每次基线更新必须本地验证构建成功**

### 3.3 基线更新流程（必须遵守）

```
1. 切换到 clean-base
   → git checkout clean-base
   → git pull origin clean-base

2. 修复问题（规范、依赖、配置、未使用代码）

3. 本地构建验证（mvn compile）
   → cd backend && mvn clean compile -DskipTests

4. 提交并推送
   → git add -A
   → git commit -m "chore: 基线更新 - 清理未使用依赖"
   → git push origin clean-base

5. 通知所有开发人员同步最新基线
```

### 3.4 基线禁止行为

- ❌ 不允许提交临时文件、测试文件、IDE 配置文件
- ❌ 不允许提交未完成代码、注释代码
- ❌ 不允许强制推送他人修改过的基线
- ❌ 不允许在基线中混合业务功能与架构修复

### 3.5 基线版本管理

- 基线版本采用语义化版本控制：`v{major}.{minor}.{patch}-clean-base`
- 重大架构变更升级 major 版本
- 配置/依赖清理升级 minor 版本
- 修复性更新升级 patch 版本
- 版本标签示例：`v1.0.0-clean-base`、`v1.1.0-clean-base`、`v1.1.1-clean-base`

### 3.6 临时文件管理规则

#### 临时文件存放位置

所有本地优化配置、临时文件统一存放在：

```
local_optimization_temp/
├── kong/                    # Kong网关配置
├── temp_security/          # 临时安全工具
├── nginx/                  # Nginx配置
├── Dockerfile.optimized    # 优化版Dockerfile
└── init-kong.sh           # Kong初始化脚本
```

#### 临时文件规则

| 规则               | 说明                    |
|------------------|-----------------------|
| ✅ 保留在本地          | 作为本地优化参考              |
| ❌ 不提交Git         | 不污染版本库                |
| ❌ 不合并到基线         | 保持基线纯净                |
| 🔄 可复制到feature分支 | 如需正式集成，先移到feature分支测试 |

#### .gitignore 配置

确保以下内容已在 `.gitignore` 中：

```
local_optimization_temp/
*.local
*.temp
*.tmp
.DS_Store
.idea/
.vscode/
```

---

## 四、质量与安全规范

### 4.1 代码质量规则

#### 代码检查

- 提交前必须运行代码检查工具
- 修复所有错误和警告
- 保持代码风格一致
- **连带修复原则**：在修复问题过程中发现的相关问题（如编译错误、明显的代码缺陷、缺失的导入等），应一并解决，避免后续重复进入相同代码模块浪费时间。但需保持提交原子性，可拆分多个提交。

#### 测试要求

- 新增功能必须包含单元测试（覆盖率 ≥ 80%）
- 修复 bug 必须包含回归测试
- 提交前必须确保所有测试通过

#### 代码注释规范

##### 类/方法注释模板（JavaDoc/TSDoc）

```java
/**
 * 功能描述：用户服务接口
 *
 * @author 作者名
 * @version 1.0.0
 * @since 2026-05-01
 */
public interface UserService {

    /**
     * 根据用户ID获取用户信息
     *
     * @param userId 用户ID（必填）
     * @return 用户信息对象
     * @throws NotFoundException 用户不存在时抛出
     */
    User getUserById(String userId);
}
```

##### 注释要求

- 复杂业务逻辑必须加注释
- 注释语言统一使用中文
- 避免无意义注释（如 `// 获取用户`）
- 定期清理过时注释

#### 导入顺序规范（阿里开发手册强制规范）

**【强制】** Java 导入语句必须按以下顺序排列，组间不允许有空行：

```
1. java.*         （Java 标准库）
2. javax.*        （Java 扩展库）
3. org.*          （第三方组织库，如 Spring、Hibernate）
4. com.*          （本公司/项目内部包）
5. net.*          （网络相关库）
6. static 导入    （静态导入，放在最后）
```

**导入顺序规则：**
- 每组导入之间**不允许有空行**
- 同组内导入按字母顺序排列
- 同一模块的导入应集中排列
- 未使用的导入必须删除

**常见第三方库分组示例：**

| 库 | 分组 |
|---|------|
| java.util, java.time, java.io | java |
| javax.servlet, javax.persistence | javax |
| org.springframework, org.apache, org.slf4j | org |
| com.fzx, com.google | com |

**反面示例（错误）：**
```java
import com.fzx.service.UserService;    // com 在前
import org.springframework.stereotype.Service;  // org 在后
import java.util.List;                // java 在最后
```

**正面示例（正确）：**
```java
import java.util.List;
import org.springframework.stereotype.Service;
import com.fzx.service.UserService;
```

#### 方法参数数量规范（阿里开发手册强制规范）

**【强制】** 方法参数数量限制：

| 参数数量 | 处理方式 |
|---------|---------|
| ≤ 3 个 | 可直接使用基本参数 |
| 4-5 个 | 建议封装为DTO对象 |
| > 5 个 | **必须**封装为DTO对象 |
| > 7 个 | Checkstyle强制报错，必须修复 |

**规范说明：**
- 参数过多会导致方法调用复杂、可读性差、维护困难
- 封装DTO对象可以提高代码可维护性和可扩展性
- DTO对象应使用Lombok的`@Data`、`@Builder`注解简化代码

**反面示例（错误）：**
```java
// 8个参数，违反规范
private WithdrawalRecord createWithdrawalRecord(Long accountId, SplitAccount account, BigDecimal amount,
                                                BigDecimal fee, BigDecimal actualAmount,
                                                String bankName, String bankAccount, String accountName) {
    // ...
}
```

**正面示例（正确）：**
```java
// 使用DTO封装参数
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WithdrawalCreationDTO {
    private Long accountId;
    private Object account;
    private BigDecimal amount;
    private BigDecimal fee;
    private BigDecimal actualAmount;
    private String bankName;
    private String bankAccount;
    private String accountName;
}

private WithdrawalRecord createWithdrawalRecord(WithdrawalCreationDTO dto) {
    // ...
}
```

**DTO命名规范：**
- 创建类DTO：`{业务对象}CreationDTO`，如`WithdrawalCreationDTO`
- 更新类DTO：`{业务对象}UpdateDTO`，如`WithdrawalUpdateDTO`
- 查询类DTO：`{业务对象}QueryDTO`，如`WithdrawalQueryDTO`
- DTO应放置在对应模块的`dto`包下

### 4.2 安全规则

#### 敏感信息管理

- 禁止提交密码、密钥等敏感信息
- 使用环境变量或配置文件管理敏感信息
- 定期检查代码中的敏感信息泄露（CI/CD 自动扫描）

#### 硬编码防护

- 禁止硬编码配置信息，如域名、URL、端口等
- 禁止硬编码敏感信息，如 API 密钥、密码等
- 使用配置文件或环境变量管理所有配置信息
- 对于 CORS 配置，必须使用配置文件管理允许的域名列表

#### 输入验证

- 对所有用户输入进行严格的验证和过滤
- 验证输入的类型、长度、格式等
- 防止 SQL 注入、XSS 攻击等安全漏洞
- 使用参数化查询处理数据库操作

#### 接口签名规则

- API 请求必须包含 `timestamp` + `nonce` + `sign` 校验
- 签名算法：HMAC-SHA256
- timestamp 有效期：5 分钟（防止重放攻击）
- nonce：随机字符串，确保请求唯一性

#### 认证和授权

- 实现强密码策略（8-32 位，包含大小写字母、数字、特殊字符）
- 使用 HTTPS 协议传输敏感数据
- 实现基于角色的访问控制（RBAC）
- 定期更新认证令牌（JWT Token 过期时间：2 小时）
- 实现会话超时机制（30 分钟无操作自动退出）

#### 数据加密

- 敏感数据（手机号、身份证号）使用 AES-256 加密存储
- 传输敏感数据使用 HTTPS + TLS 1.3
- 定期更新加密密钥（每季度轮换）
- RSA 密钥长度：2048 位（签名）/ 4096 位（加密）

#### 安全日志记录

- 记录所有安全相关的操作（登录、权限变更、数据访问）
- 记录异常访问和攻击尝试
- 定期检查和分析安全日志
- 实现日志备份和归档（保留 30 天）

---

## 五、部署脚本规范（强制）

### 5.1 错误码标准化

所有部署脚本必须使用统一错误码：

| 错误码 | 常量名 | 说明 |
|-----|--------|------|
| 0 | `SUCCESS` | 成功 |
| 21 | `NO_DEPLOY_SERVICES` | 无可部署服务 |
| 33 | `INVALID_COMPOSE_FILE` | 无效的compose文件 |
| 40 | `KEY_MISSING` | 密钥缺失 |
| 41 | `KEY_TOO_SHORT` | 密钥长度不足 |
| 42 | `KEY_VERIFY_FAILED` | 密钥验证失败 |
| 43 | `DECRYPT_FAILED` | 环境解密失败 |
| 50 | `PRE_CHECK_FAILED` | 前置校验失败 |
| 50 | `DISK_SPACE_INSUFFICIENT` | 磁盘空间不足 |
| 51 | `COMPOSE_SYNTAX_ERROR` | Compose语法错误 |
| 52 | `IMAGE_NOT_FOUND` | 镜像不存在 |
| 53 | `REGISTRY_LOGIN_FAILED` | 仓库登录失败 |
| 1 | `DEPLOY_FAILED` | 部署失败 |

### 5.2 前置校验规范

所有部署脚本必须执行以下前置校验：

| 校验项 | 开关变量 | 错误码 | 说明 |
|-------|--------|------|------|
| 目录权限 | `SKIP_PRE_CHECK` | 50 | 检查部署目录权限为755 |
| 磁盘空间 | `SKIP_DISK_CHECK` | 50 | 检查磁盘使用率<90% |
| Compose语法 | - | 51 | 验证compose配置文件语法 |
| 仓库登录 | `SKIP_REGISTRY_LOGIN` | 53 | 验证镜像仓库连通性 |
| 镜像存在性 | `SKIP_IMAGE_CHECK` | 52 | 验证目标镜像存在 |
| 端口占用 | `SKIP_PORT_CHECK` | 50 | 检查服务端口未被占用 |

### 5.3 配置加密规范

#### 加密算法

- **算法**：AES-256-GCM
- **密钥长度**：32字节（64位十六进制）或32位字符串
- **IV长度**：12字节（随机生成）
- **Tag长度**：16字节

#### 加密格式

```
ENCRYPTED::{base64编码的加密数据}
```

#### 加密验证

在解密前必须执行加密解密验证：

```python
test_plaintext = 'fzx_encryption_test_2024'
encrypted = encrypt_value(test_plaintext, key)
decrypted = decrypt_value(encrypted, key)
if decrypted != test_plaintext:
    return ErrorCode.KEY_VERIFY_FAILED
```

#### 解密失败处理

- **任何配置项解密失败**：立即阻断部署
- **返回错误码**：43（DECRYPT_FAILED）
- **禁止继续执行**：不要使用原始加密值继续部署

### 5.4 校验日志规范

所有前置校验日志必须添加 `[PRE_CHECK]` 前缀：

```
[PRE_CHECK] 执行部署前置校验...
[PRE_CHECK] 1/6 校验部署目录权限...
[PRE_CHECK]  OK: 目录权限已修正为755
[PRE_CHECK] 2/6 校验磁盘空间...
[PRE_CHECK]  INFO: 磁盘空间检查: /opt - 可用=20G, 使用率=60%
[PRE_CHECK] 3/6 校验Compose语法...
[PRE_CHECK]  OK: Compose语法校验通过: podman-compose.aliyun-dev.yml
[PRE_CHECK] 4/6 校验镜像仓库连通性...
[PRE_CHECK]  OK: 镜像仓库已登录: registry.cn-hangzhou.aliyuncs.com
[PRE_CHECK] 5/6 校验镜像存在性...
[PRE_CHECK]  OK: 镜像存在: registry.cn-hangzhou.aliyuncs.com/fzxbdsh/api-gateway:v1.1.0
[PRE_CHECK] 6/6 校验端口占用...
[PRE_CHECK]  OK: 端口占用检查通过
```

### 5.5 脚本开发要求

- ✅ 必须使用错误码返回
- ✅ 必须包含完整的错误日志输出
- ✅ 必须执行前置校验
- ✅ 禁止硬编码敏感信息
- ✅ 禁止使用明文密码
- ✅ 必须支持校验开关配置

---

## 六、配置管理规范（强制）

### 6.1 环境变量规范

#### 环境变量文件结构

```
env/
├── .env.example          # 示例配置（无敏感信息）
└── .env.aliyun-dev       # 加密的环境变量文件（提交到Git）
```

#### 敏感变量清单

| 变量名 | 用途 | 加密要求 |
|-------|------|---------|
| `MARIADB_ROOT_PASSWORD` | 数据库根密码 | 必须加密 |
| `MARIADB_PASSWORD` | 数据库服务密码 | 必须加密 |
| `REDIS_PASSWORD` | Redis密码 | 必须加密 |
| `JWT_SECRET_KEY` | JWT密钥 | 必须加密 |
| `NACOS_PASSWORD` | Nacos密码 | 必须加密 |
| `REGISTRY_USERNAME` | 镜像仓库用户名 | 必须加密 |
| `REGISTRY_PASSWORD` | 镜像仓库密码 | 必须加密 |
| `WEBHOOK_TOKEN` | Webhook令牌 | 必须加密 |
| `JENKINS_PASSWORD` | Jenkins密码 | 必须加密 |

#### 环境变量命名规范

- 全大写，下划线分隔
- 前缀标识用途：`MARIADB_`、`REDIS_`、`JWT_`、`NACOS_`等
- 避免缩写，使用完整单词

### 6.2 配置文件加密规范

#### 加密流程

```
1. 创建.env文件（包含敏感信息）
   ↓
2. 使用env-encrypt.py加密
   ↓
3. 生成.env.aliyun-dev（加密版本）
   ↓
4. 提交加密版本到Git
   ↓
5. 删除明文版本
```

#### 解密流程

```
1. 从Jenkins Credentials获取ENV_ENCRYPT_KEY
   ↓
2. 在本地（Jenkins容器内）解密.env.aliyun-dev
   ↓
3. 上传解密后的.env文件到服务器
   ↓
4. 执行部署
```

#### 加密密钥管理

- **密钥存储**：Jenkins Credentials（ID: `env-encrypt-key`）
- **密钥格式**：64位十六进制或32位字符串
- **密钥轮换**：每90天轮换一次，更新所有相关加密配置

---

## 七、镜像仓库管理规范（强制）

### 7.1 镜像仓库配置

#### 本地开发环境仓库

- **仓库名称**：fzx-local-registry
- **地址**：`http://localhost:5000`
- **数据目录**：`D:\opt\local-registry\data`（Windows）/ `/opt/local-registry/data`（Linux）
- **用途**：本地开发、测试镜像存储

#### 阿里云开发环境仓库

- **仓库名称**：fzx-aliyun-registry
- **地址**：`http://localhost:5000`（容器网络）
- **数据目录**：`/opt/local-registry/data`
- **用途**：阿里云开发环境镜像存储

#### 阿里云容器镜像服务

- **仓库地址**：`registry.cn-hangzhou.aliyuncs.com/fzxbdsh`
- **用途**：CI/CD流水线构建、部署镜像存储
- **认证方式**：使用 `REGISTRY_USERNAME`/`REGISTRY_PASSWORD` 环境变量

### 7.2 镜像标签策略（强制）

#### 标签命名规范

| 标签类型 | 格式 | 示例 | 用途 |
|--------|------|------|------|
| 开发测试标签 | `latest` | `localhost:5000/fzx/api-gateway:latest` | 本地开发、快速迭代 |
| 稳定版本标签 | `v{major}.{minor}.{patch}` | `localhost:5000/fzx/api-gateway:v1.1.0` | 阿里云开发/测试环境部署 |

#### 版本号同步规则

- **镜像版本号必须与基线版本保持一致**
- 当前基线版本：`v1.1.0-clean-base` → 镜像标签：`v1.1.0`
- 基线升级后，镜像标签同步升级

### 7.3 镜像仓库登录规范（强制）

#### 登录凭证配置

- **凭证来源**：Jenkins Credentials 或环境变量
- **用户名变量**：`REGISTRY_USERNAME`
- **密码变量**：`REGISTRY_PASSWORD`
- **禁止硬编码**：禁止在任何脚本或配置文件中硬编码仓库凭证

#### 登录验证流程

```
1. 部署前检查是否已登录
   ↓
2. 未登录时使用环境变量凭证登录
   ↓
3. 登录失败时阻断部署流程
   ↓
4. 返回错误码 53（REGISTRY_LOGIN_FAILED）
```

#### 依赖管理

- 定期更新依赖（每月检查）
- 检查依赖包的安全漏洞（使用 dependency-check 或类似工具）
- 使用固定版本（禁止使用 `latest`）
- 第三方依赖审计流程（每月执行）
- 引入新依赖前必须进行安全评估

#### 供应链安全扫描（SCA）

- **强制启用 dependency-check**：绑定 Maven verify 阶段，作为上线安全卡点
- **离线模式配置**：生产环境网络隔离时使用离线模式，配置如下：
  ```xml
  <plugin>
      <groupId>org.owasp</groupId>
      <artifactId>dependency-check-maven</artifactId>
      <configuration>
          <offline>true</offline>
          <dataDirectory>${maven.user.home}/.dependency-check</dataDirectory>
          <disableOssIndex>true</disableOssIndex>
          <disableCentral>true</disableCentral>
          <failBuildOnCVSS>0</failBuildOnCVSS>
      </configuration>
  </plugin>
  ```
- **漏洞库更新**：每月在联网环境执行 `mvn dependency-check:check` 更新本地缓存
- **禁止永久禁用**：仅允许临时跳过（`-Ddependency-check.skip=true`）或临时注释 execution，禁止删除插件配置

#### 安全审计日志规范

```json
{
  "timestamp": "2026-05-12T10:30:00",
  "level": "INFO",
  "traceId": "abc123",
  "userId": "123456",
  "operation": "LOGIN",
  "resource": "/api/v1/user/login",
  "status": "SUCCESS",
  "clientIp": "192.168.1.1",
  "userAgent": "Mozilla/5.0",
  "detail": "用户登录成功"
}
```

### 4.3 业务场景特殊规则

#### 支付/订单核心流程

- 接口幂等性设计（使用订单号/请求 ID 去重）
- 分布式事务保障（使用 RocketMQ 消息事务）
- 支付回调必须验证签名
- 订单状态机严格校验（禁止非法状态转换）

### 4.4 CI/CD 效率优化规范

#### Maven 依赖缓存

- 在 Jenkins Pipeline 中配置 Maven 本地仓库缓存
- 基于 `pom.xml` 哈希值生成缓存密钥
- 配置回退密钥，提高缓存命中率

```groovy
options {
    cache(path: '~/.m2/repository',
          key: 'maven-${MD5SUM(pom.xml)}',
          restoreKeys: ['maven-'])
}
```

#### Docker 镜像分层缓存

- 使用 `--cache-from` 参数复用已有镜像层
- 按环境打标签，便于缓存复用
- 保留 `latest` 标签作为缓存源

#### 流水线并行化

- 单元测试与代码质量检查并行执行
- 不同环境采用不同的并行策略（开发环境简化）
- 使用 `parallel` 块实现阶段并行

```groovy
stage('Parallel Tests') {
    parallel {
        stage('Unit Test') {
            steps { sh 'mvn test' }
        }
        stage('Code Quality') {
            steps { sh 'mvn checkstyle:check pmd:check' }
        }
    }
}
```

### 4.5 质量左移规范

#### Pre-commit 钩子配置

- 使用 `pre-commit` 工具在代码提交前执行检查
- 配置 Checkstyle 代码风格检查
- 添加 trailing-whitespace、remove-tabs 等基础检查

```yaml
repos:
  - repo: https://github.com/pre-commit/mirrors-checkstyle
    rev: 'google_checks'
    hooks:
      - id: checkstyle
        args: ['-c', 'checkstyle/checkstyle.xml']

  - repo: https://github.com/Lucas-C/pre-commit-hooks
    rev: v1.1.10
    hooks:
      - id: remove-tabs
      - id: trailing-whitespace
```

#### 钩子安装与使用

```bash
# 安装 pre-commit
pip install pre-commit

# 安装钩子
pre-commit install

# 手动执行检查
pre-commit run --all-files
```

### 4.6 监控告警规范

#### 告警分级策略

| 级别     | 触发条件                  | 响应时间 |
|--------|-----------------------|------|
| P1（紧急） | Jenkins服务宕机、服务器磁盘>90% | 15分钟 |
| P2（重要） | 构建连续失败≥3次、证书有效期<7天    | 30分钟 |
| P3（一般） | 容器异常退出、资源使用率>80%      | 1小时  |

#### 钉钉告警集成

- 使用钉钉机器人推送告警消息
- 配置健康检查脚本定时执行
- 覆盖服务器、容器、应用多维度监控

```bash
send_alert() {
    local message=$1
    curl -s -X POST $DINGTALK_WEBHOOK \
      -H 'Content-Type: application/json' \
      -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$message\"}}"
}
```

#### 运维操作标准化

- 环境切换脚本集成至 Jenkins 流水线
- 实现一键切换环境（dev/test/pre）
- 操作日志自动记录，便于问题追溯

#### 巡检闭环流程

- 定期执行巡检脚本
- 记录 CPU、内存、容器状态等指标
- 异常情况自动触发告警

#### 高并发场景

- **Redis 限流**（单用户每秒最多 10 次请求）
- **MQ 削峰**（秒杀场景使用消息队列缓冲）
- **数据库读写分离**（读操作走从库）
- **接口熔断降级**（使用 Sentinel 或 Hystrix）

##### Redis 限流实现示例（令牌桶算法）

```java
// 使用 Redis 实现令牌桶限流
public boolean isAllowed(String userId, String resourceKey, int maxTokens, int refillRate) {
    String bucketKey = "rate:limit:" + resourceKey + ":" + userId;
    String timestampKey = bucketKey + ":timestamp";

    try (var redisOps = redisTemplate.opsForValue()) {
        long now = System.currentTimeMillis() / 1000;
        Long currentTokens = redisOps.increment(bucketKey, -1);

        if (currentTokens == null || currentTokens > maxTokens) {
            // 初始化令牌桶
            redisOps.set(bucketKey, String.valueOf(maxTokens));
            redisOps.set(timestampKey, String.valueOf(now));
            return true;
        }

        if (currentTokens >= 0) {
            return true;
        }

        // 令牌耗尽，尝试补充
        Long lastRefillTime = Long.parseLong(redisOps.get(timestampKey));
        long tokensToAdd = (now - lastRefillTime) * refillRate;

        if (tokensToAdd > 0) {
            long newTokens = Math.min(tokensToAdd, maxTokens);
            redisOps.set(bucketKey, String.valueOf(newTokens));
            redisOps.set(timestampKey, String.valueOf(now));
            return newTokens > 0;
        }

        return false;
    }
}
```

##### RocketMQ 分布式事务示例

```java
// 半消息发送 + 本地事务 + 事务状态回查
public void sendOrderMessage(String orderId, String payload) throws MQClientException {
    TransactionMQProducer producer = new TransactionMQProducer("order-transaction-group");

    producer.setTransactionListener(new TransactionListener() {
        @Override
        public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
            try {
                // 1. 执行本地事务（扣库存、创建订单）
                orderService.createOrder(orderId);
                inventoryService.decreaseStock(orderId);
                return LocalTransactionState.COMMIT_MESSAGE;
            } catch (Exception e) {
                log.error("本地事务失败", e);
                return LocalTransactionState.ROLLBACK_MESSAGE;
            }
        }

        @Override
        public LocalTransactionState checkLocalTransaction(MessageExt msg) {
            // 回查本地事务状态
            String orderId = msg.getKeys();
            if (orderService.isOrderCreated(orderId)) {
                return LocalTransactionState.COMMIT_MESSAGE;
            }
            return LocalTransactionState.ROLLBACK_MESSAGE;
        }
    });

    Message message = new Message("order-topic", "order-tag", orderId, payload.getBytes());
    producer.sendMessageInTransaction(message, null);
}

#### 数据脱敏规则
- 手机号：`138****1234`（中间 4 位脱敏）
- 身份证号：`110101**********1234`（中间 8 位脱敏）
- 地址：`北京市朝阳区****街道`（详细地址脱敏）
- 脱敏规则统一封装工具类，禁止重复实现

---

## 四、交付与部署规范

### 4.1 部署前检查
- 确保所有测试通过
- 确保代码已提交并推送
- 确保文档已更新
- 确认配置文件正确（环境变量、数据库连接等）

### 4.2 部署流程

#### 标准部署步骤
1. **构建前端应用**（执行 `npm run build`）
2. **构建后端服务**（执行 `mvn clean package`）
3. **打包 Docker/Podman 镜像**
4. **运行数据库迁移**（Flyway）
5. **部署到服务器**（滚动发布）
6. **验证部署结果**（健康检查、接口测试）

#### 滚动发布流程
1. 停止部分容器（如 1/3）
2. 部署新版本
3. 启动新容器并验证健康状态
4. 重复步骤 1-3 直到全部更新完成
5. 监控服务状态 10 分钟

#### 蓝绿发布流程（适用于重大变更）
1. 部署新版本到"绿环境"
2. 验证绿环境服务正常
3. 切换流量到绿环境
4. 保留蓝环境一段时间（回滚备用）
5. 确认稳定后销毁蓝环境

#### 部署回滚规则
- 发布失败后 10 分钟内必须回滚
- 回滚流程：停止新版本 → 启动旧版本 → 验证服务
- 回滚后需记录原因并复盘

### 4.3 容器化部署

#### 容器资源限制
| 服务 | CPU | 内存 | 备注 |
|------|-----|------|------|
| MariaDB | 2核 | 4GB | 生产环境 |
| Redis | 1核 | 2GB | 生产环境 |
| Nacos | 1核 | 1GB | 单机模式 |
| API Gateway | 2核 | 2GB | 生产环境 |
| 业务服务 | 1核 | 1GB | 每个服务 |

#### 健康检查配置
```yaml
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 60s
```

#### Kubernetes 适配（规模化部署）

##### Deployment 配置示例

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: platform-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: platform-service
  template:
    metadata:
      labels:
        app: platform-service
    spec:
      containers:
      - name: platform-service
        image: fzx-platform-service:latest
        resources:
          requests:
            memory: "512Mi"
            cpu: "100m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
```

##### HPA 自动扩缩容配置

```yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: platform-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: platform-service
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

#### 日志管理
- 使用 JSON 文件驱动
- 设置日志大小限制（单个文件 100MB）
- 日志保留数量（保留 30 个）
- 启用日志压缩（gzip）
- 日志采集：使用 Filebeat/Fluentd 采集到 Elasticsearch

### 4.4 CI/CD 流程规范

#### CI 流程
```

代码提交 → 代码检查（SonarQube）→ 单元测试 → 构建 → 镜像构建 → 镜像扫描（Trivy）

```

#### CD 流程
```

镜像推送 → 部署到测试环境 → 自动化测试 → 人工验证 → 部署到生产环境（滚动发布）

```

#### CI/CD 质量门禁
- 代码覆盖率 ≥ 80%
- 代码检查无严重/阻断级问题
- 单元测试通过率 100%
- 镜像扫描无高危漏洞

### 4.5 监控运维

#### 监控指标
- CPU 使用率（阈值：>80% 告警）
- 内存使用率（阈值：>85% 告警）
- 磁盘使用率（阈值：>90% 告警）
- 接口响应时间（阈值：>1s 告警）
- 错误率（阈值：>5% 告警）

#### 告警机制
- **告警渠道**：钉钉/企业微信/邮件
- **告警级别**：紧急（立即通知）、重要（10 分钟内处理）、一般（工作日处理）
- **告警收敛**：同一问题 5 分钟内只告警一次
- **告警联动**：CPU>90% + 错误率>10% 自动触发服务降级

#### APM 链路追踪
- **工具选型**：SkyWalking 或 Jaeger
- **追踪范围**：API Gateway → 业务服务 → 数据库 → 缓存
- **采样策略**：生产环境 10% 采样，测试环境 100% 采样
- **关键指标**：
  - 服务响应时间（P50/P95/P99）
  - 调用链成功率
  - 数据库慢查询（>500ms）

#### 故障应急预案

##### 核心服务降级策略
- 支付服务降级：切换到备用支付通道
- 订单服务降级：只读模式，暂停创建订单
- 用户服务降级：缓存用户信息，减少数据库查询

##### 数据库/缓存故障兜底
- 数据库故障：使用本地缓存数据应急
- Redis 故障：降级为数据库直接查询（性能下降但可用）
- 主库故障：自动切换到从库

##### 应急响应流程
1. 收到告警 → 确认问题 → 启动应急预案
2. 降级服务（如必要）→ 通知相关人员
3. 排查根因 → 修复问题 → 恢复服务
4. 复盘总结 → 更新应急预案

---

## 五、命名与设计规范

### 5.1 命名规范

#### 核心原则
| 原则 | 说明 |
|------|------|
| **全部小写** | 服务名、容器名、域名等必须使用小写字母 |
| **中横线连接** | 单词之间使用中横线 `-` 连接，禁止使用下划线或驼峰 |
| **业务领域命名** | 使用业务领域名称命名，不使用 `admin`、`manager`、`console` 等模糊词汇 |
| **全局唯一** | 服务名在整个项目中必须唯一 |
| **语义清晰** | 命名应直观表达服务/组件的功能 |

#### 服务命名规范
**服务名格式**: `{业务领域}-service`

| 服务名称 | 服务标识 |
|----------|----------|
| 平台端服务 | `platform-service` |
| 用户端服务 | `user-service` |
| 商家端服务 | `merchant-service` |
| 骑手端服务 | `rider-service` |
| 订单服务 | `order-service` |
| API 网关 | `api-gateway` |

#### 容器命名规范
**容器名格式**: `{环境}-{服务标识}`

| 环境 | 标识 |
|------|------|
| 本地开发 | `fzx-local` |
| 开发环境 | `dev` |
| 测试环境 | `test` |
| 生产环境 | `prod` |

#### URL 路由规范
| 应用 | 主路径 | 别名路径（兼容） |
|------|--------|----------------|
| 平台端 | `/platform/` | `/admin/` |
| 用户端 | `/user/` | - |
| 商家端 | `/merchant/` | - |
| 骑手端 | `/rider/` | - |
| 官方网站 | `/official/` | `/`（根路径） |

#### 前端组件/页面命名
- 组件：`PascalCase`，如 `UserOrderList.vue`、`MerchantCard.tsx`
- 页面：`PascalCase`，如 `OrderDetailPage.vue`
- 工具函数：`camelCase`，如 `formatPhone.ts`
- 常量：`UPPER_SNAKE_CASE`，如 `MAX_RETRY_COUNT`

#### 日志文件命名
- 格式：`{服务名}-{日期}.log`
- 示例：`platform-service-2026-05-12.log`

#### 统一别名规则
为保持向后兼容性，允许以下别名映射：
- `platform` → `admin`（平台端管理后台，兼容旧链接）

> **注意**：别名仅用于 URL 路由兼容，代码和配置中必须使用主名称 `platform`。

### 5.2 UI/UX 设计规范

#### 主色调规范
- **主色调统一使用 #067bff**
- 所有页面、组件、按钮、导航栏等 UI 元素的主色调必须使用 #067bff
- 禁止使用 #1890ff、#ff7f00 等其他颜色作为主色调
- 主色调应用场景：按钮、导航栏、选中状态、重要图标等

#### 多端一致性规范
- 用户端小程序版本与 APP 版本必须保持功能、页面、交互体验完全一致
- 小程序版本必须包含与 APP 版本相同的所有页面
- 底部导航栏配置必须一致，包含相同数量的页面和相同的图标
- 所有新增功能必须同时在小程序和 APP 版本中实现

---

## 六、接口规范

### 6.1 RESTful API 字段规范

#### 响应码定义
| 响应码 | 含义 | 使用场景 |
|--------|------|----------|
| 200 | 成功 | 请求成功，返回数据 |
| 201 | 创建成功 | POST 请求成功创建资源 |
| 204 | 无内容 | 请求成功，但无返回数据 |
| 400 | 参数错误 | 请求参数校验失败 |
| 401 | 未认证 | 用户未登录或 Token 过期 |
| 403 | 无权限 | 用户无权限访问该资源 |
| 404 | 资源不存在 | 请求的资源不存在 |
| 409 | 冲突 | 资源冲突（如重复提交） |
| 500 | 服务异常 | 服务器内部错误 |

#### 响应格式规范
```json
{
  "code": 200,
  "message": "success",
  "data": {
    // 业务数据
  },
  "timestamp": 1715472000000
}
```

#### 错误响应格式

```json
{
  "code": 400,
  "message": "参数错误：用户ID不能为空",
  "data": null,
  "timestamp": 1715472000000,
  "errorDetail": {
    "field": "userId",
    "message": "不能为空"
  }
}
```

### 6.2 接口版本管理

- 版本标识：`/v{版本号}/`，如 `/v1/user/login`
- 版本升级策略：新增接口使用新版本，旧版本保留一段时间
- 版本废弃：提前 30 天通知，废弃后返回 410（Gone）

### 6.3 接口幂等性设计

- 使用 `requestId`（客户端生成的唯一标识）去重
- 对于支付/订单等核心接口，必须实现幂等性
- 幂等性保证时间：至少 24 小时
- 幂等性存储：使用 Redis 存储 requestId，设置过期时间

### 6.4 分页响应格式规范

```json
{
  "code": 200,
  "message": "success",
  "data": {
    "list": [],
    "pagination": {
      "pageNum": 1,
      "pageSize": 10,
      "total": 100,
      "totalPages": 10
    }
  },
  "timestamp": 1715472000000
}
```

### 6.5 API 限流规范

- **限流策略**：基于用户 ID/IP 的令牌桶限流
- **限流阈值**：
  - 普通接口：单用户每秒 10 次
  - 核心接口（支付/订单）：单用户每秒 5 次
  - 公共接口：单 IP 每分钟 100 次
- **限流返回码**：429（Too Many Requests）
- **限流提示**：{"code": 429, "message": "请求过于频繁，请稍后重试"}

---

## 七、多环境配置规范

### 7.1 环境隔离方案

#### 配置文件结构

```
backend/
├── src/main/resources/
│   ├── application.yml          # 公共配置
│   ├── application-dev.yml      # 开发环境
│   ├── application-test.yml     # 测试环境
│   └── application-prod.yml     # 生产环境
└── .env                        # 环境变量（不提交版本控制）
```

#### 环境变量文件

- 文件位置：`./.env`
- 包含所有敏感信息（密码、密钥等）
- 不要提交到版本控制

#### 环境变量命名

- 使用大写字母和下划线
- 前缀表示服务名称
- 示例：`MARIADB_ROOT_PASSWORD`、`REDIS_PASSWORD`

### 7.2 配置中心分层（Nacos）

#### 配置优先级（从高到低）

1. 运行时参数（命令行参数）
2. Nacos 服务配置（`{service}-{profile}.yml`）
3. Nacos 公共配置（`common-{profile}.yml`）
4. 本地配置文件（`application-{profile}.yml`）
5. 本地公共配置（`application.yml`）

---

## 八、最佳实践

### 8.1 前端最佳实践

#### 架构设计

- 使用分层架构，将 UI、业务逻辑、数据访问分离
- 采用状态管理库（如 Provider、GetX）管理应用状态
- 实现路由管理，使用命名路由或路由导航器

#### API 集成

- 封装网络服务，统一处理 API 调用
- 实现错误处理机制，包括网络错误、业务错误等
- 使用拦截器处理认证 Token、请求/响应格式化等

#### 性能优化

- 使用 const 构造函数创建不变的 Widget
- 实现懒加载和缓存机制
- 优化图片加载，使用适当的图片格式和大小
- 减少不必要的重建和重绘

#### 用户体验

- 实现加载状态和错误提示
- 提供离线支持和缓存策略
- 优化动画和过渡效果

### 8.2 后端最佳实践

#### API 设计

- 采用 RESTful API 设计风格
- 统一响应格式，包含状态码、消息和数据
- 实现 API 版本控制
- 提供 API 文档（如 Swagger）

#### 代码结构

- 采用分层架构，如 Controller、Service、Mapper
- 实现依赖注入，减少代码耦合
- 使用异常处理机制，统一处理错误

#### 数据库设计

- 使用数据库迁移工具（如 Flyway）管理数据库结构
- 设计合理的表结构和索引
- 实现事务管理，确保数据一致性

#### 安全措施

- 实现认证和授权机制
- 防止 SQL 注入、XSS 等安全漏洞
- 对敏感数据进行加密处理

### 8.3 中间件最佳实践

#### API 网关

- 配置合理的路由规则
- 实现限流、熔断等保护机制
- 统一处理跨域请求

#### 服务注册和发现

- 使用服务注册中心（如 Nacos）管理服务
- 实现服务健康检查和自动发现

#### 缓存策略

- 使用 Redis 等缓存技术提高性能
- 设计合理的缓存键和过期策略
- 实现缓存与数据库的一致性保证

##### 缓存穿透防护

```java
// 使用布隆过滤器防止缓存穿透
public User getUserById(Long userId) {
    // 1. 先查布隆过滤器
    if (!bloomFilter.mightContain(userId)) {
        return null;
    }

    // 2. 查缓存
    User user = (User) redisTemplate.opsForValue().get("user:" + userId);
    if (user != null) {
        return user;
    }

    // 3. 查数据库
    user = userRepository.findById(userId).orElse(null);

    if (user != null) {
        redisTemplate.opsForValue().set("user:" + userId, user, 30, TimeUnit.MINUTES);
    } else {
        // 空值也缓存，防止缓存穿透
        redisTemplate.opsForValue().set("user:" + userId, null, 5, TimeUnit.MINUTES);
    }

    return user;
}
```

##### 缓存击穿防护（热点key过期）

```java
// 使用分布式锁防止缓存击穿
public User getHotUser(Long userId) {
    String cacheKey = "user:hot:" + userId;

    // 1. 先查缓存
    User user = (User) redisTemplate.opsForValue().get(cacheKey);
    if (user != null) {
        return user;
    }

    // 2. 获取分布式锁
    String lockKey = "lock:user:" + userId;
    Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 30, TimeUnit.SECONDS);

    if (Boolean.TRUE.equals(lockAcquired)) {
        try {
            // 3. 双重检查缓存
            user = (User) redisTemplate.opsForValue().get(cacheKey);
            if (user != null) {
                return user;
            }

            // 4. 查询数据库
            user = userRepository.findById(userId).orElse(null);

            if (user != null) {
                redisTemplate.opsForValue().set(cacheKey, user, 2, TimeUnit.HOURS);
            }
        } finally {
            redisTemplate.delete(lockKey);
        }
    } else {
        // 等待其他线程更新缓存后重试
        Thread.sleep(100);
        return getHotUser(userId);
    }

    return user;
}
```

##### 缓存雪崩防护

- **方案1**：设置不同的过期时间（随机偏移 0-30 分钟）
- **方案2**：使用多级缓存（本地缓存 + Redis）
- **方案3**：热点数据永不过期，后台定时更新

---

## 九、问题排查

### 9.1 Podman 配置错误

- **错误**：`invalid escape in string`
- **解决**：检查 `/etc/containers/registries.conf.d/99-mirror.conf` 文件格式

### 9.2 容器无法启动

1. 检查日志：`podman logs <container_name>`
2. 检查环境变量：`podman exec <container_name> env`
3. 检查网络：`podman network inspect fzx-network`

### 9.3 数据库连接失败

1. 确认数据库容器正在运行
2. 确认网络别名正确
3. 确认用户名和密码正确
4. 确认数据库已创建

### 9.4 Nacos 启动失败

1. 检查内存配置（至少 256MB）
2. 检查数据库连接配置
3. 查看日志：`podman logs fzx-local-nacos`

### 9.5 接口调用失败

1. 检查网络连通性：`curl http://localhost:8089/api/health`
2. 检查服务是否注册到 Nacos
3. 检查网关路由配置

---

## 十、后端开发强制规范

### 10.1 数据库字符集强制规范

#### 10.1.1 建库强制规则

所有业务库、新库，必须按以下标准创建：

```sql
CREATE DATABASE 库名
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;
```

**禁止**：不指定字符集直接建库；使用 `utf8` / `latin1` / `gbk`

#### 10.1.2 建表强制规则

所有业务表结尾必须固定声明：

```sql
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```

#### 10.1.3 字段设计约束

- 所有字符串类业务字段，统一用 `varchar` / `text`
- 禁止使用非 `utf8mb4` 排序规则
- 预留 emoji、生僻字存储能力

### 10.2 JDBC 连接串统一规范

#### 标准模板

```yaml
jdbc:mariadb://mariadb:3306/库名?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai&useSSL=false&allowMultiQueries=true
```

#### 强制必带参数

- `useUnicode=true`
- `characterEncoding=utf8mb4`
- `serverTimezone=Asia/Shanghai`

### 10.3 MariaDB Docker 部署规范

```yaml
command:
  - --character-set-server=utf8mb4
  - --collation-server=utf8mb4_unicode_ci
  - --init-connect=SET NAMES utf8mb4
  - --skip-character-set-client-handshake
```

### 10.4 Spring Boot 依赖注入规范

#### 统一注入方案

所有 `@Service` / `@Component` / `@FeignClient` 实现类：

- 统一使用 **Lombok + 构造器注入**
- 固定注解：`@RequiredArgsConstructor`

#### 标准模板

```java
@Service
@RequiredArgsConstructor
public class XxxServiceImpl implements XxxService {
    private final XxxMapper xxxMapper;
    private final XxxFeign xxxFeign;
}
```

#### 三条红线（严禁违反）

1. **禁止混用**：同时写 `@Autowired` 字段 + 手动构造器 + `@RequiredArgsConstructor`
2. **禁止手写**无参/有参构造器与 Lombok 注解共存
3. **禁止**注入字段不加 `final`

### 10.5 阿里开发手册核心编码规范（强制）

#### 10.5.1 空值判断规范

**强制要求**：使用 `Objects.isNull()` / `Objects.nonNull()` 替代 `== null` / `!= null`

```java
// 正确写法
if (Objects.isNull(user)) {
    throw new ResourceNotFoundException("User", userId);
}

if (Objects.nonNull(user.getAddress())) {
    // 处理地址
}

// 错误写法（禁止）
if (user == null) { ... }
if (user != null) { ... }
```

#### 10.5.2 字符串判断规范

**强制要求**：使用 `StringUtils.isEmpty()` / `StringUtils.isBlank()` 判断字符串

```java
// 正确写法
if (StringUtils.isEmpty(name)) { ... }
if (StringUtils.isBlank(description)) { ... }

// 错误写法（禁止）
if ("".equals(name)) { ... }
if (name == "") { ... }
```

#### 10.5.3 集合初始化规范

**强制要求**：集合初始化时必须指定初始容量

```java
// 正确写法
List<String> list = new ArrayList<>(10);
Map<String, Object> map = new HashMap<>(16);
Set<String> set = new HashSet<>(8);

// 错误写法（禁止）
List<String> list = new ArrayList<>();  // 未指定初始容量
```

**容量选择原则**：

- 预估元素数量 <= 7：初始容量设为 8
- 预估元素数量 <= 15：初始容量设为 16
- 预估元素数量 <= 31：初始容量设为 32

#### 10.5.4 异常处理规范

**强制要求**：禁止直接抛出 `RuntimeException` / `Exception`，必须使用自定义异常

```java
// 正确写法
throw new ResourceNotFoundException("User", userId);
throw new BusinessException("ORDER_EXPIRED", "订单已过期");
throw new ValidationException("phone", "手机号格式不正确");

// 错误写法（禁止）
throw new RuntimeException("用户不存在");
throw new Exception("业务异常");
```

#### 10.5.5 日志规范

**强制要求**：使用参数化日志，禁止字符串拼接

```java
// 正确写法
log.info("用户登录成功，用户ID：{}", userId);
log.warn("订单状态异常，订单号：{}，状态：{}", orderNo, status);
log.error("支付失败，订单ID：{}，错误信息：{}", orderId, e.getMessage(), e);

// 错误写法（禁止）
log.info("用户登录成功，用户ID：" + userId);
log.info("用户登录成功，用户ID：" + userId + "，时间：" + System.currentTimeMillis());
```

#### 10.5.6 方法参数规范

**强制要求**：方法参数不超过 4 个，超过时使用 DTO 封装

```java
// 正确写法
public void createOrder(OrderCreateDTO dto) { ... }

// 错误写法（禁止）
public void createOrder(Long userId, Long merchantId, BigDecimal amount,
                        String address, String phone, String remark) { ... }
```

#### 10.5.7 魔法数字规范

**强制要求**：魔法数字必须定义为常量

```java
// 正确写法
private static final int MAX_RETRY_COUNT = 3;
private static final int TIMEOUT_SECONDS = 30;

// 错误写法（禁止）
if (retryCount >= 3) { ... }
if (timeout > 30) { ... }
```

---

## 十一、团队协作规范

### 11.1 代码审核规则

- 所有合并到 clean-base 的代码必须经过至少 1 人审核
- 审核内容包括：代码质量、安全性、命名规范、测试覆盖
- 审核通过后方可合并

### 11.2 基线同步通知

基线更新后 24 小时内通知所有开发人员：

```
【基线更新通知】
版本：v1.1.0-clean-base
更新内容：xxx
同步要求：请在 48 小时内同步最新基线
```

### 11.3 新人入职流程

1. 阅读本文档
2. 阅读 `项目开发规范&Git工作流规则.md` Git工作流规范
3. 从 `v1.1.0-clean-base` 标签开始熟悉代码
4. 在 `feature/security-enhance` 分支进行开发
5. 导师带教完成第一个功能

### 11.4 违规处理

| 违规行为            | 处理方式        |
|-----------------|-------------|
| 直接修改 clean-base | 回滚 + 警告     |
| 提交敏感信息          | 立即删除 + 安全审查 |
| 未测试部署云端         | 回滚 + 批评教育   |
| 多次违规            | 暂停开发权限 + 培训 |

---

## 十二、规则落地保障

### 12.1 规则执行检查机制

- **规则合规性检查清单**：每周抽检代码/配置是否符合规范
- **CI/CD 自动校验**：
  - 提交时检查命名规范
  - 代码注释覆盖率检查
  - 接口规范校验
  - 安全漏洞扫描
  - 字符集配置校验
  - 依赖注入规范校验

### 12.2 规则更新流程

1. 提出规则修改申请（描述修改原因和内容）
2. 项目负责人 + 技术负责人双确认
3. 更新文档并增加版本号
4. 同步团队培训
5. 更新 CI/CD 校验规则

### 12.3 例外场景处理

- **规则豁免流程**：特殊业务场景需临时偏离规范，需书面申请
- 记录豁免场景和原因
- 定期复盘（每月），评估是否需要调整规则

---

## 十三、版本与更新记录

### 版本信息

- **版本**：v2.2.0
- **生效日期**：2026-06-16
- **适用范围**：风七六本地生活服务平台所有开发团队

### 版本兼容性

| 组件         | 版本      | 兼容性说明                       |
|------------|---------|-----------------------------|
| Podman     | 5.8.1   | Windows WSL2                |
| MariaDB    | 10.11   | MySQL 8.0 兼容                |
| Nacos      | 2.4.3   | Spring Cloud Alibaba 2022.x |
| Redis      | 7.2.4   | -                           |
| RocketMQ   | 5.3.1   | -                           |
| Kong       | 3.9.0   | -                           |
| Prometheus | v2.54.1 | -                           |
| Grafana    | 11.2.0  | -                           |

### 更新记录

| 日期         | 版本     | 更新内容                      | 作者   |
|------------|--------|---------------------------|------|
| 2026-04-04 | v1.0.0 | 创建技术栈规则文件                 | 技术团队 |
| 2026-05-11 | v1.1.0 | 添加命名规范章节                  | 技术团队 |
| 2026-05-12 | v2.0.0 | 合并技术栈和开发规则，全面完善规范         | 技术团队 |
| 2026-05-14 | v2.1.0 | 添加后端开发强制规范（字符集、JDBC、依赖注入） | 技术团队 |
| 2026-06-16 | v2.2.0 | 对标大厂标准，新增日期时间、集合、SQL、并发、微服务规范 | 技术团队 |

---

## 附录：命名转换对照表

| 旧命名             | 新命名                |
|-----------------|--------------------|
| `admin-service` | `platform-service` |
| `AdminService`  | `PlatformService`  |
| `admin-web`     | `platform_web`     |
| `admin.conf`    | `platform.conf`    |
| `ADMIN_*`       | `PLATFORM_*`       |

---

## 十四、环境变量管理规范（大厂标准）

### 14.1 核心原则

#### 禁止硬编码原则

- **❌ 禁止**在代码或配置文件中硬编码任何敏感信息（密码、密钥、地址等）
- **❌ 禁止**硬编码 IP 地址，必须使用容器别名或 DNS 解析
- **✅ 必须**使用环境变量传递所有配置参数

#### 环境变量命名规范

| 规则    | 说明             | 示例                                |
|-------|----------------|-----------------------------------|
| 全大写   | 所有环境变量必须使用大写字母 | `SPRING_DATASOURCE_URL`           |
| 下划线分隔 | 单词之间使用下划线分隔    | `REDIS_HOST`                      |
| 前缀区分  | 不同组件使用统一前缀     | `MARIADB_*`, `REDIS_*`, `NACOS_*` |
| 语义清晰  | 变量名必须清晰表达含义    | `JWT_SECRET_KEY`                  |

### 14.2 环境变量分类

#### 基础配置变量

```bash
# 环境标识
ENV=dev
ENVIRONMENT_NAME=开发环境

# 时区配置（全局统一）
TZ=Asia/Shanghai
```

#### 数据库配置变量

```bash
# MariaDB 配置
MARIADB_HOST=mariadb
MARIADB_PORT=3306
MARIADB_DATABASE=fzx_local_life
MARIADB_USER=fzx_app
MARIADB_PASSWORD=your_secure_password

# 连接池配置
DB_POOL_MAX_SIZE=20
DB_POOL_MIN_IDLE=5
DB_CONNECTION_TIMEOUT=30000
```

#### 缓存配置变量

```bash
# Redis 配置
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password
REDIS_DATABASE=0

# 连接池配置
REDIS_POOL_MAX_ACTIVE=8
REDIS_POOL_MAX_IDLE=8
REDIS_TIMEOUT=30000
```

#### 服务注册配置变量

```bash
# Nacos 配置
NACOS_SERVER_ADDR=nacos:8848
NACOS_NAMESPACE=public
NACOS_USERNAME=nacos
NACOS_PASSWORD=nacos
NACOS_DISCOVERY_ENABLED=true
NACOS_CONFIG_ENABLED=true
```

#### 安全配置变量

```bash
# JWT 配置（生产环境必须 >= 32 字符）
JWT_SECRET_KEY=your_very_secure_jwt_secret_key_at_least_32_chars
JWT_EXPIRE_TIME=86400000
JWT_ISSUER=fengqiliu

# 加密密钥
ENCRYPTION_MASTER_KEY=your_secure_encryption_key_32_chars
```

#### 第三方服务配置变量

```bash
# 钉钉告警
DINGTALK_WEBHOOK_URL=https://oapi.dingtalk.com/robot/send?access_token=xxx
DINGTALK_SECRET=your_dingtalk_secret

# 短信服务
SMS_ACCESS_KEY_ID=your_sms_access_key
SMS_ACCESS_KEY_SECRET=your_sms_secret

# 云存储 OSS
OSS_ACCESS_KEY_ID=your_oss_key
OSS_ACCESS_KEY_SECRET=your_oss_secret
OSS_BUCKET_NAME=your_bucket
OSS_ENDPOINT=oss-cn-beijing.aliyuncs.com

# 地图服务
MAP_API_KEY=your_map_api_key
```

### 14.3 容器网络别名规范

#### 容器别名命名规则

- **基础设施服务**：使用简单名称作为别名
  - MariaDB: `mariadb`
  - Redis: `redis`
  - Nacos: `nacos`

- **业务微服务**：使用 `-service` 后缀作为别名
  - 用户服务: `user-service`
  - 认证服务: `auth-service`
  - 订单服务: `order-service`

#### docker-compose 配置示例

```yaml
services:
  user-service:
    container_name: fzx-local-user-service
    networks:
      fzx-backend-network:
        aliases:
          - user-service  # 容器别名，供其他服务访问
```

### 14.4 环境变量配置文件管理

#### 配置文件结构

```
env/
├── .env.example        # 示例配置（提交到版本库）
├── .env.local          # 本地开发环境（不提交）
├── .env.dev            # 开发环境
├── .env.test           # 测试环境
├── .env.staging        # 预发布环境
└── .env.prod           # 生产环境（不提交，仅在服务器上配置）
```

#### .gitignore 配置

```
# 环境变量文件（敏感信息）
.env
.env.local
.env.prod
.env.production

# 容器配置
docker-compose.override.yml
```

### 14.5 多环境配置策略

#### 环境隔离原则

| 环境    | 数据库              | Redis | 端口范围      | 用途     |
|-------|------------------|-------|-----------|--------|
| 本地开发  | fzx_local_life   | 本地容器  | 8080-8099 | 日常开发调试 |
| 开发环境  | fzx_aliyun_life  | 共享容器  | 8080-8099 | 联调测试   |
| 测试环境  | fzx_test_life    | 独立容器  | 8180-8199 | 自动化测试  |
| 预发布环境 | fzx_staging_life | 独立容器  | 8280-8299 | 灰度验证   |
| 生产环境  | fzx_prod_life    | 独立集群  | 80/443    | 正式服务   |

#### 配置优先级（Spring Boot）

1. 命令行参数（最高优先级）
2. 环境变量
3. Nacos 配置中心
4. application-{profile}.yml
5. application.yml（最低优先级）

### 14.6 容器资源配置规范

#### 单环境运行模式（4核8GB服务器）

```bash
# 资源限制配置
RESOURCE_DB_CPU_LIMIT=1.5
RESOURCE_DB_MEMORY_LIMIT=2G

RESOURCE_REDIS_CPU_LIMIT=0.5
RESOURCE_REDIS_MEMORY_LIMIT=512M

RESOURCE_NACOS_CPU_LIMIT=1.0
RESOURCE_NACOS_MEMORY_LIMIT=1.5G

RESOURCE_GATEWAY_CPU_LIMIT=0.75
RESOURCE_GATEWAY_MEMORY_LIMIT=768M

RESOURCE_SERVICE_CPU_LIMIT=0.5
RESOURCE_SERVICE_MEMORY_LIMIT=512M
```

#### docker-compose 资源配置示例

```yaml
deploy:
  resources:
    limits:
      memory: "512M"
      cpus: "0.5"
    reservations:
      memory: "256M"
      cpus: "0.25"
```

### 14.7 安全最佳实践

#### 敏感信息保护

- **禁止**将敏感配置提交到版本控制
- **必须**使用密钥管理服务（如阿里云 KMS）管理生产环境密钥
- **必须**定期轮换敏感密钥（每季度至少一次）

#### 密码复杂度要求

| 类型     | 最小长度 | 复杂度要求             |
|--------|------|-------------------|
| 数据库密码  | 16   | 大小写字母 + 数字 + 特殊字符 |
| JWT 密钥 | 32   | 随机字符串             |
| 加密密钥   | 32   | AES-256 标准        |

#### 配置验证

- CI/CD 流水线必须验证配置文件格式
- 部署前必须检查所有必需环境变量是否存在
- 敏感配置变更必须经过审批流程

---

## 十五、服务器访问信息

### 15.1 阿里云ECS服务器

| 属性          | 值                                   |
|-------------|-------------------------------------|
| **IP地址**    | 8.140.221.49                        |
| **SSH密钥文件** | `C:\Users\FZX\.ssh\FzxBdsh-ECS.pem` |
| **SSH端口**   | 22                                  |
| **登录用户**    | root                                |
| **免密码登录**   | 已配置                                 |

#### 登录命令

```bash
# Windows PowerShell
ssh -i "C:\Users\FZX\.ssh\FzxBdsh-ECS.pem" root@8.140.221.49

# Linux/Mac
ssh -i ~/.ssh/FzxBdsh-ECS.pem root@8.140.221.49
```

#### 服务访问地址

| 服务        | 地址                                      | 端口   |
|-----------|-----------------------------------------|------|
| Nexus     | http://8.140.221.49:8091                | 8091 |
| SonarQube | http://sonar-dev.fengzhongxing.com:9000 | 9000 |
| Jenkins   | http://8.140.221.49:8080                | 8080 |

---

**文档管理**

- 本文档为风七六本地生活服务平台唯一官方开发规范
- 所有开发人员必须遵守本文档中的规则
- 规则如有更新，将通过团队会议和文档版本更新同步
- 本文档包含强制性规范，违反将导致服务启动失败或安全漏洞
