# 资金服务平台 - 开发问题清单 > **文档版本**: v1.0 > **创建日期**: 2026-02-13 > **记录时段**: 2026-02-12 09:00 ~ 2026-02-13 当前时间 --- ## 问题清单概览 | 序号 | 问题分类 | 问题描述 | 严重程度 | 状态 | |------|----------|----------|----------|------| | 1 | 前后端接口 | /auth/info接口返回400 Bad Request | 高 | 已解决 | | 2 | 前端路由 | 个人中心和系统设置菜单点击无反应 | 中 | 已解决 | | 3 | 前端路由 | 刷新页面显示404 | 高 | 已解决 | | 4 | 后端序列化 | AOP日志LocalDateTime序列化失败 | 中 | 已解决 | | 5 | 后端接口 | 新增支出expenseType字段雪花ID超出Integer范围 | 高 | 已解决 | | 6 | OpenFeign配置 | FeignChainInterceptor未注册为Spring Bean | 高 | 已解决 | | 7 | 全链路追踪 | TraceContextHolder未在HTTP入口初始化导致链路断裂 | 高 | 已解决 | | 8 | OpenFeign配置 | FeignClient硬编码URL导致Nacos服务发现失效 | 高 | 已解决 | | 9 | Nacos 配置 | Nacos 3.0 客户端缺少 username/password 认证配置 | 高 | 已解决 | | 10 | 连接池监控 | HikariMonitorConfig空指针异常 | 中 | 已解决 | --- ## 问题详情与解决方案 ### 问题1:/auth/info接口返回400 Bad Request #### 问题现象 ``` Request URL: http://localhost:3002/sys/api/v1/auth/info Request Method: GET Status Code: 400 Bad Request ``` 用户登录成功后,调用 `/auth/info` 获取用户信息时返回400错误。 #### 问题原因 后端接口需要 `X-User-Id` 请求头来识别当前用户,但前端未在请求中传递该header。 #### 解决方案 **1. 修改前端请求拦截器** (`fund-admin/src/api/request.ts`) ```typescript // 在请求头中添加 X-User-Id request.headers['X-User-Id'] = localStorage.getItem('userId') || '' ``` **2. 修改用户登录逻辑** (`fund-admin/src/stores/user.ts`) ```typescript // 登录成功后保存 userId 和 tenantId 到 localStorage localStorage.setItem('userId', String(res.data.userId)) localStorage.setItem('tenantId', String(res.data.tenantId)) ``` #### 经验总结 - 前后端接口对接时,需确认所有必需的请求头 - 用户信息(userId、tenantId)应在登录成功后立即持久化存储 --- ### 问题2:个人中心和系统设置菜单点击无反应 #### 问题现象 点击顶部下拉菜单中的"个人中心"和"系统设置"选项后,页面无任何跳转反应。 #### 问题原因 `MainLayout.vue` 中的 `handleCommand` 函数对 `profile` 和 `settings` 两个命令的处理为空实现。 ```typescript // 问题代码 const handleCommand = async (command: string) => { switch (command) { case 'profile': // 空实现,无任何代码 break case 'settings': // 空实现,无任何代码 break case 'logout': await userStore.logout() router.push('/login') break } } ``` #### 解决方案 **修改 `fund-admin/src/layouts/MainLayout.vue`** ```typescript const handleCommand = async (command: string) => { switch (command) { case 'profile': router.push('/profile') break case 'settings': router.push('/system/config') break case 'logout': await userStore.logout() router.push('/login') break } } ``` 同时在侧边栏菜单中添加"参数设置"入口。 #### 经验总结 - 开发新功能时,需确保所有UI交互都有对应的业务实现 - 代码提交前应进行基础功能测试 --- ### 问题3:刷新页面显示404 #### 问题现象 登录后进入业务页面,刷新浏览器后页面显示404: ``` Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. type=Not Found, status=404 ``` #### 问题原因 Vite 开发服务器的代理配置中,`/sys` 路径模糊匹配了前端路由 `/system`,导致前端路由请求被错误代理到后端服务。 ```typescript // 问题配置 proxy: { '/sys': { // 会匹配 /sys 开头的所有路径,包括 /system target: 'http://localhost:8100', changeOrigin: true, rewrite: (path) => path.replace(/^\/sys/, '') } } ``` #### 解决方案 **修改 `fund-admin/vite.config.ts`** ```typescript proxy: { '/sys/': { // 添加斜杠,精确匹配 /sys/ 开头的路径 target: 'http://localhost:8100', changeOrigin: true, rewrite: (path) => path.replace(/^\/sys/, '') } } ``` 同时改进路由守卫逻辑,更好地处理页面刷新场景。 #### 经验总结 - 代理路径配置应使用精确匹配,避免模糊匹配导致的路由冲突 - 前端路由命名应与后端API路径有明显区分 --- ### 问题4:AOP日志LocalDateTime序列化失败 #### 问题现象 为 fund-sys 添加 AOP 日志功能后,日志输出时报错: ``` Java 8 date/time type 'java.time.LocalDateTime' not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling ``` #### 问题原因 Jackson 默认不支持 Java 8 的日期时间类型(LocalDateTime、LocalDate等)的序列化,需要额外配置。 #### 解决方案 **1. 添加 Maven 依赖** (`fund-sys/pom.xml`) ```xml com.fasterxml.jackson.datatype jackson-datatype-jsr310 ``` **2. 配置 ObjectMapper** (`ApiLogAspect.java`) ```java private static final ObjectMapper objectMapper = new ObjectMapper(); static { // 注册JavaTimeModule以支持Java 8日期时间类型 objectMapper.registerModule(new JavaTimeModule()); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); } ``` **3. 序列化异常兜底处理** ```java try { logInfo.put("responseBody", objectMapper.writeValueAsString(result)); } catch (Exception e) { // 序列化失败时使用toString()兜底 logInfo.put("responseBody", result.toString()); } ``` #### 经验总结 - 使用 Jackson 序列化 Java 8 日期时间类型时,必须注册 `JavaTimeModule` - 对于复杂的序列化场景,应添加异常兜底处理,避免日志功能影响业务 - Spring Boot 项目使用 AOP 需引入 `spring-boot-starter-aop` 依赖 --- ### 问题5:新增支出expenseType字段雪花ID超出Integer范围 #### 问题现象 ``` POST http://localhost:8080/exp/api/v1/exp/expense Status Code: 400 Bad Request ``` 移动端新增支出时,请求返回 400 错误,无任何响应内容。 #### 问题原因 后端 `FundExpenseDTO.expenseType` 字段类型为 `Integer`,最大值为 2147483647。而前端传递的是雪花ID(如 `2023686600025919489`),远超 Integer 范围,导致 JSON 解析失败。 #### 解决方案 **修改 `fund-exp/src/main/java/com/fundplatform/exp/dto/FundExpenseDTO.java`** ```java // 修改前 @NotNull(message = "支出类型不能为空") private Integer expenseType; public Integer getExpenseType() { return expenseType; } public void setExpenseType(Integer expenseType) { this.expenseType = expenseType; } // 修改后 @NotNull(message = "支出类型不能为空") private Long expenseType; public Long getExpenseType() { return expenseType; } public void setExpenseType(Long expenseType) { this.expenseType = expenseType; } ``` #### 经验总结 - 使用雪花ID作为主键的实体,其外键字段类型必须使用 `Long` 而非 `Integer` - Java Integer 范围:-2147483648 ~ 2147483647(约21亿) - 雪花ID范围:通常为19位数字,远超 Integer 范围 --- ### 问题6:FeignChainInterceptor未注册为Spring Bean #### 问题现象 OpenFeign 调用下游服务时,租户ID、用户信息、TraceId 等上下文信息未透传,导致下游服务无法获取当前请求的租户和用户信息。 #### 问题原因 `FeignChainInterceptor` 虽然实现了 `RequestInterceptor` 接口,但缺少 `@Component` 注解,未被 Spring 注册为 Bean,导致 OpenFeign 调用时拦截器不生效。 ```java // 问题代码 public class FeignChainInterceptor implements RequestInterceptor { // 没有 @Component 注解 } ``` #### 解决方案 **1. 添加 Bean 注解** (`fund-common/src/main/java/com/fundplatform/common/feign/FeignChainInterceptor.java`) ```java @Component // 添加此注解 public class FeignChainInterceptor implements RequestInterceptor { // ... } ``` **2. 配置组件扫描** (`fund-report/src/main/java/com/fundplatform/report/ReportApplication.java`) ```java @SpringBootApplication(scanBasePackages = {"com.fundplatform.report", "com.fundplatform.common"}) @EnableDiscoveryClient @EnableFeignClients public class ReportApplication { // ... } ``` #### 经验总结 - Spring 组件(Service、Component、Repository 等)必须添加相应注解才能被容器管理 - 跨模块的组件需确保使用该组件的模块配置了正确的 `scanBasePackages` - Feign 拦截器是实现微服务间上下文透传的关键,必须确保正确注册 --- ### 问题 7:TraceContextHolder 未在 HTTP 入口初始化导致链路断裂 #### 问题现象 Gateway 层已生成 TraceId 并写入请求头 `X-Trace-Id`,但业务服务中调用 `TraceContextHolder.getTraceId()` 返回 null,Feign 调用时会重新生成新的 TraceId,导致全链路追踪断裂。 #### 问题原因 `ContextInterceptor` 只提取了租户 ID 和用户 ID,未从请求头中提取 Gateway 传递的 TraceId 并设置到 `TraceContextHolder`,导致: 1. 业务逻辑无法获取 Gateway 生成的 TraceId 2. Feign 调用时通过 `getOrCreateTraceId()` 生成新的 TraceId 3. 日志系统中出现多个不同的 TraceId,无法串联完整调用链 ```java // 问题代码 - ContextInterceptor.preHandle // 缺少 TraceId 的提取逻辑 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 只设置了 TenantId 和 UserId TenantContextHolder.setTenantId(tenantId); UserContextHolder.setUserId(userId); // 缺失:TraceContextHolder.setTraceId(traceId); return true; } ``` #### 解决方案 **修改 `fund-common/src/main/java/com/fundplatform/common/web/ContextInterceptor.java`** 1. 添加导入和常量定义 ```java import com.fundplatform.common.context.TraceContextHolder; public static final String HEADER_TRACE_ID = "X-Trace-Id"; ``` 2. 在 preHandle 中提取 TraceId ```java // 提取 TraceId(如不存在,后续会在需要时自动生成) String traceId = request.getHeader(HEADER_TRACE_ID); if (traceId != null && !traceId.isEmpty()) { TraceContextHolder.setTraceId(traceId); } ``` 3. 在 afterCompletion 中清理 TraceContextHolder ```java @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { TenantContextHolder.clear(); UserContextHolder.clear(); TraceContextHolder.clear(); // 新增 } ``` #### 修复后的完整链路 ``` Gateway (GlobalLogFilter) ↓ 生成 TraceId: abc123 并写入 X-Trace-Id 请求头 业务服务 A (ContextInterceptor.preHandle) ↓ 读取 X-Trace-Id: abc123 并设置到 TraceContextHolder 业务逻辑 A ↓ 使用 TraceContextHolder.getTraceId() → abc123 FeignChainInterceptor.apply ↓ 从 TraceContextHolder 获取 abc123 并透传到下游 业务服务 B (ContextInterceptor.preHandle) ↓ 读取 X-Trace-Id: abc123 并设置到 TraceContextHolder 业务逻辑 B ↓ 使用 TraceContextHolder.getTraceId() → abc123 afterCompletion ↓ 清理所有 ThreadLocal ``` #### 经验总结 - Gateway 生成的 TraceId 必须在业务服务入口处提取并设置到 ThreadLocal - Feign 拦截器应从 ThreadLocal 获取 TraceId 并透传,而不是重新生成 - 所有 ThreadLocal 使用后必须在 finally 或 afterCompletion 中清理,防止内存泄漏 - 全链路追踪需要每个环节都正确传递 TraceId,任何一环断裂都会导致追踪失败 --- ### 问题 8:FeignClient 硬编码 URL 导致 Nacos 服务发现失效 #### 问题现象 已配置 Nacos 作为服务注册中心,但各 FeignClient 仍使用 `url = "${feign.xxx.url:http://localhost:xxxx}"` 硬编码地址,导致: 1. Nacos 服务注册中心形同虚设 2. Feign 不会通过 Nacos 进行服务发现和负载均衡 3. 无法实现服务动态扩缩容和高可用 ```java // 问题代码 - ExpenseFeignClient.java @FeignClient(name = "fund-exp", url = "${feign.fund-exp.url:http://localhost:8140}") public interface ExpenseFeignClient { // ... } ``` #### 问题原因 **架构设计不一致**: - ✅ 已在 `application.yml` 中配置 Nacos 服务发现 - ❌ 但 FeignClient 仍指定了固定的 URL 地址 **可能的历史原因**: 1. **开发环境过渡方案**:本地开发时 Nacos 未部署,临时使用直连方式 2. **迁移遗留问题**:从单体架构迁移到微服务时的过渡配置 3. **理解偏差**:误以为 FeignClient 必须指定 url #### 解决方案 **修复前(❌)**: ```java @FeignClient(name = "fund-exp", url = "${feign.fund-exp.url:http://localhost:8140}") // ↓ 直接访问固定地址,Nacos 不生效 ``` **修复后(✅)**: ```java @FeignClient(name = "fund-exp") // ↓ 通过 Nacos 服务发现 + Ribbon 负载均衡 ``` **涉及的文件修改**: 1. `ExpenseFeignClient.java` - 移除 `url` 属性 2. `ReceivableFeignClient.java` - 移除 `url` 属性 3. `ProjectFeignClient.java` - 移除 `url` 属性 4. `SysServiceClient.java` - 移除 `url` 属性 #### 修复后的架构优势 **工作流程:** ``` Fund-Report (调用方) ↓ FeignClient: fund-exp ↓ Spring Cloud OpenFeign + Nacos Discovery ↓ 从 Nacos 查询 fund-exp 服务的所有实例 ↓ Ribbon/LoadBalancer 进行负载均衡选择实例 ↓ 发起 HTTP 请求到选中的实例 ``` **带来的好处:** | 特性 | 修复前 | 修复后 | |------|--------|--------| | **服务发现** | ❌ 固定地址 | ✅ 自动感知上下线 | | **负载均衡** | ❌ 单点 | ✅ 多实例轮询 | | **高可用** | ❌ 故障无法切换 | ✅ 自动切换健康实例 | | **弹性扩缩容** | ❌ 需修改配置 | ✅ 新增实例无需配置 | | **架构一致性** | ❌ Nacos 形同虚设 | ✅ 充分发挥作用 | #### 正确的 FeignClient 配置规范 | 场景 | 配置方式 | 示例 | |------|---------|------| | **有注册中心(推荐)** | 只指定 name | `@FeignClient(name = "fund-exp")` | | **无注册中心** | 指定 name + url | `@FeignClient(name = "xxx", url = "http://localhost:8080")` | | **需要降级** | 指定 name + fallback | `@FeignClient(name = "fund-exp", fallback = ExpFallback.class)` | #### 必备配置要求 **1. application.yml 配置** ```yaml spring: cloud: nacos: discovery: server-addr: localhost:8848 # Nacos 地址 namespace: fund-platform # 命名空间 group: DEFAULT_GROUP # 分组 ``` **2. 启动类注解** ```java @SpringBootApplication @EnableDiscoveryClient // 启用服务发现 @EnableFeignClients // 启用 Feign 客户端 public class ReportApplication { // ... } ``` #### 经验总结 - **有注册中心时必须移除 url 属性**,让 Feign 通过注册中心发现服务 - **url 属性仅用于开发测试或特殊场景**(如直连第三方服务) - **Nacos 的价值在于服务发现与负载均衡**,硬编码 URL 会让这些能力失效 - **微服务架构应充分利用注册中心**,避免回到点对点调用的老路 --- ### 问题 9:Nacos 3.0 客户端缺少 username/password 认证配置 #### 问题现象 Nacos 3.0 版本升级后,各业务服务启动时无法注册到 Nacos,控制台报错: ``` com.alibaba.nacos.api.exception.NacosException: Error Code: 403, Error Msg: authorization failed ``` 或日志中出现: ``` WARN com.alibaba.nacos.client.naming - [NA] failed to call server com.alibaba.nacos.api.exception.NacosException: Client need token, but token is empty. ``` #### 问题原因 **Nacos 3.0 安全策略变更**: - Nacos 2.x 版本:客户端可以匿名访问服务端 - Nacos 3.0 版本:**强制要求客户端提供用户名和密码进行认证** **默认凭证**: - 用户名:`nacos` - 密码:`nacos` **影响范围**: 所有配置了 Nacos 服务发现的模块都需要添加认证信息。 #### 解决方案 **修复前(❌)**: ```yaml spring: cloud: nacos: discovery: server-addr: localhost:8848 namespace: fund-platform group: DEFAULT_GROUP # 缺少 username 和 password ``` **修复后(✅)**: ```yaml spring: cloud: nacos: discovery: server-addr: localhost:8848 namespace: fund-platform group: DEFAULT_GROUP username: nacos # Nacos 3.0 必需 password: nacos # Nacos 3.0 必需 ``` **涉及的所有模块**: | 模块 | 服务名 | 配置文件位置 | |------|--------|-------------| | fund-sys | fund-sys | `fund-sys/src/main/resources/application.yml` | | fund-cust | fund-cust | `fund-cust/src/main/resources/application.yml` | | fund-exp | fund-exp | `fund-exp/src/main/resources/application.yml` | | fund-proj | fund-proj | `fund-proj/src/main/resources/application.yml` | | fund-req | fund-req | `fund-req/src/main/resources/application.yml` | | fund-receipt | fund-receipt | `fund-receipt/src/main/resources/application.yml` | | fund-file | fund-file | `fund-file/src/main/resources/application.yml` | | fund-report | fund-report | `fund-report/src/main/resources/application.yml` | #### 验证方法 **1. 查看服务注册状态** 访问 Nacos 控制台:http://localhost:8048/ - 登录账号:`nacos` / `nacos` - 进入「服务管理」→「服务列表」 - 应该能看到所有服务已成功注册 **2. 检查服务日志** 启动日志中应该出现: ``` INFO c.a.cloud.nacos.registry.NacosServiceRegistry - nacos registry, DEFAULT_GROUP fund-sys 10.244.21.185:8100 register finished ``` **3. 测试服务调用** ```bash curl http://localhost:8000/sys/api/v1/sys/health # 应该能正常返回健康检查结果 ``` #### Nacos 3.0 vs 2.x 主要变化 | 特性 | Nacos 2.x | Nacos 3.0 | 影响 | |------|-----------|-----------|------| | **客户端认证** | ❌ 不需要 | ✅ 强制要求 | 必须配置 username/password | | **Token 机制** | ❌ 无 | ✅ JWT Token | 客户端需携带有效 Token | | **权限控制** | ❌ 弱 | ✅ 强化 | 支持细粒度 RBAC 权限管理 | | **审计日志** | ❌ 基础 | ✅ 完整 | 记录所有敏感操作 | #### 经验总结 - **Nacos 3.0 升级后必须修改客户端配置**,否则无法正常注册 - **默认用户名和密码都是 `nacos`**,生产环境建议修改为强密码 - **Gateway 不需要配置 discovery**,但需要通过 `@EnableDiscoveryClient` 启用服务发现 - **认证失败会报 403 错误**,而不是连接失败的错误 --- ### 问题 10:HikariMonitorConfig 空指针异常 #### 问题现象 服务启动后,定时任务日志中持续报错: ``` java.lang.NullPointerException: Cannot invoke "com.zaxxer.hikari.HikariPoolMXBean.getActiveConnections()" because the return value of "com.zaxxer.hikari.HikariDataSource.getHikariPoolMXBean()" is null at com.fundplatform.sys.config.HikariMonitorConfig.monitorHikariPool(HikariMonitorConfig.java:38) ``` #### 问题原因 **HikariCP 连接池初始化时机问题**: - `HikariDataSource.getHikariPoolMXBean()` 方法在连接池尚未初始化时返回 `null` - 定时任务在应用启动后立即执行,此时连接池可能还未完成初始化 - 直接调用 `getActiveConnections()` 等方法会导致空指针异常 **相关代码**: ```java // 问题代码 @Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES) public void monitorHikariPool() { if (dataSource instanceof HikariDataSource) { HikariDataSource hikariDataSource = (HikariDataSource) dataSource; // 未检查 getHikariPoolMXBean() 返回值是否为 null log.info("活跃连接数: {}", hikariDataSource.getHikariPoolMXBean().getActiveConnections()); } } ``` #### 解决方案 **修复后代码**: ```java @Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES) public void monitorHikariPool() { if (dataSource instanceof HikariDataSource) { HikariDataSource hikariDataSource = (HikariDataSource) dataSource; HikariConfigMXBean config = hikariDataSource.getHikariConfigMXBean(); var poolMXBean = hikariDataSource.getHikariPoolMXBean(); // 检查连接池是否已初始化 if (poolMXBean == null) { log.debug("HikariCP 连接池尚未初始化,跳过监控"); return; } log.info("=== HikariCP 连接池状态 ==="); log.info("连接池名称: {}", config.getPoolName()); log.info("活跃连接数: {}", poolMXBean.getActiveConnections()); log.info("空闲连接数: {}", poolMXBean.getIdleConnections()); log.info("等待获取连接的线程数: {}", poolMXBean.getThreadsAwaitingConnection()); log.info("最大连接数: {}", config.getMaximumPoolSize()); log.info("最小空闲连接数: {}", config.getMinimumIdle()); } } ``` **修复要点**: 1. 先获取 `HikariPoolMXBean` 实例并存储到变量 2. 检查是否为 `null`,为 `null` 则跳过本次监控 3. 使用变量访问连接池信息,避免重复调用 `getHikariPoolMXBean()` #### 修复文件 - `fund-sys/src/main/java/com/fundplatform/sys/config/HikariMonitorConfig.java` #### 经验总结 - **调用可能返回 null 的方法前必须做空值检查** - **定时任务执行时需考虑资源初始化时机**,不能假设资源已就绪 - **使用变量存储对象引用**,避免重复调用 getter 方法 --- ## 预防措施清单 ### 前后端接口对接 | 检查项 | 说明 | |--------|------| | 请求头确认 | 确认所有必需的请求头(X-User-Id、X-Tenant-Id、Authorization等) | | 响应格式确认 | 统一使用 `Result` 包装响应,确认字段命名一致 | | 错误码定义 | 明确各类错误码的含义和处理方式 | ### 前端路由配置 | 检查项 | 说明 | |--------|------| | 代理路径精确匹配 | 使用 `/api/` 带斜杠的形式,避免模糊匹配 | | 路由命名规范 | 前端路由与后端API路径应使用不同的前缀区分 | | 刷新兼容性 | SPA 应用需考虑页面刷新时的路由状态恢复 | ### 后端开发规范 | 检查项 | 说明 | |--------|------| | AOP 依赖引入 | 使用 AOP 需添加 `spring-boot-starter-aop` 依赖 | | Jackson 日期配置 | 序列化 Java 8 日期类型需注册 `JavaTimeModule` | | 日志独立输出 | 使用 Logger name 隔离,配置独立的 appender | | 外键字段类型 | 使用雪花 ID 的外键字段必须使用 Long 类型 | | Feign 拦截器注册 | Feign 拦截器必须添加@Component 注解并配置组件扫描 | | TraceId 传递 | ContextInterceptor 必须提取并设置 TraceId | | **FeignClient 配置** | **有注册中心时必须移除 url 属性,仅保留 name** | | **Nacos 3.0 认证** | **客户端必须配置 username 和 password(默认都是 nacos)** | | **定时任务资源检查** | **定时任务访问资源前需检查资源是否已初始化(如连接池)** | ### 功能开发流程 | 检查项 | 说明 | |--------|------| | UI交互完整性 | 所有菜单、按钮的点击事件都应有对应实现 | | 自测覆盖 | 代码提交前进行基础功能自测 | | 刷新测试 | 重点测试页面刷新后的状态是否正常 | --- ## 相关文件索引 ### 本次问题修复涉及的文件 **后端文件:** - `fund-sys/pom.xml` - 添加 AOP 和 Jackson 依赖 - `fund-sys/src/main/java/com/fundplatform/sys/aop/ApiLogAspect.java` - AOP 日志切面 - `fund-sys/src/main/resources/logback-spring.xml` - 日志配置 - `fund-exp/src/main/java/com/fundplatform/exp/dto/FundExpenseDTO.java` - 支出 DTO expenseType 字段类型修复 - `fund-common/src/main/java/com/fundplatform/common/feign/FeignChainInterceptor.java` - Feign 拦截器添加@Component 注解 - `fund-report/src/main/java/com/fundplatform/report/ReportApplication.java` - 配置组件扫描路径 - `fund-common/src/main/java/com/fundplatform/common/web/ContextInterceptor.java` - 添加 TraceId 提取与清理逻辑 - `fund-report/src/main/java/com/fundplatform/report/feign/ExpenseFeignClient.java` - 移除硬编码 URL,使用 Nacos 服务发现 - `fund-report/src/main/java/com/fundplatform/report/feign/ReceivableFeignClient.java` - 移除硬编码 URL,使用 Nacos 服务发现 - `fund-report/src/main/java/com/fundplatform/report/feign/ProjectFeignClient.java` - 移除硬编码 URL,使用 Nacos 服务发现 - `fund-cust/src/main/java/com/fundplatform/cust/feign/SysServiceClient.java` - 移除硬编码 URL,使用 Nacos 服务发现 - `fund-*/src/main/resources/application.yml` - 为所有业务模块添加 Nacos 3.0 username/password 认证配置 **前端文件:** - `fund-admin/vite.config.ts` - 代理配置修复 - `fund-admin/src/router/index.ts` - 路由配置 - `fund-admin/src/layouts/MainLayout.vue` - 菜单事件处理 - `fund-admin/src/api/request.ts` - 请求拦截器 - `fund-admin/src/stores/user.ts` - 用户状态管理 --- ## 附录:常见错误速查 | 错误信息 | 可能原因 | 解决方案 | |----------|----------|----------| | `400 Bad Request` | 缺少必需请求头 | 检查X-User-Id、X-Tenant-Id等 | | `404 Not Found (刷新后)` | 代理路径冲突 | 使用精确匹配,区分前后端路由 | | `Java 8 date/time type not supported` | Jackson未配置日期模块 | 注册JavaTimeModule | | `ClassNotFoundException: Aspect` | 未引入AOP依赖 | 添加spring-boot-starter-aop | | `JSON parse error` | 字段类型不匹配(Integer vs Long) | 雪花ID外键必须使用Long类型 | | `Feign 调用未透传上下文` | 拦截器未注册为 Bean | 添加@Component 注解并配置扫描 | | `TraceId 链路断裂` | ContextInterceptor 未提取 TraceId | 在 preHandle 中添加 TraceId 设置逻辑 | | `服务发现失效` | FeignClient 硬编码 URL | 移除 url 属性,仅保留 name 使用 Nacos 发现 | | `Nacos 注册失败 (认证错误)` | 缺少 username/password 配置 | 在 discovery 节点添加 username 和 password | | `HikariPoolMXBean NullPointerException` | 定时任务执行时连接池未初始化 | 添加 poolMXBean 空值检查 | --- > **备注**: 本文档将根据后续开发过程中的问题持续更新。