4. 输入边界设计:导出请求的标准化接口定义、参数校验规则、请求上下文传递

报表导出模块的输入边界是系统与外部交互的第一道防线。一个设计良好的输入边界,能够确保导出请求的完整性、合法性与可追溯性。本章节围绕标准化接口定义、参数校验规则以及请求上下文传递三个核心维度展开,构建稳固的导出请求入口。

4.1 标准化接口定义

导出请求接口采用统一的RESTful风格设计,所有导出操作均通过单一端点接收请求,避免因接口分散导致维护成本上升。接口定义遵循以下原则:

  • 统一入口:所有报表导出请求统一使用 POST /api/v1/export 端点。
  • 请求体结构:使用JSON格式承载参数,包含报表标识、模板配置、输出格式、请求上下文等核心字段。
  • 响应约定:同步导出直接返回文件流;异步导出返回任务ID,供客户端轮询进度。
字段 类型 必填 说明
reportCode String 是 报表唯一编码,用于定位报表定义
templateId String 否 模板标识,为空则使用默认模板
format String 是 输出格式:PDF、EXCEL、CSV、HTML
params Map<String, Object> 否 报表查询参数键值对
context Object 是 请求上下文,包含用户、租户、语言等信息
async Boolean 否 是否异步导出,默认false

接口设计要点:params 字段采用松散键值对结构,允许不同报表携带差异化的查询条件,避免接口定义随报表数量膨胀而频繁变更。模板引擎在渲染阶段根据报表定义解析 params 中的具体字段。

// 导出请求示例(JSON)
{
  "reportCode": "SALES_MONTHLY",
  "templateId": "template_v2",
  "format": "PDF",
  "params": {
    "startDate": "2025-01-01",
    "endDate": "2025-01-31",
    "region": "华东"
  },
  "context": {
    "userId": "u10086",
    "tenantId": "t_aliyun",
    "locale": "zh-CN",
    "timezone": "Asia/Shanghai"
  },
  "async": true
}

4.2 参数校验规则

参数校验是输入边界的核心防线,采用分层校验策略,兼顾性能与安全性。校验规则分为三个层级:

  1. 基础格式校验:检查必填字段是否存在、字段类型是否正确、枚举值是否在允许范围内。
  2. 业务逻辑校验:验证报表编码是否已注册、模板是否对应当前报表、参数组合是否满足报表定义要求。
  3. 安全校验:防止SQL注入、XSS攻击、参数溢出等安全风险。
校验层级 校验项 失败处理
基础格式 reportCode 非空、format 属于枚举、context 必填 返回 400 Bad Request,明确错误字段
业务逻辑 reportCode 存在且已发布、templateId 与报表匹配 返回 404 或 422,附带业务错误码
安全校验 params 值长度限制、特殊字符过滤、数值范围检查 返回 400,拒绝请求并记录安全日志

最佳实践:建议使用声明式校验注解(如Jakarta Validation的 @NotNull、@Size)配合自定义校验器实现业务规则。校验失败时返回统一错误结构,包含 code、message、field 三个字段,便于前端定位问题。

// 校验失败响应示例
{
  "code": "EXPORT_PARAM_INVALID",
  "message": "报表编码不能为空",
  "field": "reportCode"
}

4.3 请求上下文传递

请求上下文承载了导出操作所需的用户身份、租户隔离、国际化等环境信息。上下文对象在接口层被解析,并通过线程局部变量或显式参数传递至整个导出链路。

请求上下文传递链路 API 网关 / 控制器 上下文解析器 RequestContext userId: String tenantId: String locale: String 参数校验器 模板引擎 数据源 / 权限过滤 传递方式 ThreadLocal 或 显式参数传递 避免全局变量污染

上下文传递需关注以下关键点:

  • 线程安全:使用 InheritableThreadLocal 或 TransmittableThreadLocal 确保异步任务能正确继承上下文。
  • 租户隔离:数据源路由、模板资源加载均需根据 tenantId 进行隔离,防止跨租户数据泄露。
  • 国际化支持:locale 字段影响日期格式、数字格式、错误提示语言,模板引擎在渲染时根据该字段选择对应的资源包。
  • 审计日志:userId 和 tenantId 必须记录到导出日志中,用于操作追溯和用量统计。

常见陷阱:在异步导出场景中,如果使用线程池执行导出任务,务必在提交任务前将上下文快照复制到任务对象中,避免线程复用导致上下文错乱。推荐使用 ContextAwareRunnable 包装类自动处理上下文传递。

4.4 输入边界整体架构

将标准化接口、参数校验、上下文传递三者整合,形成完整的输入边界架构。下图展示了请求从进入系统到进入核心处理流程的完整路径。

输入边界整体架构 外部导出请求 标准化接口 (POST /api/v1/export) 参数校验器(三层校验) 上下文解析与注入 导出核心处理(模板引擎 + 数据源) 校验失败返回 400 / 404 / 422 统一错误结构 上下文传递 ThreadLocal 异步快照

输入边界设计的关键在于“收口”与“透传”的平衡:接口层收窄入口,校验层过滤无效请求,上下文层透传环境信息。三层协作确保只有合法、完整、可追溯的导出请求才能进入核心处理流程,为后续的模板引擎集成与参数配置奠定坚实基础。