在使用 /api/excel/operation 接口时,如果只在外层指定 fileName,会收到参数校验失败的错误:
{
"success": false,
"message": "参数校验失败: 文件名不能为空; 文件名不能为空",
"data": null
}错误原因: Spring的 @Valid 注解会在方法执行前进行参数校验,而自动传递 fileName 的逻辑在方法内部,导致校验时 fileName 还是空的。
修复方式:
- 移除了
ExcelWriteRequest和ExcelReadRequest中fileName字段的@NotBlank验证注解 - 在
/write和/read接口中添加了手动验证 /operation接口会自动传递外层的fileName
现在只需在外层指定一次 fileName,系统会自动传递给内部的 writeRequest 和 readRequest。
优化后的请求格式:
{
"fileName": "公式.xlsx",
"writeRequest": {
"sheetName": "伤寒法要",
"cells": [
{
"cellAddress": "D8",
"value": "女",
"valueType": "STRING"
},
{
"cellAddress": "D9",
"value": "戌",
"valueType": "STRING"
},
{
"cellAddress": "F8",
"value": "庚",
"valueType": "STRING"
}
]
},
"readRequest": {
"sheetName": "伤寒法要",
"cells": [
{
"cellAddress": "I8"
},
{
"cellAddress": "I9"
},
{
"cellAddress": "I10"
},
{
"cellAddress": "I11"
},
{
"cellAddress": "I12"
}
],
"readFormula": true
}
}关键变化:
- ✅ 无需在
writeRequest中指定fileName - ✅ 无需在
readRequest中指定fileName - ✅ 只需在外层指定一次
fileName,简洁明了
在 ExcelController.performOperation() 方法中添加了自动传递逻辑:
@PostMapping("/operation")
public ResponseEntity<ExcelResponse> performOperation(
@Valid @RequestBody ExcelOperationRequest request) {
log.info("接收操作请求: 文件={}", request.getFileName());
// 自动将外层的fileName传递给内部的writeRequest和readRequest
if (request.getWriteRequest() != null && request.getWriteRequest().getFileName() == null) {
request.getWriteRequest().setFileName(request.getFileName());
}
if (request.getReadRequest() != null && request.getReadRequest().getFileName() == null) {
request.getReadRequest().setFileName(request.getFileName());
}
ExcelResponse response = excelService.writeAndRead(
request.getWriteRequest(),
request.getReadRequest()
);
return ResponseEntity.ok(response);
}如果你在 writeRequest 或 readRequest 内部显式指定了 fileName,系统会优先使用内部指定的值,不会覆盖。
仍然支持的旧格式:
{
"fileName": "outer.xlsx",
"writeRequest": {
"fileName": "inner.xlsx", // 会使用这个值
"sheetName": "Sheet1",
"cells": [...]
},
"readRequest": {
"fileName": "inner.xlsx", // 会使用这个值
"sheetName": "Sheet1",
"cells": [...]
}
}只在外层指定 fileName,简洁清晰:
{
"fileName": "data.xlsx",
"writeRequest": {
"sheetName": "Sheet1",
"cells": [...]
},
"readRequest": {
"sheetName": "Sheet1",
"cells": [...]
}
}在内部重复指定 fileName,代码冗余:
{
"fileName": "data.xlsx",
"writeRequest": {
"fileName": "data.xlsx", // 不必要的重复
"sheetName": "Sheet1",
"cells": [...]
},
"readRequest": {
"fileName": "data.xlsx", // 不必要的重复
"sheetName": "Sheet1",
"cells": [...]
}
}- 访问:
http://localhost:8080/admin/test - 选择Token
- 选择接口:
写入并读取(组合操作) - 点击"📝 加载示例"
- 注意示例中只有一个
fileName字段 - 点击"🚀 发送请求"
- 验证成功响应
curl -X POST "http://localhost:8080/api/excel/operation" \
-H "X-API-Token: tk_your_token_here" \
-H "Content-Type: application/json" \
-d '{
"fileName": "test.xlsx",
"writeRequest": {
"sheetName": "Sheet1",
"cells": [
{"cellAddress": "A1", "value": 10, "valueType": "NUMBER"},
{"cellAddress": "A2", "value": 20, "valueType": "NUMBER"},
{"cellAddress": "A3", "value": "=A1+A2", "valueType": "FORMULA"}
]
},
"readRequest": {
"sheetName": "Sheet1",
"cells": [{"cellAddress": "A3"}],
"readFormula": false
}
}'✅ 优化前: 需要在3个地方指定 fileName(外层 + writeRequest + readRequest)
✅ 优化后: 只需在1个地方指定 fileName(外层),自动传递
✅ 兼容性: 完全向后兼容,不影响现有代码
✅ 生效版本: v1.2.1
立即重启应用以使用新功能! 🚀