Skip to content

Latest commit

 

History

History
227 lines (185 loc) · 5.42 KB

File metadata and controls

227 lines (185 loc) · 5.42 KB

组合操作API参数优化说明

问题描述

在使用 /api/excel/operation 接口时,如果只在外层指定 fileName,会收到参数校验失败的错误:

{
  "success": false,
  "message": "参数校验失败: 文件名不能为空; 文件名不能为空",
  "data": null
}

错误原因: Spring的 @Valid 注解会在方法执行进行参数校验,而自动传递 fileName 的逻辑在方法内部,导致校验时 fileName 还是空的。

修复方式:

  1. 移除了 ExcelWriteRequestExcelReadRequestfileName 字段的 @NotBlank 验证注解
  2. /write/read 接口中添加了手动验证
  3. /operation 接口会自动传递外层的 fileName

解决方案

✅ 已优化(v1.2.1)

现在只需在外层指定一次 fileName,系统会自动传递给内部的 writeRequestreadRequest

优化后的请求格式:

{
  "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);
}

兼容性说明

向后兼容 ✅

如果你在 writeRequestreadRequest 内部显式指定了 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": [...]
  }
}

测试建议

在Web管理后台测试

  1. 访问:http://localhost:8080/admin/test
  2. 选择Token
  3. 选择接口:写入并读取(组合操作)
  4. 点击"📝 加载示例"
  5. 注意示例中只有一个 fileName 字段
  6. 点击"🚀 发送请求"
  7. 验证成功响应

使用curl测试

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


立即重启应用以使用新功能! 🚀