Aller au contenu principal

页面请求上下文与后端调试

Traduction en coursCe guide est actuellement disponible en chinois simplifié. Une version traduite sera ajoutée ultérieurement.

Spark Page 在页面设计、设计预览和应用运行时都会调用后端接口。为了让同一份页面配置能够连接开发、测试和生产环境,并让后端区分“设计器正在快速预览”与“用户正在使用应用”,平台会在页面请求中统一携带两个标准请求头。

这套协议适用于页面元数据、Custom URL、Model Data Source、文件上传、表格行操作,以及 Interaction 中的 Send Request 等页面请求。控件只负责配置业务 URL 和业务参数,不需要逐个手工填写环境请求头。

1. 整体流程​

一次设计预览请求按以下顺序执行:

Page Designer 配置 Data Source / Interaction
│
▼
Spark 页面共享请求层解析当前环境与渲染模式
│
├── X-Spark-Page-Environment: DEV
└── X-Spark-Page-Render-Mode: DESIGN_PREVIEW
│
▼
后端 Controller 使用 SparkPageRequestHeaders 解析标准上下文
│
▼
Service 根据环境与渲染模式选择预览数据或对应环境的数据服务
│
▼
统一返回 ApiResult<DTO>,页面按配置的数据路径和字段映射渲染

设计器和运行时使用同一个共享请求层,因此在设计态测试通过的 URL、请求参数、Connection 和响应解析规则,会按同一契约用于页面预览和运行态。

2. 请求头协议​

请求头可用值默认值说明
X-Spark-Page-EnvironmentDEV、TEST、PRODDEV当前页面连接的应用环境
X-Spark-Page-Render-ModeDESIGN_PREVIEW、RUNTIMERUNTIME当前请求来自设计预览还是应用运行态

两个维度彼此独立,常见组合如下:

使用位置EnvironmentRender Mode后端建议
Page Designer 画布、Data Source 测试DEVDESIGN_PREVIEW返回稳定、可重复、覆盖典型字段的开发预览数据;避免危险写操作
开发环境应用运行态DEVRUNTIME连接开发数据库或开发服务,验证真实业务流程
测试环境应用运行态TESTRUNTIME连接测试数据与测试依赖
生产环境应用运行态PRODRUNTIME连接生产服务,并执行完整认证、授权和审计

如果在 Page Designer URL 中选择了其他环境,平台会使用当前选择的环境值;设计预览模式仍为 DESIGN_PREVIEW。

3. 前端不需要手工配置协议头​

页面设计器、运行时 Shell 和共享请求层负责集中注入标准请求头。即使控件的 Headers 或 Connection 中存在同名配置,平台上下文值也应覆盖它们,避免页面作者把 DEV 页面误标成 PROD。

控件只需要配置:

  • 业务 URL 与请求方式
  • 业务查询参数或请求体
  • Response List Path 等响应解析规则
  • 必要的 Connection Key

不要在每个 Tree、ProTable 或 Send Request 中重复添加 X-Spark-Page-* 请求头,也不要在单个控件代码中硬编码 DEV 或 DESIGN_PREVIEW。

4. Java Controller 解析上下文​

Java 17 / Spring Boot 4 后端使用 spark-base 提供的共享常量和模型。Controller 只解析一次,再把标准化的 SparkPageRequestContext 传入 Service。

@RestController
@RequestMapping("/spark/api/catalog/tree")
public class CatalogTreeController {

private final CatalogTreeService treeService;

public CatalogTreeController(CatalogTreeService treeService) {
this.treeService = treeService;
}

@GetMapping("/nodes")
public ApiResult<TreeDataResult> nodes(
@RequestParam(required = false) String parentId,
@RequestHeader(value = "Accept-Language", required = false)
String language,
@RequestHeader(value = SparkPageRequestHeaders.ENVIRONMENT,
required = false) String environment,
@RequestHeader(value = SparkPageRequestHeaders.RENDER_MODE,
required = false) String renderMode) {
Locale locale = SparkApiResultHelper.resolveLocale(language);
SparkPageRequestContext context =
SparkPageRequestHeaders.resolve(environment, renderMode);
TreeDataResult data = treeService.query(parentId, context);
return SparkApiResultHelper.success(
locale, data, "CATALOG-TREE-QUERY-SUCCESS");
}
}

业务 Service 不应接收原始 Header 字符串或临时 Map。统一模型可以避免不同接口各自解释 dev、preview 等非标准值。

5. Service 根据上下文选择数据​

开发态分支的目的不是在前端伪造数据,而是让真实后端接口知道这次调用用于快速预览和调试。推荐把“选择哪一个数据提供者”集中在 Service 或专门的路由组件中,Controller 和 DTO 契约保持不变。

@Service
public class CatalogTreeService {

private final CatalogTreeRepository repository;
private final CatalogTreePreviewProvider previewProvider;

public CatalogTreeService(
CatalogTreeRepository repository,
CatalogTreePreviewProvider previewProvider) {
this.repository = repository;
this.previewProvider = previewProvider;
}

public TreeDataResult query(
String parentId,
SparkPageRequestContext context) {
List<TreeNodeDTO> nodes = isDevelopmentPreview(context)
? previewProvider.query(parentId)
: repository.query(parentId, context.getEnvironment());
return new TreeDataResult(nodes, context);
}

private boolean isDevelopmentPreview(SparkPageRequestContext context) {
return context.getEnvironment() == SparkPageEnvironment.DEV
&& context.getRenderMode()
== SparkPageRenderMode.DESIGN_PREVIEW;
}
}

预览数据提供者建议遵守以下原则:

  • 返回稳定且可重复的数据,刷新画布或再次测试时结果不应随机变化。
  • 覆盖真实 DTO 的关键字段、空值和典型层级,帮助页面作者检查映射。
  • 默认只读;创建、删除、付款、发消息等有副作用的接口应提供明确的开发沙箱,或在设计预览模式下拒绝执行。
  • DEV + RUNTIME 仍可连接开发数据库,用于验证真实流程,不要与 DEV + DESIGN_PREVIEW 混为一谈。
  • TEST、PROD 的数据路由由后端配置决定,不能相信前端请求头来绕过权限控制。

6. Data Source 测试​

支持测试的数据源在配置弹窗中提供 Test。以 Tree 为例:

  1. 填写 Root Data URL、Request Method、Request Parameters 和 Response List Path。
  2. 点击 Test。
  3. Spark 使用当前页面环境和 DESIGN_PREVIEW 发起真实请求。
  4. 面板显示最终 URL、业务参数、HTTP 状态、耗时和实际响应。
  5. Spark 使用当前 Response List Path 与字段映射解析响应,并显示识别出的节点数量。
  6. 根据结果调整 dataPath、Title Field、Value Field、Leaf Field 等配置,确认无误后再保存。

测试功能与设计画布、运行态复用同一个请求构造器。它不会额外保存数据源,也不会把认证、Cookie、Access Key 或 Connection 中的敏感 Header 显示在结果面板中;响应中常见的密码、Token、Secret 字段会被遮罩。

Tree 的完整配置过程参见 Tree 控件介绍。

7. 外部服务的 CORS 配置​

如果 Custom URL 指向不同域名,外部服务除了允许常规方法和认证头,还必须在 CORS 中允许这两个请求头:

X-Spark-Page-Environment
X-Spark-Page-Render-Mode

Spring MVC 示例:

@Configuration
public class WebCorsConfiguration implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://spark.hiforce.ai")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders(
"Content-Type",
"Authorization",
SparkPageRequestHeaders.ENVIRONMENT,
SparkPageRequestHeaders.RENDER_MODE);
}
}

生产项目应按实际 Spark 域名和安全策略收窄 Origin、方法和 Header 范围。

8. 安全边界​

X-Spark-Page-Environment 和 X-Spark-Page-Render-Mode 是页面运行上下文,不是可信身份信息。浏览器请求头可以被修改,因此后端仍必须独立完成:

  • 登录状态和 Access Token 校验
  • 租户、用户和资源权限检查
  • 写操作的业务校验与审计
  • DEV、TEST、PROD 数据源的服务端隔离
  • 敏感字段过滤和日志脱敏

不能因为请求声明为 DESIGN_PREVIEW 就跳过认证,也不能因为请求声明为 PROD 就直接连接任意生产租户数据。

9. 调试检查表​

接口没有按预期返回时,按以下顺序检查:

  1. 在 Data Source 中点击 Test,确认最终 URL 和业务参数正确。
  2. 确认结果面板显示预期的 Environment 与 Render Mode。
  3. 在浏览器 Network 中检查两个标准请求头是否存在。
  4. 检查后端是否使用 SparkPageRequestHeaders.resolve(...),而不是自行比较大小写字符串。
  5. 检查 Service 的预览分支是否返回与正式 DTO 相同的 JSON 结构。
  6. 检查 Response List Path 和字段映射是否与实际响应一致。
  7. 跨域请求失败时检查 OPTIONS 响应与 Allowed Headers。
  8. 运行态正常但设计态失败时,检查后端是否错误地拒绝 DESIGN_PREVIEW,或预览数据是否缺少必需字段。