6.8 KiB
6.8 KiB
Banner管理API Bug修复报告
🐛 问题描述
错误1: 批量排序验证失败
PUT /admin/banners/batch-sort
HandlerMethodValidationException: 400 BAD_REQUEST "Validation failure"
根本原因:
- 前端发送的数据格式与
BannerUpdateDto的验证要求不匹配 BannerUpdateDto包含过多必填字段,而批量排序只需要id和sortOrder
错误2: 状态切换接口不存在
PUT /admin/banners/status
HttpRequestMethodNotSupportedException: Request method 'PUT' is not supported
根本原因:
- 控制器中缺少
/status接口 - 前端调用的接口在后端没有实现
✅ 修复方案
1. 创建专用DTO
新增 BannerSortDto.java
@Data
@Schema(description = "Banner排序请求")
public class BannerSortDto {
@NotNull(message = "Banner ID不能为空")
private Long id;
@NotNull(message = "排序值不能为空")
@Min(value = 0, message = "排序值不能小于0")
private Integer sortOrder;
}
新增 BannerStatusDto.java
@Data
@Schema(description = "Banner状态请求")
public class BannerStatusDto {
@NotNull(message = "Banner ID不能为空")
private Long id;
@NotNull(message = "状态不能为空")
private Boolean isEnabled;
}
2. 更新控制器接口
修改批量排序接口
@PutMapping("/batch-sort")
public Result<Void> batchUpdateSortOrder(@Valid @RequestBody List<BannerSortDto> sortDtos) {
log.info("管理员批量更新Banner排序: size={}", sortDtos.size());
bannerService.batchUpdateSortOrder(sortDtos);
return Result.success(null);
}
新增状态切换接口
@PutMapping("/status")
public Result<Void> updateBannerStatus(@Valid @RequestBody BannerStatusDto statusDto) {
log.info("管理员更新Banner状态: id={}, enabled={}", statusDto.getId(), statusDto.getIsEnabled());
bannerService.updateBannerStatus(statusDto.getId(), statusDto.getIsEnabled());
return Result.success(null);
}
3. 更新服务层
修改服务接口
// 修改批量排序方法签名
void batchUpdateSortOrder(List<BannerSortDto> sortDtos);
// 新增状态更新方法
void updateBannerStatus(Long id, Boolean isEnabled);
更新服务实现
@Override
@Transactional
public void batchUpdateSortOrder(List<BannerSortDto> sortDtos) {
if (sortDtos == null || sortDtos.isEmpty()) {
throw new BusinessException("批量更新数据不能为空");
}
List<Banner> banners = sortDtos.stream().map(sortDto -> {
Banner banner = new Banner();
banner.setId(sortDto.getId());
banner.setSortOrder(sortDto.getSortOrder());
banner.setUpdateTime(LocalDateTime.now());
return banner;
}).toList();
int result = bannerMapper.batchUpdateSortOrder(banners);
if (result <= 0) {
throw new BusinessException("批量更新排序失败");
}
log.info("批量更新Banner排序成功: size={}", sortDtos.size());
}
@Override
@Transactional
public void updateBannerStatus(Long id, Boolean isEnabled) {
Banner existingBanner = bannerMapper.selectById(id);
if (existingBanner == null) {
throw new BusinessException("Banner不存在");
}
Banner banner = new Banner();
banner.setId(id);
banner.setIsEnabled(Boolean.TRUE.equals(isEnabled) ? 1 : 0);
banner.setUpdateTime(LocalDateTime.now());
int result = bannerMapper.updateById(banner);
if (result <= 0) {
throw new BusinessException("更新Banner状态失败");
}
log.info("更新Banner状态成功: id={}, enabled={}", id, isEnabled);
}
🧪 测试验证
测试页面
创建了 test_banner_admin.html 测试页面,包含:
- 📄 Banner列表加载
- 🔢 批量排序测试
- 🔄 状态切换测试
- 📊 实时结果显示
测试用例
1. 批量排序测试
// 请求数据格式
PUT /admin/banners/batch-sort
[
{"id": 1, "sortOrder": 1},
{"id": 2, "sortOrder": 2},
{"id": 3, "sortOrder": 3}
]
// 预期响应
{
"code": 200,
"message": "操作成功",
"data": null
}
2. 状态切换测试
// 请求数据格式
PUT /admin/banners/status
{
"id": 1,
"isEnabled": false
}
// 预期响应
{
"code": 200,
"message": "操作成功",
"data": null
}
📊 修复前后对比
修复前
| 接口路径 | 状态 | 问题 |
|---|---|---|
PUT /admin/banners/batch-sort |
❌ 失败 | 参数验证失败 |
PUT /admin/banners/status |
❌ 失败 | 接口不存在 |
修复后
| 接口路径 | 状态 | 功能 |
|---|---|---|
PUT /admin/banners/batch-sort |
✅ 正常 | 批量更新排序 |
PUT /admin/banners/status |
✅ 正常 | 状态切换 |
🛡️ 安全性
权限验证
- ✅ 所有接口都使用
@RequireAdminOrStaff注解 - ✅ 需要有效的管理员JWT Token
- ✅ 自动记录操作日志
数据验证
- ✅ 使用专用DTO进行参数验证
- ✅ 数据库操作前检查记录存在性
- ✅ 事务保护确保数据一致性
🚀 使用指南
前端调用示例
批量排序
const sortData = [
{id: 1, sortOrder: 1},
{id: 2, sortOrder: 2}
];
const response = await fetch('/admin/banners/batch-sort', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(sortData)
});
状态切换
const statusData = {
id: 1,
isEnabled: false
};
const response = await fetch('/admin/banners/status', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(statusData)
});
📋 文件清单
新增文件
- ✅
src/main/java/com/dora/dto/BannerSortDto.java - ✅
src/main/java/com/dora/dto/BannerStatusDto.java - ✅
src/main/resources/static/test_banner_admin.html
修改文件
- ✅
src/main/java/com/dora/controller/AdminBannerController.java - ✅
src/main/java/com/dora/service/BannerService.java - ✅
src/main/java/com/dora/service/impl/BannerServiceImpl.java
🎯 总结
✅ 修复成果
- 参数验证优化: 创建专用DTO,避免过度验证
- 接口完整性: 补充缺失的状态切换接口
- 错误处理: 增强异常处理和日志记录
- 测试支持: 提供完整的测试页面
🚨 注意事项
- 参数格式: 确保前端发送的数据格式与DTO要求一致
- 权限验证: 所有操作都需要管理员权限
- 数据一致性: 批量操作使用事务保护
- 错误处理: 详细的错误信息便于问题排查
修复状态: ✅ 已完成
测试状态: ✅ 已验证
风险等级: 低(不影响现有功能)
部署要求: 重启服务器使修改生效