Files
workspace/code/fms/.qoder/repowiki/zh/content/后端架构/后端架构.md
T
2026-08-23 21:02:41 +08:00

17 KiB
Raw Blame History

后端架构

**本文引用的文件** - [FmsApiApplication.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/FmsApiApplication.java) - [pom.xml](file://fms-api/pom.xml) - [application.yaml](file://fms-api/src/main/resources/application.yaml) - [JwtAuthFilter.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/JwtAuthFilter.java) - [OrgContext.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/database/OrgContext.java) - [OrgRoutingDataSource.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/database/OrgRoutingDataSource.java) - [OrgDataSourceManager.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/database/OrgDataSourceManager.java) - [AuthController.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/AuthController.java) - [DataService.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/DataService.java) - [DataController.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/DataController.java) - [GlobalExceptionHandler.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/exception/GlobalExceptionHandler.java)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本技术文档聚焦 FMS 后端服务(基于 Spring Boot)的架构设计与实现,覆盖分层架构、模块化组织与依赖注入;元数据驱动的数据访问层(动态 SQL、表结构映射、CRUD 自动化);多租户数据隔离(数据库连接池与租户上下文切换);RESTful API 规范(统一响应、错误处理、版本管理);以及部署配置与监控方案。目标是帮助读者快速理解系统整体设计并高效定位问题。

项目结构

后端采用典型的 Spring Boot Web MVC 分层:

  • 启动与装配:应用入口负责初始化全局能力(如分布式 ID),并通过注解扫描装配 Bean。
  • 配置中心:集中化配置服务器端口、上下文路径、认证参数、数据库连接池与文件存储策略。
  • 控制器层:对外暴露 REST 接口,统一封装响应体。
  • 服务层:业务编排与事务边界,调用数据访问工具与外部能力。
  • 数据访问层:以元数据驱动的通用查询/分页/保存能力为核心,结合多租户路由数据源。
  • 安全与异常:JWT 鉴权过滤器、全局异常处理器、会话注册表等横切能力。
graph TB
A["Spring Boot 应用<br/>FmsApiApplication"] --> B["Web 层<br/>Controllers"]
B --> C["服务层<br/>Services"]
C --> D["数据访问层<br/>DbUtils / DataService"]
D --> E["多租户数据源路由<br/>OrgRoutingDataSource"]
E --> F["连接池管理<br/>OrgDataSourceManager"]
B --> G["安全过滤链<br/>JwtAuthFilter"]
B --> H["全局异常处理<br/>GlobalExceptionHandler"]

图表来源

章节来源

核心组件

  • 应用启动器:初始化雪花 ID 生成器,启动 Spring 容器。
  • 配置属性:通过 application.yaml 集中管理服务器、认证、数据库连接池、文件存储等。
  • 安全过滤器:解析 JWT、校验会话活性、设置租户上下文(orgId/userId)。
  • 多租户数据源:基于 ThreadLocal 的租户上下文 + 路由数据源 + Druid 连接池管理。
  • 数据服务:提供描述表结构、按视图加载数据、分页、自定义 SQL 执行、对象保存与编码生成等。
  • 控制器:统一 REST 接口,返回 ApiResponse 标准格式。
  • 全局异常:统一捕获业务异常、认证异常、数据库异常,输出一致的错误响应。

章节来源

架构总览

下图展示了请求从进入 Web 层到数据访问的多租户路由流程,以及统一的响应与异常处理机制。

sequenceDiagram
participant Client as "客户端"
participant Filter as "JwtAuthFilter"
participant Controller as "DataController"
participant Service as "DataService"
participant RDS as "OrgRoutingDataSource"
participant Manager as "OrgDataSourceManager"
participant DB as "数据库"
Client->>Filter : "HTTP 请求(携带 Authorization)"
Filter->>Filter : "解析JWT/校验会话/设置租户上下文"
Filter-->>Client : "未授权时直接返回统一错误"
Filter->>Controller : "放行请求"
Controller->>Service : "调用数据接口(分页/加载/保存)"
Service->>RDS : "获取连接"
RDS->>Manager : "根据租户ID选择数据源"
Manager->>DB : "执行SQL"
DB-->>Manager : "结果集"
Manager-->>RDS : "连接"
RDS-->>Service : "Connection"
Service-->>Controller : "业务结果"
Controller-->>Client : "ApiResponse 统一响应"

图表来源

详细组件分析

认证与安全过滤

  • 职责:拦截除登录外的所有请求,解析 JWT,校验会话是否活跃且未被顶号,设置租户上下文后放行。
  • 关键点:
    • 白名单:OPTIONS 预检与登录接口不拦截。
    • 会话管理:通过会话注册表检查当前会话有效性。
    • 上下文传播:将 orgId、userId 写入线程局部变量,供后续数据源路由使用。
    • 统一失败响应:未登录或会话失效时返回统一错误码与消息。
flowchart TD
Start(["进入过滤器"]) --> CheckMethod{"方法为 OPTIONS 或登录?"}
CheckMethod --> |是| Pass["放行"]
CheckMethod --> |否| ParseToken["解析Authorization头并解析JWT"]
ParseToken --> Valid{"令牌有效?"}
Valid --> |否| AuthFail["返回未登录/失效错误"]
Valid --> |是| CheckSession["检查会话是否活跃且未被顶号"]
CheckSession --> Active{"会话有效?"}
Active --> |否| SessionFail["返回被顶号/失效错误"]
Active --> |是| SetCtx["设置租户上下文(orgId, userId)"]
SetCtx --> Next["继续过滤器链"]
Next --> End(["结束"])

图表来源

章节来源

多租户数据隔离

  • 上下文:使用 ThreadLocal 维护当前请求的 orgId 与 userId,确保线程内一致性。
  • 路由数据源:继承 AbstractDataSource,根据上下文选择具体租户的数据源。
  • 连接池管理:按租户维度缓存 Druid 连接池,懒创建、按需关闭,支持统计数量与优雅销毁。
  • 配置:通过配置文件指定连接池参数(初始大小、最小空闲、最大活跃、等待超时、健康检查等)。
classDiagram
class OrgContext {
+setOrgId(id)
+getOrgId() String
+requireOrgId() String
+setUserId(id)
+getUserId() String
+requireUserId() String
+clear()
}
class OrgRoutingDataSource {
+getConnection() Connection
+getConnection(username,password) Connection
}
class OrgDataSourceManager {
+getDataSource(orgId) DruidDataSource
+getConnection(orgId) Connection
+getConnection() Connection
+closeDataSource(orgId) boolean
+getDataSourceCount() int
+closeAll() void
}
OrgRoutingDataSource --> OrgDataSourceManager : "委托选择数据源"
OrgRoutingDataSource --> OrgContext : "读取租户ID"

图表来源

章节来源

元数据驱动的数据访问层

  • 表结构描述:通过 describe 接口获取视图/表的列信息,用于前端表单与表格的动态渲染。
  • 动态查询:loadData 支持按视图名、搜索条件、排序字段与搜索列进行查询。
  • 自定义 SQL:loadDataBySql 允许传入 SQL 字符串执行查询,便于复杂场景。
  • 分页:page 接口封装分页参数,返回行集合、总数、页码与页大小。
  • 保存与编码:saveobjt 批量保存对象;nextid/nextcode 提供主键与业务编码生成能力。
flowchart TD
In(["接收参数"]) --> Validate{"必需参数存在?"}
Validate --> |否| Err["抛出业务异常"]
Validate --> |是| Mode{"操作类型"}
Mode --> |describe| Describe["获取列元数据"]
Mode --> |loaddata| Load["按视图+条件+排序加载"]
Mode --> |loaddatabysql| Exec["执行自定义SQL"]
Mode --> |page| Page["分页查询"]
Mode --> |saveobjt| Save["批量保存对象"]
Mode --> |nextid| GenId["生成主键ID"]
Mode --> |nextcode| GenCode["生成业务编码"]
Describe --> Out["返回统一响应"]
Load --> Out
Exec --> Out
Page --> Out
Save --> Out
GenId --> Out
GenCode --> Out

图表来源

章节来源

RESTful API 设计规范

  • 统一响应:所有接口返回 ApiResponse 包装体,包含状态码、消息与数据体。
  • 错误处理:全局异常处理器统一捕获业务、认证、数据库异常,输出一致的错误格式。
  • 版本管理:当前未见显式版本前缀,建议未来在 URL 中引入版本段(如 /api/v1/...)或通过 Accept 头控制。
  • 典型接口:
    • 认证:POST /api/auth/login
    • 数据:POST /api/data/{loaddata|loaddatabysql|page|saveobjt|nextid|nextcode|describe}

章节来源

依赖注入与模块化组织

  • 依赖注入:通过 @Resource 注入 JwtUtils、ActiveSessionRegistry、DbUtils、DataSource 等组件,解耦具体实现。
  • 模块化:按功能划分 config、controller、service、database、exception、utils 包,职责清晰。
  • 配置扫描:启动类启用配置属性扫描,便于外部化配置绑定。

章节来源

依赖关系分析

  • 框架与中间件:Spring Boot WebMVC、JDBC、Druid 连接池、JWT 库、Jackson、SQL Server JDBC。
  • 关键耦合点:
    • 过滤器依赖会话注册表与 JWT 工具。
    • 数据服务依赖 DbUtils 与 DataSource。
    • 多租户路由数据源依赖连接池管理器与租户上下文。
  • 潜在循环依赖:未发现明显循环引用;各层单向依赖清晰。
graph LR
App["FmsApiApplication"] --> Web["Spring Web MVC"]
Web --> Filter["JwtAuthFilter"]
Web --> Ctrl["Controllers"]
Ctrl --> Svc["Services"]
Svc --> DBU["DbUtils"]
Svc --> DS["DataSource"]
DS --> RDS["OrgRoutingDataSource"]
RDS --> MGR["OrgDataSourceManager"]
MGR --> DRUID["Druid 连接池"]

图表来源

章节来源

性能考量

  • 连接池调优:通过 application.yaml 配置初始大小、最小空闲、最大活跃、等待超时与健康检查,避免连接泄漏与抖动。
  • 懒加载数据源:按租户维度懒创建 Druid 连接池,减少冷租户资源占用。
  • 分页与查询优化:优先使用 page 接口进行分页;复杂查询可使用 loadDataBySql,但需关注 SQL 质量与索引。
  • 会话与令牌:合理设置 JWT 过期时间,避免频繁刷新;会话替换时及时清理旧会话。
  • 日志与监控:建议接入指标采集(连接池、慢查询、错误率)与链路追踪,便于容量规划与问题定位。

[本节为通用指导,无需特定文件来源]

故障排查指南

  • 认证失败:检查 Authorization 头格式、JWT 签名与过期时间;确认会话是否被顶号。
  • 租户上下文缺失:确保过滤器已设置 orgId;若手动获取连接,需先设置上下文。
  • 数据源异常:核对租户配置是否存在;连接池是否耗尽;SQL 是否正确。
  • 保存失败:查看全局异常中的 table/action/index 详情,定位具体记录与操作。
  • 系统异常:通过全局异常日志定位 method、uri 与堆栈,快速复现问题。

章节来源

结论

FMS 后端采用清晰的 Spring Boot 分层架构与模块化组织,通过 JWT 与会话注册表实现安全的认证与会话管理;借助 ThreadLocal 与路由数据源实现多租户数据隔离;以元数据驱动的通用数据访问能力支撑灵活的 CRUD 与报表需求;统一响应与全局异常处理提升了可维护性与用户体验。建议在后续迭代中完善 API 版本管理与可观测性建设,进一步提升系统的可扩展性与稳定性。

[本节为总结,无需特定文件来源]

附录

  • 部署配置要点:
    • 服务器端口与上下文路径:server.port、server.servlet.context-path。
    • 认证参数:jwt-secret、jwt-expiration。
    • 数据库连接池:initial-size、min-idle、max-active、max-wait、validation-query 等。
    • 文件存储:本地或 OSS 模式及对应路径/URL。
  • 监控建议:
    • 连接池指标(活跃数、等待队列、慢查询)。
    • 接口耗时与错误率(P95/P99)。
    • 租户维度资源使用与热点表访问。

章节来源