fundplatform/Agents.md
zhangjf 7909daf8a4 docs: 更新架构文档,添加单机部署配置总结
- Agents.md v1.1: 新增配置文件分离架构说明
  - 统一配置 env.properties(所有服务共用)
  - 个性化配置 service.properties(每服务独立)
  - 配置加载顺序说明
  - 打包目录结构
  - 日志配置集中化
  - 多租户部署配置示例

- 单机部署文档 v2.2: 同步更新配置说明
  - 添加配置文件架构章节
  - 添加多租户部署示例
  - 更新打包结构说明
2026-02-22 16:16:53 +08:00

23 KiB
Raw Blame History

资金服务平台 (FundPlatform) - 开发规范

文档版本: v1.1
创建日期: 2026-02-20
更新日期: 2026-02-13
适用范围: 本项目所有开发人员


一、项目概述

资金服务平台是一套完整的公司项目资金管理解决方案,采用微服务架构,实现应收账款和项目支出的全流程跟踪与管理。

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

@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 必备字段

所有业务表必须包含以下审计字段:

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 多租户字段

支持多租户的表必须包含:

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> 包装:

{
    "code": 200,
    "message": "success",
    "data": { ... },
    "success": true
}

错误响应:

{
    "code": 400,
    "message": "参数错误:客户名称不能为空",
    "data": null,
    "success": false
}

5.4 分页格式

{
    "code": 200,
    "message": "success",
    "data": {
        "pageNum": 1,
        "pageSize": 10,
        "total": 100,
        "list": [ ... ]
    },
    "success": true
}

5.5 状态码规范

状态码 说明
200 成功
400 参数错误
401 未授权/Token无效
403 权限不足
404 资源不存在
500 服务器内部错误

六、多租户规范

6.1 租户ID传递

  1. 前端请求Header 传递 X-Tenant-Id
  2. GatewayTenantGatewayFilter 提取并透传
  3. 后端服务TenantContextHolder 存储到 ThreadLocal
  4. MyBatis拦截器:自动注入 tenant_id 条件

6.2 租户隔离

// 自动注入 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 租户上下文

// 获取当前租户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

// 生成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请求

@Around("execution(* com.fundplatform..controller..*(..))")
public Object logApiRequest(ProceedingJoinPoint joinPoint) {
    // 记录:请求方法、参数、响应时间、结果状态
}

十、异常处理规范

10.1 统一异常处理

@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 业务异常

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 异常使用

// 参数校验
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层

@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层

@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规范

@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

# ============================================
# 环境变量配置文件(所有服务共用)
# ============================================

# 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

# ============================================
# 服务个性化配置
# 此文件随服务打包,每个服务独立配置
# ============================================

# 服务名称
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 配置加载顺序

启动脚本按以下顺序加载配置(后加载覆盖先加载):

# 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 控制,从环境变量读取配置:

<!-- 从环境变量读取配置 -->
<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 共享实例配置

# service.properties
APP_NAME=fund-sys
INSTANCE_NAME=fund-sys
TENANT_ID=                    # 空值表示共享实例

13.4.2 VIP专属实例配置

# 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

spring:
  data:
    redis:
      host: localhost
      port: 6379
      password: zjf@123456
      database: 0

13.2 Nacos配置

spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: fund-platform
        group: DEFAULT_GROUP
        username: nacos
        password: nacos

13.3 日志配置

<!-- 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名称冲突

多模块配置类避免冲突:

// 错误:多个模块都有 RedisConfig
@Configuration
public class RedisConfig { }

// 正确:添加模块前缀
@Configuration
public class GatewayRedisConfig { }  // Gateway专用

14.2 WebFlux与Servlet冲突

Gateway作为WebFlux应用不能使用Servlet API

// 错误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包含依赖

<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 访问地址

服务 地址
管理后台 http://localhost:3000
API网关 http://localhost:8000
Nacos控制台 http://localhost:8048/nacos

15.3 默认账号

系统 用户名 密码
Nacos nacos nacos
管理后台 admin 123456

文档结束