【导入导出】功能设计方案(Java版)

通用导入导出功能设计方案

一、数据库设计

1、数据库ER图

erDiagram excel_config ||--o{ sheet_config : "1:n" sheet_config ||--o{ column_config : "1:n" excel_config ||--o{ export_column_config : "1:n" excel_config ||--o{ export_condition : "1:n" sheet_config ||--o{ import_validation : "1:n" excel_config { BIGINT config_id PK VARCHAR(50) business_key BOOLEAN template_mode BOOLEAN import_mode BOOLEAN export_mode VARCHAR(20) sheet_strategy } sheet_config { BIGINT sheet_id PK BIGINT config_id FK VARCHAR(100) sheet_pattern INTEGER start_row VARCHAR(100) target_table } column_config { BIGINT column_id PK BIGINT sheet_id FK VARCHAR(5) excel_col VARCHAR(100) db_column VARCHAR(20) data_type VARCHAR(100) format_pattern } export_column_config { BIGINT export_id PK BIGINT config_id FK VARCHAR(100) db_column VARCHAR(100) excel_header INTEGER display_order VARCHAR(100) format_pattern } import_validation { BIGINT validation_id PK BIGINT sheet_id FK VARCHAR(20) rule_type TEXT rule_expression VARCHAR(255) error_message } export_condition { BIGINT condition_id PK BIGINT config_id FK VARCHAR(50) param_name VARCHAR(20) data_type BOOLEAN required }

2、完整表结构DDL

sql 复制代码
-- 主配置表
CREATE TABLE excel_config (
  config_id BIGSERIAL PRIMARY KEY,
  business_key VARCHAR(50) UNIQUE NOT NULL,
  template_mode BOOLEAN DEFAULT FALSE,
  import_mode BOOLEAN DEFAULT FALSE,
  export_mode BOOLEAN DEFAULT FALSE,
  sheet_strategy VARCHAR(20) CHECK (sheet_strategy IN ('first','all','by_name')),
  file_types VARCHAR(50)[] CHECK (file_types <@ ARRAY['xls','xlsx','csv']),
  version INTEGER DEFAULT 1 NOT NULL
);
​
COMMENT ON TABLE excel_config IS '核心配置表';
COMMENT ON COLUMN excel_config.sheet_strategy IS '多Sheet处理策略';
​
-- Sheet配置表
CREATE TABLE sheet_config (
  sheet_id BIGSERIAL PRIMARY KEY,
  config_id BIGINT NOT NULL REFERENCES excel_config(config_id),
  sheet_pattern VARCHAR(100),
  start_row INTEGER DEFAULT 1 NOT NULL,
  end_row_detect BOOLEAN DEFAULT TRUE,
  target_table VARCHAR(100) NOT NULL,
  UNIQUE(config_id, sheet_pattern)
);
​
COMMENT ON COLUMN sheet_config.end_row_detect IS '自动检测结束行';
​
-- 列配置表
CREATE TABLE column_config (
  column_id BIGSERIAL PRIMARY KEY,
  sheet_id BIGINT NOT NULL REFERENCES sheet_config(sheet_id),
  excel_col VARCHAR(5) NOT NULL CHECK (excel_col ~ '^[A-Z]+$'),
  db_column VARCHAR(100) NOT NULL,
  data_type VARCHAR(20) CHECK (data_type IN ('string','number','date','boolean')),
  required BOOLEAN DEFAULT FALSE,
  format_pattern VARCHAR(100),
  header_style VARCHAR(50),
  data_style VARCHAR(50),
  UNIQUE(sheet_id, excel_col)
);
​
-- 导出列配置表
CREATE TABLE export_column_config (
  export_id BIGSERIAL PRIMARY KEY,
  config_id BIGINT NOT NULL REFERENCES excel_config(config_id),
  db_column VARCHAR(100) NOT NULL,
  excel_header VARCHAR(100) NOT NULL,
  display_order INTEGER NOT NULL CHECK (display_order > 0),
  format_pattern VARCHAR(100),
  security_level INTEGER CHECK (security_level BETWEEN 1 AND 3),
  mask_pattern VARCHAR(100),
  permission_code VARCHAR(50),
  UNIQUE(config_id, db_column)
);
​
-- 导入验证规则表
CREATE TABLE import_validation (
  validation_id BIGSERIAL PRIMARY KEY,
  sheet_id BIGINT REFERENCES sheet_config(sheet_id),
  rule_type VARCHAR(50) NOT NULL CHECK (rule_type IN ('file','sheet','cell','business')),
  rule_expression TEXT NOT NULL,
  error_message VARCHAR(255) NOT NULL,
  CONSTRAINT valid_sheet CHECK (
    (rule_type = 'file' AND sheet_id IS NULL) OR 
    (rule_type != 'file' AND sheet_id IS NOT NULL)
  )
);
​
-- 导出条件表
CREATE TABLE export_condition (
  condition_id BIGSERIAL PRIMARY KEY,
  config_id BIGINT NOT NULL REFERENCES excel_config(config_id),
  param_name VARCHAR(50) NOT NULL,
  data_type VARCHAR(20) CHECK (data_type IN ('date','number','string')),
  required BOOLEAN DEFAULT FALSE,
  default_value VARCHAR(100),
  UNIQUE(config_id, param_name)
);

3、索引建议

sql 复制代码
-- 主表索引
CREATE INDEX idx_business_key ON excel_config(business_key);
CREATE INDEX idx_sheet_mapping ON sheet_config(config_id, target_table);
​
-- 导出配置索引
CREATE INDEX idx_export_order ON export_column_config(config_id, display_order);
CREATE INDEX idx_export_security ON export_column_config(security_level);
​
-- 导入验证索引
CREATE INDEX idx_validation_type ON import_validation(rule_type);
CREATE INDEX idx_sheet_validations ON import_validation(sheet_id);
​
-- 导出条件索引
CREATE INDEX idx_export_params ON export_condition(config_id, param_name);

4、使用示例

场景1:合同模板配置(模板导出)
sql 复制代码
-- 启用模板模式
INSERT INTO excel_config (business_key, template_mode, sheet_strategy)
VALUES ('contract', TRUE, 'by_name');
​
-- 配置Sheet
INSERT INTO sheet_config (config_id, sheet_pattern, target_table)
VALUES (1, '^合同主表$', 'contract_main');
​
-- 配置列
INSERT INTO column_config (sheet_id, excel_col, db_column, data_type, format_pattern)
VALUES 
(1, 'A', 'contract_no', 'string', 'text'),
(1, 'B', 'sign_date', 'date', 'yyyy-MM-dd');
场景2:数据导入验证规则
sql 复制代码
-- 文件级验证
INSERT INTO import_validation (rule_type, rule_expression, error_message)
VALUES 
('file', 'size < 10485760', '文件大小不能超过10MB'),
('file', 'fileType IN (xlsx)', '仅支持xlsx格式');
​
-- 列级验证
INSERT INTO import_validation (sheet_id, rule_type, rule_expression, error_message)
VALUES 
(1, 'cell', 'regex:^HT\d{8}$', '合同编号格式错误'),
(1, 'cell', 'range:amount > 0', '金额必须大于0');
场景3:数据导出配置
sql 复制代码
-- 导出列配置
INSERT INTO export_column_config 
(config_id, db_column, excel_header, display_order, security_level)
VALUES
(1, 'contract_no', '合同编号', 1, 1),
(1, 'amount', '合同金额', 2, 2);
​
-- 导出条件
INSERT INTO export_condition 
(config_id, param_name, data_type, required)
VALUES
(1, 'start_date', 'date', TRUE),
(1, 'end_date', 'date', TRUE);

5、典型查询示例

获取完整导出配置
sql 复制代码
SELECT 
  ec.business_key,
  ecc.excel_header,
  ecc.db_column,
  ecc.format_pattern,
  excon.param_name
FROM excel_config ec
JOIN export_column_config ecc USING (config_id)
LEFT JOIN export_condition excon USING (config_id)
WHERE ec.business_key = 'contract'
ORDER BY ecc.display_order;
获取导入验证规则
sql 复制代码
SELECT 
  iv.rule_type,
  iv.rule_expression,
  iv.error_message,
  s.sheet_pattern
FROM import_validation iv
LEFT JOIN sheet_config s USING (sheet_id)
WHERE s.config_id = 1
ORDER BY 
  CASE iv.rule_type
    WHEN 'file' THEN 1
    WHEN 'sheet' THEN 2
    WHEN 'cell' THEN 3
    ELSE 4
  END;

二、核心设计

1、类设计

typescript 复制代码
classDiagram
    direction TB
    
    class BaseExcelController {
        <<abstract>>
        #excelService: ExcelService
        +exportTemplate(HttpServletResponse, String): void
        +importData(MultipartFile, String): Result<?>
        +exportData(HttpServletResponse, ExportRequest): void
        #getDictService()*: DictService
        #beforeImport(ImportContext): void
        #afterExport(ExportContext): void
    }
    
    class ContractController {
        +ContractController()
        +customExport(HttpServletResponse, ContractQuery): void
    }
    
    class ExcelService {
        <<interface>>
        +generateTemplate(HttpServletResponse, String): void
        +processImport(MultipartFile, String): ImportResult
        +processExport(HttpServletResponse, ExportRequest): void
    }
    
    class ExcelServiceImpl {
        -configRepository: ConfigRepository
        -dictService: DictService
        -sqlBuilder: DynamicSQLBuilder
        +validateFile(ValidationContext): boolean
        +parseDataBySheets(ValidationContext): Map~String, List~Map~~
    }
    
    class ValidationHandler {
        <<interface>>
        +validate(ValidationContext): void
        +next(): ValidationHandler
        +setNext(ValidationHandler): void
    }
    
    class FileValidation {
        -next: ValidationHandler
        +doValidate(ValidationContext): void
    }
    
    class SheetValidation {
        -next: ValidationHandler
        +doValidate(ValidationContext): void
    }
    
    class DynamicSQLBuilder {
        +buildInsertSQL(String, Set~String~): String
        +createParameterSource(Map~String,Object~): SqlParameterSource
    }
    
    class ImportContext {
        -file: MultipartFile
        -errors: List~CellError~
        +getParsedData(): Map~String, List~Map~~
        +addError(CellError): void
    }
    
    class ExportContext {
        -queryParams: Map~String, Object~
        -resultSet: Stream~Map~String, Object~~
        +getResultStream(): Stream~Map~String, Object~~
    }
    
    BaseExcelController <|-- ContractController : 继承
    BaseExcelController o--> ExcelService : 依赖
    ExcelServiceImpl ..|> ExcelService : 实现
    ExcelServiceImpl --> DynamicSQLBuilder : 组合
    ExcelServiceImpl --> ConfigRepository : 组合
    ValidationHandler <|.. FileValidation : 实现
    ValidationHandler <|.. SheetValidation : 实现
    FileValidation --> SheetValidation : 责任链
    ExcelServiceImpl --> ValidationHandler : 使用
    ImportContext <.. ExcelServiceImpl : 创建
    ExportContext <.. ExcelServiceImpl : 创建
关键设计说明:
  1. 继承结构

    复制代码
    BaseExcelController
    
    ContractController
    • 具体业务控制器(如 ContractController)继承自基类 BaseExcelController

    • 必须实现抽象方法:

      csharp 复制代码
      protected abstract DictService getDictService();
  2. 策略模式集成

    复制代码
    BaseExcelController
    
    ExcelService
    
    ExcelServiceImpl
    • 通过依赖注入的 ExcelService 实现三大场景核心逻辑

    • 具体实现类 ExcelServiceImpl 包含:

      java 复制代码
      public class ExcelServiceImpl implements ExcelService {
          // 主要组件
          private final ConfigRepository configRepository;
          private final DynamicSQLBuilder sqlBuilder;
          
          // 批处理方法
          private void batchInsertMultiTable(...);
      }
  3. 验证责任链

    复制代码
    ValidationHandler
    
    FileValidation
    
    SheetValidation
    • 验证流程按 File → Sheet → Cell → Business 顺序执行

    • 验证器类的主要方法:

      scala 复制代码
      public class FileValidation extends ValidationChain {
          @Override
          protected void doValidate(ValidationContext ctx) {
              // 1. 校验文件类型/大小
              // 2. 校验文件数字签名
          }
      }
  4. 上下文对象

    复制代码
    ImportContext
    
    ExcelServiceImpl
    
    ExportContext
    • ImportContext 封装导入过程数据:

      swift 复制代码
      public class ImportContext {
          private final MultipartFile file;
          private List<CellError> errors;
          private Map<String, Object> parsedData;
      }
    • ExportContext 封装导出查询参数:

      typescript 复制代码
      public class ExportContext {
          private Map<String, Object> queryParams;
          private Stream<Map<String, Object>> resultStream;
      }
典型调用流程示例
java 复制代码
JdbcTemplateDynamicSQLBuilderValidationHandlerExcelServiceContractControllerClientJdbcTemplateDynamicSQLBuilderValidationHandlerExcelServiceContractControllerClientalt[验证失败][验证成功]POST /contract/import + Excel文件processImport(file, "contract")执行验证链返回错误列表错误结果buildInsertSQL()生成动态SQL批量插入数据插入结果成功结果返回响应

2、BaseController核心设计

less 复制代码
public abstract class BaseExcelController {
    
    @Autowired
    protected ExcelService excelService;
    
    // 导出模板
    @GetMapping("/template")
    public void exportTemplate(HttpServletResponse response, 
                              @RequestParam String businessKey) {
        excelService.generateTemplate(response, businessKey);
    }
    
    // 导入数据
    @PostMapping("/import")
    public Result<?> importData(@RequestParam MultipartFile file,
                               @RequestParam String businessKey) {
        ImportResult result = excelService.processImport(file, businessKey);
        return Result.success(result);
    }
    
    // 导出数据
    @PostMapping("/export")
    public void exportData(HttpServletResponse response,
                          @RequestBody ExportRequest request) {
        excelService.processExport(response, request);
    }
    
    // 需要子类实现的钩子方法
    protected abstract DictService getDictService();
    protected void beforeImport(ImportContext context) {}
    protected void afterExport(ExportContext context) {}
}

3、验证流程设计(责任链模式)

3.1. 验证处理器接口
csharp 复制代码
public interface ValidationHandler {
    void validate(ValidationContext context);
    ValidationHandler next();
    ValidationHandler setNext(ValidationHandler next);
}

// 基础验证链
public class ValidationChain implements ValidationHandler {
    private ValidationHandler next;
    
    public void validate(ValidationContext context) {
        doValidate(context);
        if (next != null) {
            next.validate(context);
        }
    }
    
    protected abstract void doValidate(ValidationContext context);
}
3.2. 多级验证实现
scala 复制代码
// 文件验证
public class FileValidation extends ValidationChain {
    protected void doValidate(ValidationContext ctx) {
        // 验证文件类型、大小、病毒扫描等
    }
}

// Sheet验证
public class SheetValidation extends ValidationChain {
    protected void doValidate(ValidationContext ctx) {
        // Sheet数量、名称匹配等
    }
}

// 单元格验证
public class CellValidation extends ValidationChain {
    private final DictService dictService;
    
    protected void doValidate(ValidationContext ctx) {
        ctx.getRowData().forEach((col, value) -> {
            validateDataType(colConfig, value);
            validateDict(colConfig, value);
        });
    }
    
    private void validateDict(ColumnConfig config, Object value) {
        if (config.hasDict()) {
            if (!dictService.isValid(config.getDictType(), value)) {
                ctx.addError("无效字典值: " + value);
            }
        }
    }
}

4、动态SQL构建器

4.1. 动态元数据处理
typescript 复制代码
public class DynamicSQLBuilder {
    
    public String buildInsertSQL(String table, Set<String> columns) {
        String fields = String.join(",", columns);
        String placeholders = columns.stream()
            .map(c -> ":" + c)
            .collect(Collectors.joining(","));
        
        return String.format(
            "INSERT INTO %s (%s) VALUES (%s) ON CONFLICT DO NOTHING",
            table, fields, placeholders
        );
    }
    
    public SqlParameterSource createParameterSource(Map<String, Object> row) {
        return new MapSqlParameterSource(row);
    }
}
4.2. 批量插入实现
typescript 复制代码
public class BatchInserter {
    
    @Transactional
    public void batchInsertMultiTable(
        Map<String, List<Map<String, Object>>> dataByTable) {
        
        dataByTable.forEach((table, rows) -> {
            Set<String> columns = rows.get(0).keySet();
            String sql = sqlBuilder.buildInsertSQL(table, columns);
            
            jdbcTemplate.batchUpdate(sql, 
                rows.stream()
                    .map(sqlBuilder::createParameterSource)
                    .toArray(SqlParameterSource[]::new)
            );
        });
    }
}

5、模板生成引擎

5.1. 模板构建实现
scss 复制代码
public class TemplateBuilder {
    
    public Workbook buildTemplate(ExcelConfig config) {
        Workbook workbook = createWorkbook(config);
        
        config.getSheets().forEach(sheet -> {
            Sheet sheet = workbook.createSheet(sheet.getName());
            buildHeaders(sheet, sheet.getColumns());
            addValidations(sheet, sheet.getColumns());
        });
        
        return workbook;
    }
    
    private void addValidations(Sheet sheet, List<ColumnConfig> columns) {
        columns.forEach(col -> {
            if (col.hasDict()) {
                addDropdownValidation(sheet, col);
            }
            if (col.hasRegex()) {
                addRegexValidation(sheet, col);
            }
        });
    }
    
    private void addDropdownValidation(Sheet sheet, ColumnConfig col) {
        DataValidationHelper helper = sheet.getDataValidationHelper();
        String[] dictValues = dictService.getValues(col.getDictType());
        
        DataValidationConstraint constraint = 
            helper.createExplicitListConstraint(dictValues);
        
        CellRangeAddressList addressList = new CellRangeAddressList(
            1, 100000, col.getIndex(), col.getIndex()
        );
        
        sheet.addValidationData(helper.createValidation(constraint, addressList));
    }
}

6、异常处理增强

6.1. 自定义异常
scala 复制代码
public class ExcelException extends RuntimeException {
    private ErrorCode code;
    private List<CellError> errors;
    
    public ExcelException(ErrorCode code, String message) {
        super(message);
        this.code = code;
    }
}

public enum ErrorCode {
    FILE_TYPE_INVALID,
    DATA_VALIDATION_FAILED,
    TEMPLATE_MISMATCH
}
6.2. 全局异常处理
java 复制代码
@ControllerAdvice
public class ExcelExceptionHandler {
    
    @ExceptionHandler(ExcelException.class)
    public ResponseEntity<ErrorResponse> handleExcelException(
        ExcelException ex) {
        
        ErrorResponse response = new ErrorResponse(
            ex.getCode(),
            ex.getMessage(),
            ex.getErrors()
        );
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
            .body(response);
    }
}

7、企业级扩展实现

7.1. 数据加密处理
typescript 复制代码
public class DataMasker {
    
    public Map<String, Object> processRow(Map<String, Object> row, 
                                         List<ColumnConfig> columns) {
        return columns.stream()
            .collect(Collectors.toMap(
                ColumnConfig::getDbColumn,
                col -> maskIfRequired(col, row.get(col.getDbColumn()))
            ));
    }
    
    private Object maskIfRequired(ColumnConfig col, Object value) {
        if (col.needMask()) {
            return MaskUtils.mask(value, col.getMaskPattern());
        }
        return value;
    }
}
6.2. 分布式锁控制
typescript 复制代码
public class ImportLockManager {
    
    public void processWithLock(String businessKey, Runnable task) {
        String lockKey = "import_lock:" + businessKey;
        try {
            if (redisLock.tryLock(lockKey, 30, TimeUnit.SECONDS)) {
                task.run();
            } else {
                throw new BusinessException("存在正在处理的导入任务");
            }
        } finally {
            redisLock.unlock(lockKey);
        }
    }
}

8、性能优化方案

8.1. 流式导出实现
ini 复制代码
public class StreamingExporter {
    
    public void exportLargeData(ExportRequest request, OutputStream output) {
        try (Workbook workbook = new SXSSFWorkbook(100)) {
            Sheet sheet = workbook.createSheet("Data");
            
            jdbcTemplate.queryForStream(
                buildQuerySQL(request), 
                rs -> {
                    Map<String, Object> row = parseRow(rs);
                    writeRow(sheet, row);
                    flushIfNeeded(sheet);
                }
            );
            
            workbook.write(output);
        }
    }
    
    private void flushIfNeeded(SXSSFSheet sheet) {
        if (sheet.getLastRowNum() % 100 == 0) {
            sheet.flushRows(100);
        }
    }
}
8.2. 缓存优化
typescript 复制代码
@Cacheable(value = "excelConfig", key = "#businessKey")
public ExcelConfig loadConfig(String businessKey) {
    return configRepository.findByBusinessKey(businessKey)
           .orElseThrow(() -> new ConfigNotFoundException(businessKey));
}

@Cacheable(value = "dictValues", key = "#dictType")
public String[] getDictValues(String dictType) {
    return dictRepository.findCodesByType(dictType);
}

9、使用示例

less 复制代码
@RestController
@RequestMapping("/contract")
public class ContractController extends BaseExcelController {
    
    @Autowired
    private ContractService contractService;
    
    @Override
    protected DictService getDictService() {
        return contractService.getContractDictService();
    }
    
    @Override
    protected void beforeImport(ImportContext context) {
        context.addParam("currentUser", getCurrentUser());
    }
    
    @PostMapping("/custom-export")
    public void customExport(HttpServletResponse response,
                            @RequestBody ContractQuery query) {
        ExportRequest request = new ExportRequest("contract_export", query);
        super.exportData(response, request);
    }
}

三、验证方案

1、三种场景实现示例

场景1:导出模板

1. 数据库配置

sql 复制代码
-- 主配置
INSERT INTO excel_config (business_key, template_mode, file_types) 
VALUES ('contract_template', true, '{xlsx}');

-- Sheet配置
INSERT INTO sheet_config (config_id, sheet_pattern, target_table) 
VALUES (1, '^合同主表$', 'contract_main');

-- 列配置
INSERT INTO column_config (sheet_id, excel_col, db_column, data_type, format_pattern)
VALUES 
(1, 'A', 'contract_no', 'string', 'text'),
(1, 'B', 'sign_date', 'date', 'yyyy-MM-dd'),
(1, 'C', 'amount', 'number', '#,##0.00');

-- 字典配置示例(假设存在字典表)
INSERT INTO dict_data (dict_type, dict_code, dict_name) 
VALUES 
('contract_type', '01', '采购合同'),
('contract_type', '02', '销售合同');

2. 调用代码

scala 复制代码
@RestController
@RequestMapping("/contract")
public class ContractController extends BaseExcelController {
    
    // 导出模板
    @GetMapping("/template")
    public void downloadTemplate(HttpServletResponse response) {
        exportTemplate(response, "contract_template");
    }
}

3. 输出结果

  • 生成包含以下内容的Excel文件:
lua 复制代码
| 合同编号 | 签订日期  | 合同金额 |
|----------|-----------|----------|
(带数据验证的下拉列表和格式)
场景2:数据导入

1. 数据库配置

sql 复制代码
-- 主配置
UPDATE excel_config SET import_mode = true 
WHERE business_key = 'customer'; 

-- 验证规则
INSERT INTO import_validation (sheet_id, rule_type, rule_expression, error_message) 
VALUES 
(2, 'cell', 'regex:^[A-Za-z0-9]+$', '客户编码格式错误'),
(2, 'cell', 'dict:customer_level', '无效客户等级'),
(2, 'file', 'fileSize<5000', '文件不得超过5MB');

2. 调用代码

less 复制代码
@PostMapping("/import")
public Result<?> importCustomer(@RequestParam MultipartFile file) {
    return importData(file, "customer");
}

3. 输入文件示例(CSV)

复制代码
客户编码,客户名称,客户等级
CUST001,测试客户,钻石级

4. 处理流程

css 复制代码
DBServiceControllerClientDBServiceControllerClientalt[文件校验失败][Sheet校验失败][单元格校验失败][全部校验通过]上传文件开始验证返回错误返回错误返回详细错误批量插入返回成功
场景3:数据导出

1. 数据库配置

sql 复制代码
-- 导出列配置
INSERT INTO export_column_config (config_id, db_column, excel_header, display_order)
VALUES 
(3, 'order_no', '订单编号', 1),
(3, 'create_time', '下单时间', 2),
(3, 'total_amount', '订单金额', 3);

-- 导出条件
INSERT INTO export_condition (config_id, param_name, data_type)
VALUES 
(3, 'start_time', 'date'),
(3, 'end_time', 'date');

2. 调用代码

less 复制代码
@PostMapping("/export")
public void exportOrders(@RequestBody ExportRequest request, 
                        HttpServletResponse response) {
    request.setBusinessKey("order_export");
    exportData(response, request);
}

3. 请求示例

json 复制代码
{
  "businessKey": "order_export",
  "params": {
    "start_time": "2023-01-01",
    "end_time": "2023-12-31"
  }
}

4. 输出结果

  • 生成包含时间段内订单的Excel文件:
lua 复制代码
| 订单编号 | 下单时间                | 订单金额 |
|----------|-------------------------|----------|
| O2023001 | 2023-05-01 14:30:00     | 12,500.00|

2、测试方案

2.1. 功能测试
测试场景 测试步骤 预期结果
模板导出 1. 调用/template接口 返回带数据验证的规范模板
数据导入 1. 上传符合要求的CSV 2. 上传包含错误数据的文件 1. 返回成功 2. 返回具体错误位置
数据导出 1. 使用有效参数调用export接口 2. 使用无效时间范围 1. 返回正确Excel 2. 返回空文件提示
字典校验 导入包含未定义字典值的数据 返回"无效字典值"错误
2.2. 边界情况测试
测试类别 测试场景 预期结果
文件大小 上传10MB的CSV文件 返回"文件超过限制"错误
行数限制 导入100001行数据 返回"超出最大行数限制"
特殊字符 客户名称含emoji符号 编码转换后正常存储
时区验证 导出时使用UTC时间参数 数据按时区转换正确
空文件 上传0KB的Excel文件 返回"空文件"错误
2.3. 压力测试方案

测试工具:JMeter + Prometheus监控

测试类型 测试参数 通过标准
单接口压测 100并发导出模板 平均RT < 500ms 错误率 < 0.1%
组合场景 50并发导入+50并发导出 系统资源利用率 < 80%
大数据量 导出1,000,000行数据 内存峰值 < 2GB 导出时间 < 60s
长时间运行 持续运行24小时混合负载 无内存泄漏 TPS波动 < 10%

监控指标

  1. JVM内存使用(堆内存、GC次数)
  2. 数据库连接池使用率
  3. Excel文件生成速率(行/秒)
  4. 导入数据吞吐量(行/秒)

3、测试数据生成脚本

3.1. 大数据量导入测试文件生成(Python)
python 复制代码
import csv
from faker import Faker

fake = Faker('zh_CN')

with open('large_data.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['客户编码', '客户名称', '客户等级'])
    
    for _ in range(100000):
        writer.writerow([
            f"CUST{fake.unique.random_number(digits=6)}",
            fake.company(),
            fake.random_element(['钻石级','金牌级','银牌级'])
        ])
3.2. 压力测试JMeter配置
xml 复制代码
<TestPlan>
  <ThreadGroup>
    <numThreads>100</numThreads>
    <rampUp>60</rampUp>
    
    <HTTPSampler>
      <method>POST</method>
      <path>/api/export</path>
      <Body>
        {"businessKey":"order_export","params":{"start_time":"2023-01-01"}}
      </Body>
    </HTTPSampler>
    
    <ResultCollector>
      <name>Aggregate Report</name>
    </ResultCollector>
  </ThreadGroup>
</TestPlan>
相关推荐
喵个咪5 分钟前
开箱即用的GO后台管理系统 Kratos Admin - 定时任务
后端·微服务·消息队列
Asthenia04127 分钟前
ArrayList与LinkedList源码分析及面试应对策略
后端
Asthenia041237 分钟前
由浅入深解析Redis事务机制及其业务应用-电商场景解决超卖
后端
Asthenia041238 分钟前
Redis详解:从内存一致性到持久化策略的思维链条
后端
Asthenia041238 分钟前
深入剖析 Redis 持久化:RDB 与 AOF 的全景解析
后端
Apifox1 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
掘金一周1 小时前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
uhakadotcom1 小时前
构建高效自动翻译工作流:技术与实践
后端·面试·github
Asthenia04121 小时前
深入分析Java中的AQS:从应用到原理的思维链条
后端
Asthenia04122 小时前
如何设计实现一个定时任务执行器 - SpringBoot环境下的最佳实践
后端