# getSiteInfo 接口重新设计 - 彻底解决空值异常 ## 问题描述 `/api/cms/website/getSiteInfo` 接口持续报错: ``` code: 1 error: "java.lang.IllegalArgumentException: Value must not be null!" message: "操作失败" ``` ## 解决方案 **完全重新设计接口**,采用防御性编程和现代化时间处理方式。 ## 重新设计思路 ### 1. 防御性编程 - **全面异常捕获**: 每个步骤都有 try-catch 保护 - **空值安全**: 所有方法都进行空值检查 - **兜底策略**: 每个功能都有默认值或降级方案 ### 2. 现代化时间处理 - **使用 LocalDateTime**: 替代过时的 DateTime - **标准化格式**: 统一使用 ISO 8601 格式 - **时区安全**: 避免时区相关的问题 ### 3. 分层错误处理 - **接口层**: 捕获所有异常,返回友好错误信息 - **业务层**: 各个功能模块独立处理异常 - **数据层**: 安全的数据访问和转换 ## 重新设计内容 ### 1. 主接口重构 (`getSiteInfo`) ```java @GetMapping("/getSiteInfo") public ApiResult getSiteInfo() { try { // 1. 安全获取租户ID Integer tenantId = getTenantId(); if (ObjectUtil.isEmpty(tenantId)) { return fail("租户ID不能为空", null); } // 2. 安全查询数据库 CmsWebsite website = cmsWebsiteService.getOne( new LambdaQueryWrapper() .eq(CmsWebsite::getTenantId, tenantId) .eq(CmsWebsite::getDeleted, 0) .last("limit 1") ); // 3. 安全构建网站信息 buildSafeWebsiteInfo(website); return success(website); } catch (Exception e) { log.error("获取网站信息异常: {}", e.getMessage(), e); return fail("获取网站信息失败: " + e.getMessage(), null); } } ``` ### 2. 安全构建方法 (`buildSafeWebsiteInfo`) - **模块化处理**: 每个功能独立处理,互不影响 - **异常隔离**: 单个模块失败不影响其他模块 - **默认值策略**: 每个模块都有合理的默认值 ### 3. 现代化时间处理 (`buildSafeServerTime`) ```java // 使用 LocalDateTime 替代 DateTime java.time.LocalDateTime now = java.time.LocalDateTime.now(); java.time.LocalDate today = java.time.LocalDate.now(); serverTime.put("now", now.toString()); // ISO 8601 格式 serverTime.put("today", today.toString()); // yyyy-MM-dd 格式 serverTime.put("timestamp", System.currentTimeMillis()); ``` ### 4. 安全的导航处理 (`setSafeWebsiteNavigation`) - **双重保护**: 数据获取和树构建都有异常处理 - **降级策略**: 树构建失败时使用平铺列表 - **空值安全**: 确保返回值永远不为 null ### 5. 安全的配置构建 (`buildSafeWebsiteConfig`) - **字段安全**: 检查字段名和值的有效性 - **域名兜底**: 提供默认域名生成策略 - **配置隔离**: 单个配置项失败不影响整体 ## 新增的安全方法 ### 1. `buildSafeWebsiteInfo(CmsWebsite website)` - 统一的网站信息构建入口 - 模块化处理各个功能 - 全面的异常处理和日志记录 ### 2. `buildSafeWebsiteConfig(CmsWebsite website)` - 安全的配置信息构建 - 字段有效性检查 - 域名信息兜底策略 ### 3. `setSafeWebsiteNavigation(CmsWebsite website)` - 安全的导航信息设置 - 双重异常保护 - 树构建失败时的降级策略 ### 4. `buildSafeServerTime()` - 使用现代化的 LocalDateTime - ISO 8601 标准时间格式 - 完整的异常处理 ### 5. `getSafeSysDomain(CmsWebsite website)` 和 `getSafeDomain(CmsWebsite website)` - 安全的域名生成 - 多层空值检查 - 默认域名兜底策略 ## 技术改进 ### 1. 时间处理现代化 ```java // 旧方式 (可能有问题) DateTime date = DateUtil.date(); String today = DateUtil.today(); // 新方式 (安全可靠) LocalDateTime now = LocalDateTime.now(); LocalDate today = LocalDate.now(); ``` ### 2. 异常处理分层 ```java // 接口层 - 捕获所有异常 try { buildSafeWebsiteInfo(website); return success(website); } catch (Exception e) { return fail("获取网站信息失败: " + e.getMessage(), null); } // 业务层 - 模块化异常处理 try { setWebsiteStatus(website); } catch (Exception e) { log.warn("设置网站状态失败: {}", e.getMessage()); website.setStatus(0); // 默认状态 } ``` ### 3. 空值安全策略 ```java // 确保返回值永远不为 null if (topNavs != null && !topNavs.isEmpty()) { website.setTopNavs(CommonUtil.toTreeData(topNavs, ...)); } else { website.setTopNavs(new ArrayList<>()); } ``` ## 测试建议 1. **正常场景**: 测试有完整站点数据的租户 2. **异常场景**: 测试没有站点数据的租户 3. **边界场景**: 测试站点数据不完整的情况 4. **多租户场景**: 测试不同租户之间的数据隔离 5. **性能场景**: 测试大量导航数据的处理 6. **时间场景**: 测试不同时区的时间处理 ## 影响范围 - ✅ **彻底解决** `getSiteInfo` 接口的空值异常 - ✅ **现代化** 时间处理方式,使用 LocalDateTime - ✅ **增强** 系统整体稳定性和健壮性 - ✅ **改善** 错误日志的可读性和调试能力 - ✅ **保持** 向后兼容,不影响现有功能 - ✅ **提升** 多租户数据安全性