diff --git a/.NET5底层框架搭建方案1.md b/.NET5底层框架搭建方案1.md new file mode 100644 index 0000000..4d9c939 --- /dev/null +++ b/.NET5底层框架搭建方案1.md @@ -0,0 +1,324 @@ +# YhCore — .NET 5.0 底层框架搭建方案 + +> 参考项目:`E:\YHXT\java\bschclassmanage`(Spring Boot 2.7 + JPA + MySQL + Redis + Nacos) +> 本地类库支撑:`E:\YHXT\net\Library` +> 范围:**仅底层框架**(分层结构、基础设施、横切组件),不含任何业务逻辑 + +--- + +## 1. 背景与目标 + +将现有 Java(Spring Boot 2.7)项目 `bschclassmanage` 的底层框架能力平移到 .NET 5.0,形成一套可复用的后端基础框架,供 `YhCore` 及后续 .NET 项目使用。 + +**目标:** + +1. 保持与 Java 版一致的分层模型与开发习惯(Controller → Service → Repository → Entity),降低团队切换成本。 +2. 复用 `E:\YHXT\net\Library` 下已有的 DLL(日志、调度、文档处理、JSON 等),减少重复采购/引入。 +3. 提供统一的基础设施:配置管理、日志、异常处理、统一响应、用户上下文、操作日志 AOP、数据访问、缓存、任务调度、接口文档、鉴权。 +4. 只搭骨架,不写业务——框架落地后业务模块以"填空"方式接入。 + +--- + +## 2. Java 参考项目结构分析 + +`bschclassmanage` 的包结构即框架的职责划分,逐项映射如下: + +| Java 包 / 组件 | 职责 | 关键实现 | +| -------------------------------------------- | ------------------------------------------------ | ------------------------------- | +| `controller` (api / mobiapi / oapi) | 接口入口,按渠道分三套 | Spring MVC | +| `service` / `service.impl` | 业务服务层 | 接口 + 实现 | +| `Repository` / `specification` | 数据访问层 + 动态查询 | Spring Data JPA + Specification | +| `entity` | 数据库实体 | Hibernate 注解实体 | +| `model` (dto / vo / excel / constant / tool) | 传输与视图模型 | POJO + ModelMapper 转换 | +| `config` | 框架配置(Async / Redis / Swagger / WebMvc / File) | `@Configuration` | +| `interceptor` | 用户上下文拦截器 | `UserContextInterceptor` | +| `annotation` + `aspect` | 操作日志、同步日志 AOP | `@OperationLog` + AspectJ | +| `scheduler` | 定时任务(升级、日志清理) | Spring `@Scheduled` | +| `validation` | 自定义校验(密码等) | Hibernate Validator | +| `utils` | 30+ 工具类(日期/分页/签名/加解压/Redis/HTTP…) | 静态工具类 | +| 配置体系 | `bootstrap.yml`(Nacos) + `application-{env}.yml` | Nacos 配置中心,多 Profile | +| 日志 | `logback-spring.xml` | Logback + Slf4j | + +**中间件清单**(来自 pom.xml / application.yml):MySQL 8、Redis、RabbitMQ(已预留配置)、Nacos、CAS SSO(yh-auth)、应用间签名鉴权(yh-app-auth)、Swagger(SpringDoc)。 + +--- + +## 3. 技术选型对照表(Java → .NET 5.0) + +| 能力 | Java 实现 | .NET 5.0 方案 | 来源 | +| -------- | -------------------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | +| Web 框架 | Spring MVC | **ASP.NET Core 5.0 Web API** | 内置 | +| 依赖注入 | Spring IoC | **内置 DI**(Autofac 可选,AOP 需要时引入) | 内置 / NuGet | +| ORM | Spring Data JPA (Hibernate) | **EF Core 5.0** 为主;高频 SQL 用 **Dapper** | NuGet `Microsoft.EntityFrameworkCore.SqlServer 5.x` + Library `Dapper.Common.dll` | +| 数据库 | mysql-connector-java 8.0.33(MySQL 8) | **主库 SQL Server**(`Microsoft.EntityFrameworkCore.SqlServer 5.x`);**MySQL 可切换**(`Pomelo.EntityFrameworkCore.MySql 5.x`,按 `DatabaseProvider` 配置切换) | NuGet | +| 动态条件查询 | JPA Specification | EF Core `IQueryable` 链式拼装 + 自定义 Specification 模式 | 框架自研(轻量) | +| 缓存 | spring-data-redis | **StackExchange.Redis**(封装 `RedisUtil` 对应 Java 版) | NuGet | +| 配置中心 | Nacos + 多 Profile | **appsettings.{env}.json** 为基础;预留 **nacos-sdk-csharp** 接入点 | NuGet(可选) | +| 日志 | Logback + Slf4j接口日志 | **log4net**(Library 已有),**仅用于接口访问日志**:单一中间件记录接口调用详情,其余日志(SQL/框架/业务 Debug)全部关闭 | Library | +| JSON | fastjson / Jackson | **Newtonsoft.Json**(Library 已有,兼容旧接口格式) | Library | +| 对象映射 | ModelMapper | **AutoMapper** | NuGet | +| 参数校验 | Hibernate Validator | **FluentValidation**(或 DataAnnotations) | NuGet | +| 接口文档 | SpringDoc OpenAPI | **Swashbuckle.AspNetCore 5.x** | NuGet | +| 定时任务 | `@Scheduled` / scheduler 包 | **Quartz.NET 3.x**(Library 已有 `Quartz.dll`,需核版本)或 `BackgroundService` | Library | +| AOP | AspectJ(`aspect` + `annotation`) | **ActionFilter + 自定义 Attribute**(操作日志);全局逻辑用 **Middleware** | 内置 | +| 拦截器 | HandlerInterceptor | **Middleware / ActionFilter** | 内置 | +| HTTP 客户端 | HttpClient / OkHttp | **IHttpClientFactory** | NuGet `Microsoft.Extensions.Http` | +| Excel/文档 | easypoi (POI) | **Aspose.Cells / Aspose.Words**(Library 已有,打印场景核心) | Library | +| 压缩 | GzipUtil | `ICSharpCode.SharpZipLib`(Library 已有)或 BCL `System.IO.Compression` | Library | +| HTML 解析 | CommonMark / jsoup 类 | **HtmlAgilityPack**(Library 已有) | Library | +| SSO / 鉴权 | CAS(yh-auth)+ yh-app-auth 签名 | 自定义 `AuthenticationHandler` + 签名中间件(对接 `BschOpenApi.dll`) | Library + 自研 | +| 短信/消息 | — | `HyCloud.Sms.dll` / `BestschSendMsg.dll`(按需接入) | Library | +| Lombok | `@Getter/@Setter` | C# 9 `record` / 自动属性,无需替代 | 语言内置 | +| 异步线程池 | AsyncConfig | `async/await` + `Task.Run`,无需独立配置 | 语言内置 | + +--- + +## 4. Library DLL 适配性评估(.NET 5.0 兼容性) + +> .NET 5.0 可引用面向 **.NET Standard 2.0/2.1** 或 **.NET Core/.NET 5+** 的程序集;纯 .NET Framework 4.x 程序集多数可运行但需逐一验证。 + +| DLL | 用途 | .NET 5 兼容策略 | +| ------------------------------------------------------------------ | ------------------------- | ------------------------------------------------------------------------------------------------- | +| `Aspose.Cells/Words/Slides.dll` | Excel/Word/PPT 文档生成(打印核心) | 需确认版本 ≥ 20.x(支持 .NET Standard 2.0)。旧 .NET Framework 版建议升级 NuGet 官方包 | +| `EntityFramework.dll` + `EntityFramework.SqlServer.dll` | EF6(SQL Server) | ⚠️ **不建议使用**:EF6 仅 6.4+ 支持 .NET Core;本方案选 EF Core 5(SqlServer 提供方) | +| `Dapper.Common.dll` | Dapper 扩展 | 验证目标框架;不兼容则改用 NuGet `Dapper` + `Dapper.Contrib` | +| `log4net.dll` + `Common.Logging*.dll` | 日志 | log4net 2.0.8+ 支持 .NET Standard 2.0,可直接用;建议只保留 log4net,弃用 Common.Logging(.NET 5 有官方 `ILogger` 抽象) | +| `Quartz.dll` | 任务调度 | 需 ≥ 3.1(.NET Standard 2.0);旧 2.x 不兼容,则 NuGet 升级 `Quartz` 3.x | +| `Newtonsoft.Json.dll` | JSON | 直接用(或 NuGet 对齐版本) | +| `ICSharpCode.SharpZipLib.dll` | 压缩/解压 | 1.2+ 支持 .NET Standard 2.0,可用 | +| `HtmlAgilityPack.dll` | HTML 解析 | 1.11+ 支持 .NET Standard 2.0,可用 | +| `C5.dll` | 扩展集合 | 2.5+ 支持 .NET Standard,可用(优先级低) | +| `BschOpenApi.dll` | 开放平台签名 | ⚠️ 需反编译确认目标框架;若为 .NET Framework 4.x 且无 Core 版,封装为独立 Facade 隔离风险 | +| `BestschSendMsg.dll` / `HyCloud.Sms.dll` / `BestSchool.Unread.dll` | 消息/短信 | 同上,逐个验证;不兼容走 HTTP API 调用替代 | +| `HTTPSSSL.dll` / `DecompressFile.dll` | HTTPS / 解压 | .NET 5 原生支持,建议**弃用**,用 BCL 替代 | + +**结论**:核心三件(Aspose、log4net、Quartz)+ Newtonsoft.Json + SharpZipLib + HtmlAgilityPack 构成 Library 复用主力;EntityFramework、HTTPSSSL、DecompressFile 弃用;业务 DLL(BschOpenApi/Sms 等)做兼容性验证后封装接入。 + +--- + +## 5. 解决方案结构设计 + +``` +E:\YHXT\net\YhCore\ +├─ YhCore.sln +├─ docs\ # 方案与设计文档 +├─ lib\ # 本地 DLL 引用(软链或复制自 E:\YHXT\net\Library) +├─ sqlscript\ # 数据库脚本(沿用 Java 项目惯例) +├─ src\ +│ ├─ YhCore.WebApi\ # ★ 启动项目(对应 Java 的 controller + config) +│ │ ├─ Controllers\ +│ │ │ ├─ Api\ # 对应 controller/api +│ │ │ ├─ MobiApi\ # 对应 controller/mobiapi +│ │ │ └─ OApi\ # 对应 controller/oapi +│ │ ├─ Middleware\ # 对应 interceptor:接口访问日志、用户上下文、异常、签名 +│ │ ├─ Filters\ # 对应 aspect+annotation:操作日志、校验 +│ │ ├─ Attributes\ # 对应 annotation:[OperationLog] 等 +│ │ ├─ Extensions\ # ServiceCollection / ApplicationBuilder 扩展 +│ │ ├─ appsettings.json +│ │ ├─ appsettings.Development.json +│ │ ├─ appsettings.Production.json +│ │ ├─ log4net.config +│ │ ├─ Program.cs +│ │ └─ Startup.cs +│ ├─ YhCore.Service\ # 业务服务层(对应 service + service.impl) +│ │ ├─ Interfaces\ +│ │ └─ Impl\ +│ ├─ YhCore.Repository\ # 数据访问层(对应 Repository + specification) +│ │ ├─ Base\ # Repository 基类、IRepository、UnitOfWork +│ │ ├─ Specification\ # 动态查询条件构造 +│ │ └─ YHDbContext.cs # EF Core 上下文 +│ ├─ YhCore.Entity\ # 数据库实体(对应 entity,DB First 生成) +│ ├─ YhCore.Model\ # 对应 model:DTO / VO / Excel / 常量 +│ │ ├─ Dto\ +│ │ ├─ Vo\ +│ │ ├─ Excel\ +│ │ └─ Constant\ +│ ├─ YhCore.Common\ # 对应 utils:30+ 工具类的 .NET 版 +│ │ ├─ Result\ # ServiceResult / ApiResult 统一响应 +│ │ ├─ UserContext\ # 当前用户上下文(AsyncLocal 实现) +│ │ ├─ Cache\ # RedisUtil 封装 +│ │ ├─ Http\ # HttpClient 封装 +│ │ ├─ Security\ # Signature 签名、加密 +│ │ └─ Utils\ # 日期/分页/枚举/校验/Gzip… +│ └─ YhCore.Task\ # 对应 scheduler:Quartz 任务宿主 +│ ├─ Jobs\ +│ └─ QuartzHostedService.cs +├─ tests\ +│ └─ YhCore.Tests\ # xUnit 单元测试 +└─ docker\ # Dockerfile / compose(沿用 Java 项目惯例) +``` + +**分层依赖方向**(单向,禁止反向引用): + +``` +WebApi → Service → Repository → Entity + └──────→ Model ←──────┘ + └──────────→ Common ←──────────┘(Common 不依赖任何上层) +``` + +--- + +## 6. 底层框架核心组件设计 + +### 6.1 配置体系(对应 bootstrap.yml + application-{env}.yml) + +- 本地开发:`appsettings.json` + `appsettings.Development.json`(默认不连 Nacos,对应 Java 的 `profile=local`)。 +- 生产:环境变量注入(对应 CI 注入 `SPRING_PROFILES_ACTIVE=prod`)+ 可选 Nacos(`nacos-sdk-csharp`),加载顺序沿用"共享配置 → 应用配置 → 环境变量覆盖"的三级优先级约定。 +- 强类型配置:`services.Configure(configuration.GetSection("Yh:Sso"))`,Options 类按 Java yml 的 key 结构一一对应(`yh.sso.*`、`yh.app-auth.*`、datasource、redis 等)。 + +### 6.2 日志(对应 logback-spring.xml) + +**只保留接口访问日志,其余日志一律去除。** + +- 通过 `ApiAccessLogMiddleware`(请求管道最外层)统一记录每次接口调用详情,框架不再输出任何其他日志(SQL 日志、框架运行日志、业务 Debug/Info 日志全部关闭)。 +- **记录字段**:请求时间、渠道(api / mobiapi / oapi)、请求路径与方法、Query 与 Body(敏感字段脱敏,对应 `SensitiveDataUtil`)、客户端 IP、当前用户(取 `UserContext`)、响应状态码、响应耗时、异常摘要(若本次请求出错)。 +- **落地**:log4net(Library 复用)配置单个 `RollingFileAppender`,按天滚动一个接口日志文件,不做级别分文件。 +- **屏蔽其他输出**:`appsettings.json` 中将 `Microsoft.*`、`System.*`、`Pomelo.*`(EF Core SQL 日志)等内置日志类别全部设为 `None`;代码规范上禁止在业务代码中调用 `ILogger` 写日志。 + +### 6.3 统一响应(对应 yh-api-std / BestSchool.Common 的 ServiceResult) + +复用 `Library\新建文件夹\BestSchool.Common\ServiceResult.cs` 的思路,定义: + +```csharp +public class ApiResult +{ + public int Code { get; set; } // 0=成功 + public string Message { get; set; } + public T Data { get; set; } + public static ApiResult Ok(T data) => new() { Code = 0, Data = data }; + public static ApiResult Fail(string msg, int code = -1) => new() { Code = code, Message = msg }; +} +``` + +配合 `ActionFilter` 自动包装 Controller 返回值,业务代码只返回 `T`。 + +### 6.4 全局异常处理中间件 + +- 捕获未处理异常 → 返回统一 `ApiResult.Fail`(对应 Java 的 `@ControllerAdvice`);异常详情由 6.2 的接口访问日志统一记录,不单独输出错误日志。 +- 自定义 `BizException`:Service 层抛出业务异常,中间件翻译为友好错误码。 + +### 6.5 用户上下文(对应 UserContextInterceptor + UserContext + ControllerUserContextAspect) + +- `UserContextMiddleware`:从 CAS Ticket / Header 解析当前用户,写入 `AsyncLocal`。 +- 全链路任意位置通过 `UserContextHolder.Current` 获取(对应 Java 的 ThreadLocal 方案,AsyncLocal 是 .NET 的等价物且对 async 安全)。 +- **Java `DWebMvcConfig` 不迁移、直接移除**:它仅负责把 `UserContextInterceptor` 注册到 `/**`,中间件方式天然作用于全管道,无需等价的注册配置类。 + +### 6.6 操作日志 AOP(对应 @OperationLog + OperationLogAspect) + +```csharp +[AttributeUsage(AttributeTargets.Method)] +public class OperationLogAttribute : Attribute +{ + public string Module { get; } + public string Action { get; } +} +``` + +- `[OperationLog("班级", "升级")]` 标注在 Controller 方法上; +- `OperationLogFilter : IAsyncActionFilter` 在方法执行后解析 SpEL 等价表达式(用路由参数/参数名占位符),异步落库到操作日志表(对应 `OperationLogResolver` + `OperationLogRecordRepository`)。 + +### 6.7 数据访问(对应 JPA Repository + Specification) + +- **数据库方案**:主库 **SQL Server**(`Server=localhost;Database=EduCloudDocPrint`),同时**支持切换 MySQL**——`appsettings.json` 中 `DatabaseProvider` 取 `SqlServer`(默认)或 `MySql`,`AddDataLayer` 扩展按此选择 EF Core 提供方(`Microsoft.EntityFrameworkCore.SqlServer 5.x` / `Pomelo.EntityFrameworkCore.MySql 5.x`)。连接串生产环境用环境变量覆盖(`ConnectionStrings__SqlServer`),不入库密码。 +- **EF Core 5**:`YHDbContext` 集中管理实体;旧 EF6 实体无 `[Key]` 标注,统一按约定推断主键(优先 `Id`,其次 `SerID`,皆无则 Keyless);`IRepository` / `RepositoryBase` 提供 CRUD、分页(对应 `PageUtil`)、批量操作。 +- **Specification 轻量实现**:`Expression>` 组合器(And/Or/Not),对应 Java `specification` 包的动态查询。 +- **Dapper 通道**:复杂报表/批量快照插入(对应 Java 用 JdbcTemplate 的 `backupAllSnapshot` 场景)走 Dapper,与 EF 共存。 +- 事务:`IDbContextTransaction` 显式事务 + UnitOfWork 模式;生产 `ddl-auto=none` 对应 EF **禁用自动迁移**,结构变更走 `sqlscript` 脚本。 + +### 6.8 Redis 缓存(对应 RedisConfig + RedisUtil) + +- `StackExchange.Redis` 单例 `ConnectionMultiplexer` 注入; +- `RedisUtil` 封装 String/Hash/Set/分布式锁,Key 规范常量集中在 `RedisConstants`(对应 Java 同名类)。 + +### 6.9 任务调度(对应 scheduler 包) + +- Quartz.NET 3.x + `QuartzHostedService` 承载;Job 通过 DI 构造(可访问 Service 层)。 +- 框架内置两个示例 Job 骨架:定时任务模板、日志清理任务模板(对应 `SysOperationLogCleanupTask`),业务 Job 后续按模板添加。 +- 轻量场景可直接用 `BackgroundService` + `PeriodicTimer`。 + +### 6.10 接口文档(对应 SwaggerConfig) + +- Swashbuckle:按渠道分组(api / mobiapi / oapi 三个 Swagger Doc),Header 鉴权参数预置,对应 Java 的三套 controller 分组。 + +### 6.11 鉴权(对应 yh-auth CAS + yh-app-auth 签名) + +- `CasAuthenticationHandler : AuthenticationHandler`:复刻 CAS ticket 校验与 SSO 重定向逻辑(配置项对齐 `yh.sso.*`)。 +- `AppAuthMiddleware`:应用间调用签名校验(app-key / timestamp / sign),对应 `yh.app-auth.*`;优先尝试复用 `BschOpenApi.dll` 的签名算法,不兼容则按 Signature.java 逻辑重写。 + +### 6.12 参数校验(对应 validation 包) + +- FluentValidation:每个 DTO 一个 `AbstractValidator`,自动注册; +- 自定义校验规则(如密码强度,对应 `PasswordValidation`)实现为可复用扩展方法。 + +### 6.13 文件上传(对应 FileConfig + multipart 50MB) + +- `FormOptions` 配置 `MultipartBodyLengthLimit = 50MB`; +- 上传路径走强类型配置 `FileOptions`,对应 Java `FileConfig`。 + +### 6.14 路由常量(对应 Java `Config` 枚举的 API_PATH / MOBILEAPI_PATH / OAPI) + +- Java `Config` 枚举中的三个渠道路由前缀,集中在 `Common` 层 `ApiRoutes` 常量类: + `ApiPath = "api"`、`MobiApiPath = "mobiapi"`、`OApiPath = "oapi"`。 +- Controller 一律用 `[Route(ApiRoutes.ApiPath + "/log")]` 引用常量,**禁止硬编码 `"api/..."` 字符串**,与 Java 版 `Config.API_PATH` 常量化做法保持一致。 +- `Config` 枚举的 `FILE_PATH` / `FILE_WEB_PATH` 已由 6.13 `FileOptions` 覆盖;`getString/getInt`(ResourceBundle 读 config.properties)无对应需求,不迁移。 + +--- + +## 7. 关键骨架代码示例 + +**Program.cs / Startup.cs 装配顺序:** + +```csharp +public void ConfigureServices(IServiceCollection services) +{ + services.AddControllers() + .AddNewtonsoftJson(o => { // 对齐 Java Jackson 配置 + o.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; + }); + services.AddDataLayer(Configuration); // SQL Server 主库;DatabaseProvider=MySql 时切 Pomelo + services.AddRedisCache(Configuration); // RedisUtil 单例(StackExchange.Redis,连接串取 Redis:ConnectionString) + services.AddRepositories(); // 扩展方法:批量注册 IRepository + services.AddServices(); // 扩展方法:批量注册 Service + services.AddAutoMapper(typeof(Startup)); + services.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining()); + services.AddSwaggerGen(/* 三组文档 + 鉴权 Header */); + services.AddQuartzHosted(); // 调度 + services.AddLog4Net(); // 日志 +} + +public void Configure(IApplicationBuilder app) +{ + app.UseMiddleware(); // 0. 接口访问日志(唯一日志出口) + app.UseMiddleware(); // 1. 异常兜底(异常摘要并入接口日志) + app.UseMiddleware(); // 2. 用户上下文 + app.UseMiddleware(); // 3. 应用签名(oapi 渠道) + app.UseAuthentication(); // 4. CAS + app.UseAuthorization(); + app.UseEndpoints(e => e.MapControllers()); +} +``` + +--- + +## 8. 实施步骤 + +| 阶段 | 内容 | 产出 | +| -------- | ------------------------------------------------------------------- | ----------------- | +| 1. 环境准备 | 安装 .NET 5 SDK、创建解决方案与 7 个类库项目、配置 `lib` 本地引用 | sln 骨架可编译 | +| 2. 基础件接入 | log4net、Newtonsoft、Swagger、AutoMapper、FluentValidation | 启动即出 Swagger 页 | +| 3. 数据层 | 建 YHDbContext + Repository 基类 + Specification + Dapper 通道(暂不生成业务实体) | 连通 SQL Server 冒烟通过 | +| 4. 横切组件 | 统一响应、异常中间件、**接口访问日志中间件(唯一日志出口)**、用户上下文、操作日志 Filter | Postman 验证全链路 | +| 5. 缓存与调度 | RedisUtil + Quartz 宿主 + Job 模板 | Redis 读写、Job 触发验证 | +| 6. 鉴权 | CAS Handler + 签名中间件(对接 yh 平台配置) | SSO 联调通过 | +| 7. 收尾 | Dockerfile、CI 配置、开发规范文档 | 框架交付 | + +--- + +## 9. 风险与注意事项 + +1. **.NET 5 已 EOS**(2022-05 停止支持):按用户要求采用 5.0,但建议方案预留升级路径(代码只使用与 .NET 6/8 兼容的 API,将来改 `TargetFramework` 即可)。 +2. **Library DLL 多为 .NET Framework 时代产物**:开工第一件事是对 `lib` 全部 DLL 做目标框架核验(可用 `dotnet` 反编译或 `Assembly.LoadFrom` 试加载),不兼容的立即走 NuGet 替代,避免后期返工。 +3. **EF6 → EF Core 语义差异**:Java JPA 的 `ddl-auto: update` 在 EF Core 中对应 Migrate,生产环境一律禁用自动迁移,结构变更走 SQL 脚本(与 Java 侧生产约定一致)。 +4. **AsyncLocal vs ThreadLocal**:用户上下文必须用 `AsyncLocal`,否则 async 方法链中上下文丢失。 +5. **Nacos 为可选项**:本地/单机部署先用 `appsettings.{env}.json` + 环境变量;需接入配置中心时再启用 `nacos-sdk-csharp`,配置 key 结构保持与 Java yml 一致,降低运维心智成本。 +6. **命名习惯迁移**:Java 的 `getClassHistoryTree` 等接口路径与返回结构保持原样(URL 与 JSON 字段不变),保证前端/移动端零改动切换。