You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5.2 KiB
5.2 KiB
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
)
@GetMapping("/getSiteInfo")
public ApiResult<CmsWebsite> getSiteInfo() {
try {
// 1. 安全获取租户ID
Integer tenantId = getTenantId();
if (ObjectUtil.isEmpty(tenantId)) {
return fail("租户ID不能为空", null);
}
// 2. 安全查询数据库
CmsWebsite website = cmsWebsiteService.getOne(
new LambdaQueryWrapper<CmsWebsite>()
.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
)
// 使用 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. 时间处理现代化
// 旧方式 (可能有问题)
DateTime date = DateUtil.date();
String today = DateUtil.today();
// 新方式 (安全可靠)
LocalDateTime now = LocalDateTime.now();
LocalDate today = LocalDate.now();
2. 异常处理分层
// 接口层 - 捕获所有异常
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. 空值安全策略
// 确保返回值永远不为 null
if (topNavs != null && !topNavs.isEmpty()) {
website.setTopNavs(CommonUtil.toTreeData(topNavs, ...));
} else {
website.setTopNavs(new ArrayList<>());
}
测试建议
- 正常场景: 测试有完整站点数据的租户
- 异常场景: 测试没有站点数据的租户
- 边界场景: 测试站点数据不完整的情况
- 多租户场景: 测试不同租户之间的数据隔离
- 性能场景: 测试大量导航数据的处理
- 时间场景: 测试不同时区的时间处理
影响范围
- ✅ 彻底解决
getSiteInfo
接口的空值异常 - ✅ 现代化 时间处理方式,使用 LocalDateTime
- ✅ 增强 系统整体稳定性和健壮性
- ✅ 改善 错误日志的可读性和调试能力
- ✅ 保持 向后兼容,不影响现有功能
- ✅ 提升 多租户数据安全性