1. 架构设计文档 v1.7 -> v1.8
新增 6.1.5 API集中管理规范:
- 目录结构示例:api/index.ts + api/request.ts + api/modules/
- api/index.ts 代码示例
- Vue组件调用示例(正确vs错误对比)
- 规范要求:禁止硬编码、统一入口、路径简化、便于维护
2. Agents.md v1.2 -> v1.3
新增 5.6 前端API集中管理规范:
- 目录结构说明
- 规范要求表格
- 正确/错误代码示例对比
规范要点:
- 采用独立目录或文件集中管理后台API请求
- Vue组件中禁止直接使用 request.get('/xxx/xxx') 硬编码URL
- 所有API函数从 @/api 统一导出,按模块分组
- API路径变更时只需修改 api/index.ts 一处
989 lines
25 KiB
Markdown
989 lines
25 KiB
Markdown
# 资金服务平台 (FundPlatform) - 开发规范
|
||
|
||
> **文档版本**: v1.3
|
||
> **创建日期**: 2026-02-20
|
||
> **更新日期**: 2026-02-23
|
||
> **适用范围**: 本项目所有开发人员
|
||
|
||
---
|
||
|
||
## 一、项目概述
|
||
|
||
资金服务平台是一套完整的公司项目资金管理解决方案,采用微服务架构,实现应收账款和项目支出的全流程跟踪与管理。
|
||
|
||
### 1.1 技术栈
|
||
|
||
| 层级 | 技术选型 |
|
||
|------|----------|
|
||
| **应用框架** | Spring Boot 3.2 + Spring Cloud Alibaba |
|
||
| **服务注册** | Nacos 3.x |
|
||
| **数据库** | MySQL 8.0 |
|
||
| **缓存** | Redis 7.x |
|
||
| **ORM框架** | MyBatis-Plus 3.5 |
|
||
| **API网关** | Spring Cloud Gateway |
|
||
| **前端框架** | Vue 3 + TypeScript + Element Plus |
|
||
| **移动端** | Vue 3 + Vite 5 + Vant 4 |
|
||
|
||
### 1.2 模块划分
|
||
|
||
| 模块 | 端口 | 说明 |
|
||
|------|------|------|
|
||
| fund-gateway | 8000 | API网关 |
|
||
| fund-sys | 8100 | 系统管理服务 |
|
||
| fund-cust | 8110 | 客户管理服务 |
|
||
| fund-proj | 8120 | 项目管理服务 |
|
||
| fund-req | 8130 | 需求工单服务 |
|
||
| fund-exp | 8140 | 支出管理服务 |
|
||
| fund-receipt | 8150 | 收款管理服务 |
|
||
| fund-file | 8600 | 文件服务 |
|
||
| fund-report | 8700 | 报表服务 |
|
||
| fund-admin | 3000 | 管理后台前端 |
|
||
| fund-mobile | - | 移动端H5 |
|
||
|
||
---
|
||
|
||
## 二、项目结构规范
|
||
|
||
### 2.1 后端模块结构
|
||
|
||
```
|
||
fund-xxx/
|
||
├── src/main/java/com/fundplatform/xxx/
|
||
│ ├── XxxApplication.java # 启动类
|
||
│ ├── config/ # 配置类
|
||
│ ├── controller/ # 控制器层
|
||
│ ├── service/ # 服务层
|
||
│ │ └── impl/ # 服务实现
|
||
│ ├── mapper/ # MyBatis Mapper
|
||
│ ├── entity/ # 实体类
|
||
│ ├── dto/ # 数据传输对象
|
||
│ ├── vo/ # 视图对象
|
||
│ └── enums/ # 枚举类
|
||
├── src/main/resources/
|
||
│ ├── application.yml # 主配置
|
||
│ ├── application-docker.yml # Docker配置
|
||
│ └── logback-spring.xml # 日志配置
|
||
└── pom.xml
|
||
```
|
||
|
||
### 2.2 公共模块 (fund-common)
|
||
|
||
```
|
||
fund-common/
|
||
├── src/main/java/com/fundplatform/common/
|
||
│ ├── auth/ # 认证相关
|
||
│ ├── cache/ # 缓存服务
|
||
│ ├── config/ # 通用配置
|
||
│ ├── context/ # 上下文管理
|
||
│ ├── core/ # 核心类(Result, PageResult等)
|
||
│ ├── exception/ # 异常处理
|
||
│ ├── feign/ # Feign拦截器
|
||
│ ├── loadbalancer/ # 负载均衡
|
||
│ ├── mybatis/ # MyBatis配置
|
||
│ ├── nacos/ # Nacos配置
|
||
│ └── web/ # Web拦截器
|
||
```
|
||
|
||
### 2.3 启动类配置
|
||
|
||
所有业务服务必须配置 `scanBasePackages`:
|
||
|
||
```java
|
||
@SpringBootApplication(scanBasePackages = {"com.fundplatform.xxx", "com.fundplatform.common"})
|
||
@EnableDiscoveryClient
|
||
public class XxxApplication {
|
||
public static void main(String[] args) {
|
||
SpringApplication.run(XxxApplication.class, args);
|
||
}
|
||
}
|
||
```
|
||
|
||
**注意**: Gateway 作为 WebFlux 应用,**不扫描** `fund-common` 的任何包,避免 Servlet 依赖冲突。
|
||
|
||
---
|
||
|
||
## 三、命名规范
|
||
|
||
### 3.1 包命名
|
||
|
||
- 全部小写
|
||
- 格式:`com.fundplatform.{模块名}.{层级}`
|
||
|
||
```
|
||
com.fundplatform.cust.controller
|
||
com.fundplatform.cust.service
|
||
com.fundplatform.cust.service.impl
|
||
com.fundplatform.cust.mapper
|
||
com.fundplatform.cust.entity
|
||
com.fundplatform.cust.dto
|
||
com.fundplatform.cust.vo
|
||
```
|
||
|
||
### 3.2 类命名
|
||
|
||
| 类型 | 命名规则 | 示例 |
|
||
|------|----------|------|
|
||
| 实体类 | 名词,PascalCase | `Customer`, `Project` |
|
||
| Controller | 名词 + Controller | `CustomerController` |
|
||
| Service接口 | 名词 + Service | `CustomerService` |
|
||
| Service实现 | 名词 + ServiceImpl | `CustomerServiceImpl` |
|
||
| Mapper | 名词 + Mapper | `CustomerMapper` |
|
||
| DTO | 动作 + 名词 + DTO | `CustomerCreateDTO`, `CustomerUpdateDTO` |
|
||
| VO | 名词 + VO | `CustomerVO`, `ProjectVO` |
|
||
| 配置类 | 功能 + Config | `RedisConfig`, `MybatisConfig` |
|
||
|
||
### 3.3 方法命名
|
||
|
||
| 操作 | Service方法 | Controller方法 |
|
||
|------|-------------|----------------|
|
||
| 创建 | `createXxx()` | `createXxx()` |
|
||
| 更新 | `updateXxx()` | `updateXxx()` |
|
||
| 删除 | `deleteXxx()` | `deleteXxx()` |
|
||
| 查询单个 | `getXxxById()` | `getXxx()` |
|
||
| 分页查询 | `pageXxxs()` | `pageXxxs()` |
|
||
| 列表查询 | `listXxxs()` | `listXxxs()` |
|
||
|
||
### 3.4 数据库命名
|
||
|
||
- 表名:小写,下划线分隔,如 `customer`, `project_member`
|
||
- 字段名:小写,下划线分隔,如 `customer_name`, `created_time`
|
||
- 索引名:`idx_表名_字段名`,如 `idx_customer_status`
|
||
- 主键:`表名_id`,如 `customer_id`
|
||
|
||
---
|
||
|
||
## 四、数据库设计规范
|
||
|
||
### 4.1 必备字段
|
||
|
||
所有业务表必须包含以下审计字段:
|
||
|
||
```sql
|
||
created_by BIGINT NOT NULL COMMENT '创建人ID',
|
||
created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
updated_by BIGINT NOT NULL COMMENT '更新人ID',
|
||
updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0-未删除,1-已删除)'
|
||
```
|
||
|
||
### 4.2 多租户字段
|
||
|
||
支持多租户的表必须包含:
|
||
|
||
```sql
|
||
tenant_id BIGINT NOT NULL DEFAULT 1 COMMENT '租户ID'
|
||
```
|
||
|
||
### 4.3 主键策略
|
||
|
||
- 使用雪花算法(Snowflake)生成分布式ID
|
||
- MyBatis-Plus配置:`@TableId(type = IdType.ASSIGN_ID)`
|
||
|
||
### 4.4 逻辑删除
|
||
|
||
- 统一使用 `deleted` 字段
|
||
- 0 = 未删除,1 = 已删除
|
||
- MyBatis-Plus配置:`@TableLogic`
|
||
|
||
---
|
||
|
||
## 五、API设计规范
|
||
|
||
### 5.1 URL规范
|
||
|
||
```
|
||
# 基础格式
|
||
/{模块}/api/v1/{资源}/{动作}
|
||
|
||
# 示例
|
||
POST /sys/api/v1/auth/login # 登录
|
||
GET /cust/api/v1/customer/{id} # 查询客户
|
||
POST /cust/api/v1/customer # 创建客户
|
||
PUT /cust/api/v1/customer/{id} # 更新客户
|
||
DELETE /cust/api/v1/customer/{id} # 删除客户
|
||
GET /cust/api/v1/customer/page # 分页查询
|
||
```
|
||
|
||
### 5.2 HTTP方法
|
||
|
||
| 方法 | 用途 | 示例 |
|
||
|------|------|------|
|
||
| GET | 查询 | 查询客户列表、详情 |
|
||
| POST | 创建 | 新增客户 |
|
||
| PUT | 更新 | 修改客户信息 |
|
||
| DELETE | 删除 | 删除客户 |
|
||
|
||
### 5.3 响应格式
|
||
|
||
统一使用 `Result<T>` 包装:
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": { ... },
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
错误响应:
|
||
|
||
```json
|
||
{
|
||
"code": 400,
|
||
"message": "参数错误:客户名称不能为空",
|
||
"data": null,
|
||
"success": false
|
||
}
|
||
```
|
||
|
||
### 5.4 分页格式
|
||
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"message": "success",
|
||
"data": {
|
||
"pageNum": 1,
|
||
"pageSize": 10,
|
||
"total": 100,
|
||
"list": [ ... ]
|
||
},
|
||
"success": true
|
||
}
|
||
```
|
||
|
||
### 5.5 状态码规范
|
||
|
||
| 状态码 | 说明 |
|
||
|--------|------|
|
||
| 200 | 成功 |
|
||
| 400 | 参数错误 |
|
||
| 401 | 未授权/Token无效 |
|
||
| 403 | 权限不足 |
|
||
| 404 | 资源不存在 |
|
||
| 500 | 服务器内部错误 |
|
||
|
||
### 5.6 前端API集中管理规范
|
||
|
||
前端项目必须采用**独立目录或文件集中管理**对后台API的请求,便于调整和优化。
|
||
|
||
**目录结构**:
|
||
|
||
```
|
||
fund-admin/src/api/ 或 fund-mobile/src/api/
|
||
├── index.ts # API集中定义入口,统一导出
|
||
├── request.ts # Axios实例配置、拦截器
|
||
└── modules/ # 按业务模块拆分(可选)
|
||
├── auth.ts # 用户认证API
|
||
├── customer.ts # 客户管理API
|
||
└── expense.ts # 支出管理API
|
||
```
|
||
|
||
**规范要求**:
|
||
|
||
| 要求 | 说明 |
|
||
|------|------|
|
||
| 禁止硬编码 | Vue组件中禁止直接使用 `request.get('/xxx/xxx')` 形式 |
|
||
| 统一入口 | 所有API函数从 `@/api` 统一导出,按模块分组 |
|
||
| 路径简化 | API函数内部使用简化路径,由 baseURL 统一添加前缀 |
|
||
| 便于维护 | 后端接口变更时,只需修改 api/index.ts 一处 |
|
||
|
||
**正确示例**:
|
||
|
||
```typescript
|
||
// api/index.ts - 集中定义
|
||
export function getReceivableList(params: { pageNum: number; pageSize: number }) {
|
||
return request.get('/receipt/receivable/page', { params })
|
||
}
|
||
|
||
// Vue组件 - 使用集中定义
|
||
import { getReceivableList } from '@/api'
|
||
const res = await getReceivableList({ pageNum: 1, pageSize: 10 })
|
||
```
|
||
|
||
**错误示例**:
|
||
|
||
```typescript
|
||
// Vue组件 - 硬编码URL(禁止)
|
||
import request from '@/api/request'
|
||
const res = await request.get('/receipt/api/v1/receipt/receivable/page')
|
||
```
|
||
|
||
---
|
||
|
||
## 六、多租户规范
|
||
|
||
### 6.1 租户ID传递
|
||
|
||
1. **前端请求**:Header 传递 `X-Tenant-Id`
|
||
2. **Gateway**:`TenantGatewayFilter` 提取并透传
|
||
3. **后端服务**:`TenantContextHolder` 存储到 ThreadLocal
|
||
4. **MyBatis拦截器**:自动注入 `tenant_id` 条件
|
||
|
||
### 6.2 租户隔离
|
||
|
||
```java
|
||
// 自动注入 tenant_id
|
||
@TableField(fill = FieldFill.INSERT)
|
||
private Long tenantId;
|
||
|
||
// MyBatis-Plus 元数据填充
|
||
public class TenantMetaObjectHandler implements MetaObjectHandler {
|
||
@Override
|
||
public void insertFill(MetaObject metaObject) {
|
||
this.strictInsertFill(metaObject, "tenantId", Long.class,
|
||
TenantContextHolder.getTenantId());
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.3 租户上下文
|
||
|
||
```java
|
||
// 获取当前租户ID
|
||
Long tenantId = TenantContextHolder.getTenantId();
|
||
|
||
// 设置租户ID(通常由拦截器自动设置)
|
||
TenantContextHolder.setTenantId(tenantId);
|
||
|
||
// 清除上下文(请求结束时)
|
||
TenantContextHolder.clear();
|
||
```
|
||
|
||
---
|
||
|
||
## 七、链路追踪规范
|
||
|
||
### 7.1 TraceId 和 SpanId
|
||
|
||
- **TraceId**:全链路唯一标识,32位UUID
|
||
- **SpanId**:服务节点标识,16位UUID
|
||
|
||
### 7.2 日志格式
|
||
|
||
```
|
||
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId:-}][%X{spanId:-}] %-5level %logger{50} - %msg%n
|
||
```
|
||
|
||
日志示例:
|
||
```
|
||
2026-02-20 18:10:25.240 [http-nio-8100-exec-1] [a1b2c3d4e5f6...][1234567890abcdef] INFO c.f.c.controller.CustomerController - 查询客户列表
|
||
```
|
||
|
||
### 7.3 HTTP Header 透传
|
||
|
||
| Header | 说明 |
|
||
|--------|------|
|
||
| `X-Trace-Id` | 全链路追踪ID |
|
||
| `X-Span-Id` | 当前服务SpanID |
|
||
| `X-Source-Service` | 来源服务名 |
|
||
| `X-Request-Time` | 请求发起时间戳 |
|
||
| `X-Tenant-Id` | 租户ID |
|
||
| `X-User-Id` | 用户ID |
|
||
| `X-Username` | 用户名 |
|
||
|
||
### 7.4 响应头返回
|
||
|
||
API响应必须返回追踪信息:
|
||
|
||
```
|
||
X-Trace-Id: a1b2c3d4e5f67890a1b2c3d4e5f67890
|
||
X-Span-Id: 1234567890abcdef
|
||
```
|
||
|
||
---
|
||
|
||
## 八、Token认证规范
|
||
|
||
### 8.1 Token机制
|
||
|
||
采用 **UUID + Redis** 方案(非JWT):
|
||
|
||
```java
|
||
// 生成Token
|
||
String token = tokenService.generateToken(userId, username, tenantId);
|
||
|
||
// Token存储到Redis
|
||
Key: auth:token:{token}
|
||
Value: TokenInfo(userId, username, tenantId, expireTime)
|
||
TTL: 24小时
|
||
```
|
||
|
||
### 8.2 请求认证
|
||
|
||
```
|
||
Authorization: Bearer {token}
|
||
```
|
||
|
||
### 8.3 白名单路径
|
||
|
||
以下路径无需Token验证:
|
||
|
||
```
|
||
/sys/api/v1/auth/login
|
||
/sys/api/v1/sys/health
|
||
```
|
||
|
||
---
|
||
|
||
## 九、日志规范
|
||
|
||
### 9.1 日志级别
|
||
|
||
| 级别 | 使用场景 |
|
||
|------|----------|
|
||
| ERROR | 异常、错误、需要立即处理的问题 |
|
||
| WARN | 警告、潜在问题 |
|
||
| INFO | 关键业务流程、重要操作 |
|
||
| DEBUG | 调试信息、详细流程 |
|
||
|
||
### 9.2 日志文件
|
||
|
||
```
|
||
logs/
|
||
├── fund-xxx.log # 主日志
|
||
├── fund-xxx/
|
||
│ ├── info.log # INFO级别日志
|
||
│ ├── error.log # ERROR级别日志
|
||
│ └── aop.log # API请求日志
|
||
```
|
||
|
||
### 9.3 API请求日志
|
||
|
||
通过AOP记录所有API请求:
|
||
|
||
```java
|
||
@Around("execution(* com.fundplatform..controller..*(..))")
|
||
public Object logApiRequest(ProceedingJoinPoint joinPoint) {
|
||
// 记录:请求方法、参数、响应时间、结果状态
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 十、异常处理规范
|
||
|
||
### 10.1 统一异常处理
|
||
|
||
```java
|
||
@RestControllerAdvice
|
||
public class GlobalExceptionHandler {
|
||
|
||
@ExceptionHandler(BusinessException.class)
|
||
public Result<Void> handleBusinessException(BusinessException e) {
|
||
return Result.error(e.getCode(), e.getMessage());
|
||
}
|
||
|
||
@ExceptionHandler(Exception.class)
|
||
public Result<Void> handleException(Exception e) {
|
||
log.error("系统异常", e);
|
||
return Result.error(500, "系统异常,请稍后重试");
|
||
}
|
||
}
|
||
```
|
||
|
||
### 10.2 业务异常
|
||
|
||
```java
|
||
public class BusinessException extends RuntimeException {
|
||
private final int code;
|
||
|
||
public BusinessException(String message) {
|
||
super(message);
|
||
this.code = 400;
|
||
}
|
||
|
||
public BusinessException(int code, String message) {
|
||
super(message);
|
||
this.code = code;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 10.3 异常使用
|
||
|
||
```java
|
||
// 参数校验
|
||
if (customerName == null || customerName.isEmpty()) {
|
||
throw new BusinessException("客户名称不能为空");
|
||
}
|
||
|
||
// 业务校验
|
||
Customer customer = customerMapper.selectById(id);
|
||
if (customer == null) {
|
||
throw new BusinessException(404, "客户不存在");
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 十一、Git提交规范
|
||
|
||
### 11.1 分支命名
|
||
|
||
```
|
||
master # 主分支
|
||
develop # 开发分支
|
||
feature/xxx # 功能分支
|
||
bugfix/xxx # Bug修复分支
|
||
hotfix/xxx # 紧急修复分支
|
||
```
|
||
|
||
### 11.2 提交信息格式
|
||
|
||
```
|
||
<type>: <subject>
|
||
|
||
<body>
|
||
```
|
||
|
||
**type 类型**:
|
||
|
||
| 类型 | 说明 |
|
||
|------|------|
|
||
| feat | 新功能 |
|
||
| fix | Bug修复 |
|
||
| docs | 文档更新 |
|
||
| style | 代码格式调整 |
|
||
| refactor | 重构 |
|
||
| test | 测试相关 |
|
||
| chore | 构建/工具相关 |
|
||
|
||
**示例**:
|
||
|
||
```
|
||
feat: 新增客户管理分页查询接口
|
||
|
||
- 支持按客户名称模糊查询
|
||
- 支持按状态筛选
|
||
- 分页参数校验
|
||
```
|
||
|
||
```
|
||
fix: 修复Gateway路由配置错误
|
||
|
||
fund-cust 路由路径配置错误,修正为 /cust/**
|
||
```
|
||
|
||
---
|
||
|
||
## 十二、代码规范
|
||
|
||
### 12.1 Controller层
|
||
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/api/v1/customer")
|
||
@RequiredArgsConstructor
|
||
public class CustomerController {
|
||
|
||
private final CustomerService customerService;
|
||
|
||
@PostMapping
|
||
public Result<Long> createCustomer(@Valid @RequestBody CustomerCreateDTO dto) {
|
||
Long id = customerService.createCustomer(dto);
|
||
return Result.success(id);
|
||
}
|
||
|
||
@GetMapping("/page")
|
||
public Result<PageResult<CustomerVO>> pageCustomers(
|
||
@RequestParam(defaultValue = "1") int pageNum,
|
||
@RequestParam(defaultValue = "10") int pageSize,
|
||
@RequestParam(required = false) String keyword) {
|
||
Page<CustomerVO> page = customerService.pageCustomers(pageNum, pageSize, keyword);
|
||
return Result.success(PageResult.of(page));
|
||
}
|
||
}
|
||
```
|
||
|
||
### 12.2 Service层
|
||
|
||
```java
|
||
@Service
|
||
@RequiredArgsConstructor
|
||
public class CustomerServiceImpl implements CustomerService {
|
||
|
||
private final CustomerMapper customerMapper;
|
||
|
||
@Override
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Long createCustomer(CustomerCreateDTO dto) {
|
||
// 1. 参数校验
|
||
// 2. 业务逻辑
|
||
// 3. 数据持久化
|
||
// 4. 返回结果
|
||
}
|
||
}
|
||
```
|
||
|
||
### 12.3 DTO/VO规范
|
||
|
||
```java
|
||
@Data
|
||
public class CustomerCreateDTO {
|
||
|
||
@NotBlank(message = "客户名称不能为空")
|
||
@Size(max = 200, message = "客户名称最长200字符")
|
||
private String customerName;
|
||
|
||
@NotBlank(message = "联系人不能为空")
|
||
private String contact;
|
||
|
||
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
|
||
private String phone;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 十三、配置规范
|
||
|
||
### 13.1 配置文件分离架构
|
||
|
||
项目采用**统一配置 + 个性化配置**分离架构:
|
||
|
||
```
|
||
fundplatform/
|
||
├── scripts/
|
||
│ └── env.properties # 统一配置(所有服务共用)
|
||
├── fund-sys/src/main/resources/
|
||
│ └── service.properties # 个性化配置(每服务独立)
|
||
├── fund-gateway/src/main/resources/
|
||
│ └── service.properties
|
||
└── ...其他服务
|
||
```
|
||
|
||
#### 13.1.1 统一配置 (env.properties)
|
||
|
||
**位置**: `scripts/env.properties`
|
||
**用途**: 所有服务共用的公共配置
|
||
**打包后**: `conf/env.properties`
|
||
|
||
```properties
|
||
# ============================================
|
||
# 环境变量配置文件(所有服务共用)
|
||
# ============================================
|
||
|
||
# Nacos配置
|
||
NACOS_SERVER_ADDR=localhost:8848
|
||
NACOS_NAMESPACE=fund-platform
|
||
NACOS_GROUP=DEFAULT_GROUP
|
||
NACOS_USERNAME=nacos
|
||
NACOS_PASSWORD=nacos
|
||
|
||
# Redis配置
|
||
REDIS_HOST=localhost
|
||
REDIS_PORT=6379
|
||
REDIS_PASSWORD=zjf@123456
|
||
REDIS_DATABASE=0
|
||
REDIS_TIMEOUT=10000
|
||
REDIS_POOL_MAX_ACTIVE=8
|
||
REDIS_POOL_MAX_WAIT=-1
|
||
REDIS_POOL_MAX_IDLE=8
|
||
REDIS_POOL_MIN_IDLE=0
|
||
|
||
# Hikari连接池配置
|
||
HIKARI_MINIMUM_IDLE=5
|
||
HIKARI_CONNECTION_TIMEOUT=30000
|
||
|
||
# Sentinel配置(Gateway使用)
|
||
SENTINEL_DASHBOARD=localhost:8080
|
||
SENTINEL_PORT=8719
|
||
|
||
# 网关限流配置
|
||
GATEWAY_RATE_LIMIT_REPLENISH_RATE=100
|
||
GATEWAY_RATE_LIMIT_BURST_CAPACITY=200
|
||
|
||
# 腾讯云COS配置(文件服务使用)
|
||
COS_ENABLED=true
|
||
COS_SECRET_ID=your-secret-id
|
||
COS_SECRET_KEY=your-secret-key
|
||
COS_BUCKET=your-bucket
|
||
COS_REGION=ap-beijing
|
||
|
||
# 文件上传配置
|
||
FILE_UPLOAD_MAX_SIZE=50MB
|
||
FILE_UPLOAD_MAX_REQUEST_SIZE=100MB
|
||
FILE_STORAGE_PATH=./uploads
|
||
|
||
# 日志配置
|
||
LOG_PATH=/datacfs/applogs
|
||
LOG_LEVEL_ROOT=INFO
|
||
LOG_LEVEL_APP=DEBUG
|
||
LOG_PATTERN=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId:-}][%X{spanId:-}] %-5level %logger{50} - %msg%n
|
||
|
||
# 多租户路由配置
|
||
TENANT_ROUTING_ENABLED=true
|
||
TENANT_HEADER=X-Tenant-Id
|
||
DEFAULT_TENANT_ID=1
|
||
```
|
||
|
||
#### 13.1.2 个性化配置 (service.properties)
|
||
|
||
**位置**: 各服务 `src/main/resources/service.properties`
|
||
**用途**: 服务独立的个性化配置
|
||
**打包后**: `conf/service.properties`
|
||
|
||
```properties
|
||
# ============================================
|
||
# 服务个性化配置
|
||
# 此文件随服务打包,每个服务独立配置
|
||
# ============================================
|
||
|
||
# 服务名称
|
||
APP_NAME=fund-sys
|
||
|
||
# 实例名称(多租户场景使用,默认与APP_NAME相同)
|
||
# 多租户示例:fund-sys-shared, fund-sys-vip001
|
||
INSTANCE_NAME=${APP_NAME}
|
||
|
||
# 租户标识(多租户场景使用,用于Nacos元数据路由)
|
||
# 空值=共享实例,有值=VIP专属实例
|
||
TENANT_ID=
|
||
|
||
# 服务端口(可覆盖application.yml中的配置)
|
||
# SERVER_PORT=8100
|
||
```
|
||
|
||
#### 13.1.3 配置加载顺序
|
||
|
||
启动脚本按以下顺序加载配置(后加载覆盖先加载):
|
||
|
||
```bash
|
||
# 1. 加载统一配置
|
||
load_properties "${APP_HOME}/conf/env.properties"
|
||
|
||
# 2. 加载个性化配置(覆盖同名参数)
|
||
load_properties "${APP_HOME}/conf/service.properties"
|
||
```
|
||
|
||
### 13.2 打包目录结构
|
||
|
||
使用Maven Assembly打包后的目录结构:
|
||
|
||
```
|
||
fund-sys/ # 服务根目录
|
||
├── bin/ # 脚本目录
|
||
│ ├── start.sh # 启动脚本
|
||
│ ├── stop.sh # 停止脚本
|
||
│ ├── restart.sh # 重启脚本
|
||
│ └── status.sh # 状态查看脚本
|
||
├── lib/ # 依赖JAR目录
|
||
│ └── fund-sys.jar # 服务JAR包
|
||
└── conf/ # 配置文件目录
|
||
├── env.properties # 统一配置
|
||
├── service.properties # 个性化配置
|
||
├── application.yml # 主配置
|
||
├── bootstrap.yml # 启动配置
|
||
└── logback-spring.xml # 日志配置
|
||
```
|
||
|
||
### 13.3 日志配置集中化
|
||
|
||
日志管理统一由 `logback-spring.xml` 控制,从环境变量读取配置:
|
||
|
||
```xml
|
||
<!-- 从环境变量读取配置 -->
|
||
<springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
|
||
<springProperty scope="context" name="LOG_PATH" source="logging.file.path" defaultValue="/datacfs/applogs"/>
|
||
<springProperty scope="context" name="LOG_LEVEL_ROOT" source="logging.level.root" defaultValue="INFO"/>
|
||
<springProperty scope="context" name="LOG_LEVEL_APP" source="logging.level.app" defaultValue="DEBUG"/>
|
||
|
||
<!-- 日志文件路径 -->
|
||
<property name="LOG_FILE" value="${LOG_PATH}/${APP_NAME}"/>
|
||
```
|
||
|
||
**application.yml 中不再配置 logging 节点**,完全由 logback-spring.xml 管理。
|
||
|
||
### 13.4 多租户部署配置
|
||
|
||
#### 13.4.1 共享实例配置
|
||
|
||
```properties
|
||
# service.properties
|
||
APP_NAME=fund-sys
|
||
INSTANCE_NAME=fund-sys
|
||
TENANT_ID= # 空值表示共享实例
|
||
```
|
||
|
||
#### 13.4.2 VIP专属实例配置
|
||
|
||
```properties
|
||
# service.properties
|
||
APP_NAME=fund-sys
|
||
INSTANCE_NAME=fund-sys-vip001 # 实例名称带租户标识
|
||
TENANT_ID=vip001 # 租户ID用于Nacos路由
|
||
```
|
||
|
||
#### 13.4.3 多实例部署目录
|
||
|
||
```
|
||
/opt/fundplatform/deploy/
|
||
├── fund-sys/ # 共享实例
|
||
│ ├── bin/
|
||
│ ├── lib/
|
||
│ └── conf/
|
||
│ └── service.properties # INSTANCE_NAME=fund-sys, TENANT_ID=
|
||
├── fund-sys-vip001/ # VIP实例1
|
||
│ ├── bin/
|
||
│ ├── lib/
|
||
│ └── conf/
|
||
│ └── service.properties # INSTANCE_NAME=fund-sys-vip001, TENANT_ID=vip001
|
||
└── fund-sys-vip002/ # VIP实例2
|
||
└── ...
|
||
```
|
||
|
||
### 13.5 Redis配置
|
||
|
||
所有服务统一使用 **database 0**:
|
||
|
||
```yaml
|
||
spring:
|
||
data:
|
||
redis:
|
||
host: localhost
|
||
port: 6379
|
||
password: zjf@123456
|
||
database: 0
|
||
```
|
||
|
||
### 13.2 Nacos配置
|
||
|
||
```yaml
|
||
spring:
|
||
cloud:
|
||
nacos:
|
||
discovery:
|
||
server-addr: localhost:8848
|
||
namespace: fund-platform
|
||
group: DEFAULT_GROUP
|
||
username: nacos
|
||
password: nacos
|
||
```
|
||
|
||
### 13.3 日志配置
|
||
|
||
```xml
|
||
<!-- logback-spring.xml -->
|
||
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId:-}][%X{spanId:-}] %-5level %logger{50} - %msg%n"/>
|
||
|
||
<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||
<file>./logs/${APP_NAME}/info.log</file>
|
||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||
<fileNamePattern>./logs/${APP_NAME}/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||
<maxFileSize>100MB</maxFileSize>
|
||
<maxHistory>30</maxHistory>
|
||
</rollingPolicy>
|
||
</appender>
|
||
```
|
||
|
||
---
|
||
|
||
## 十四、常见问题处理
|
||
|
||
### 14.1 Bean名称冲突
|
||
|
||
多模块配置类避免冲突:
|
||
|
||
```java
|
||
// 错误:多个模块都有 RedisConfig
|
||
@Configuration
|
||
public class RedisConfig { }
|
||
|
||
// 正确:添加模块前缀
|
||
@Configuration
|
||
public class GatewayRedisConfig { } // Gateway专用
|
||
```
|
||
|
||
### 14.2 WebFlux与Servlet冲突
|
||
|
||
Gateway作为WebFlux应用,不能使用Servlet API:
|
||
|
||
```java
|
||
// 错误:Gateway中使用Servlet API
|
||
public class TokenAuthFilter implements Filter {
|
||
public void doFilter(ServletRequest request, ServletResponse response) { }
|
||
}
|
||
|
||
// 正确:Gateway使用WebFlux
|
||
public class TokenAuthFilter implements GlobalFilter {
|
||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { }
|
||
}
|
||
```
|
||
|
||
### 14.3 Nacos服务发现失败
|
||
|
||
确保pom.xml包含依赖:
|
||
|
||
```xml
|
||
<dependency>
|
||
<groupId>com.alibaba.cloud</groupId>
|
||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||
</dependency>
|
||
```
|
||
|
||
---
|
||
|
||
## 十五、附录
|
||
|
||
### 15.1 环境变量汇总
|
||
|
||
#### 统一配置变量 (env.properties)
|
||
|
||
| 变量名 | 说明 | 默认值 |
|
||
|--------|------|--------|
|
||
| `NACOS_SERVER_ADDR` | Nacos服务地址 | localhost:8848 |
|
||
| `NACOS_NAMESPACE` | Nacos命名空间 | fund-platform |
|
||
| `NACOS_GROUP` | Nacos分组 | DEFAULT_GROUP |
|
||
| `NACOS_USERNAME` | Nacos用户名 | nacos |
|
||
| `NACOS_PASSWORD` | Nacos密码 | nacos |
|
||
| `REDIS_HOST` | Redis地址 | localhost |
|
||
| `REDIS_PORT` | Redis端口 | 6379 |
|
||
| `REDIS_PASSWORD` | Redis密码 | zjf@123456 |
|
||
| `REDIS_DATABASE` | Redis数据库 | 0 |
|
||
| `LOG_PATH` | 日志路径 | /datacfs/applogs |
|
||
| `LOG_LEVEL_ROOT` | 根日志级别 | INFO |
|
||
| `LOG_LEVEL_APP` | 应用日志级别 | DEBUG |
|
||
| `TENANT_ROUTING_ENABLED` | 多租户路由开关 | true |
|
||
| `DEFAULT_TENANT_ID` | 默认租户ID | 1 |
|
||
|
||
#### 个性化配置变量 (service.properties)
|
||
|
||
| 变量名 | 说明 | 备注 |
|
||
|--------|------|--------|
|
||
| `APP_NAME` | 服务名称 | 对应JAR文件名 |
|
||
| `INSTANCE_NAME` | 实例名称 | 多租户场景区分实例 |
|
||
| `TENANT_ID` | 租户标识 | 空值=共享实例,有值=VIP实例 |
|
||
| `SERVER_PORT` | 服务端口 | 可选,覆盖application.yml |
|
||
|
||
### 15.2 前端部署路径
|
||
|
||
前端项目采用 **Nginx 子路径部署** 模式:
|
||
|
||
| 前端项目 | 部署路径 | 访问地址 | 说明 |
|
||
|----------|----------|----------|------|
|
||
| fund-admin | `/fadmin/` | `http://host/fadmin/` | 管理后台 |
|
||
| fund-mobile | `/fmobile/` | `http://host/fmobile/` | 移动端H5 |
|
||
| API网关 | `/fund/` | `http://host/fund/` | 后端API统一前缀 |
|
||
|
||
**开发环境访问地址**:
|
||
|
||
| 服务 | 地址 |
|
||
|------|------|
|
||
| 管理后台 | http://localhost:3000 |
|
||
| 移动端H5 | http://localhost:8080 |
|
||
| API网关 | http://localhost:8000 |
|
||
| Nacos控制台 | http://localhost:8048/nacos |
|
||
|
||
### 15.3 默认账号
|
||
|
||
| 系统 | 用户名 | 密码 |
|
||
|------|--------|------|
|
||
| Nacos | nacos | nacos |
|
||
| 管理后台 | admin | 123456 |
|
||
|
||
---
|
||
|
||
**文档结束**
|