Files
form-center-service/pom.xml
chenxing b3478afddd t17:oapi v2 增量拉取 + RabbitMQ 事件(可选依赖、信封十字段闭集、软删防回归断言)
- GET /oapi/form/answers(契约 §6.1/C9/C11/C12):域校验走 readDomainForm(他校与不存在同一条
  "表单不存在",V54;软删表单照读,§5.4/P32),行集恒带 sch_id。增量口径按冻结状态二分且不接受混用
  (混用给可诊断拒绝,而不是静默返回一个"看起来正常"的空窗口):
  冻结=append-only + after=answer_uuid(服务端按 uk 换算库内 id,id 绝不出响应,V53,墓碑照常下发);
  非冻结=updated_since + 复合键 (update_time, answer_uuid),续拉游标 {ISO8601}|{answer_uuid}(P126)。
  limit 1~2000 越界拒不夹;nextCursor 只在这一页填满时给(宁可末尾多要一次空页,不可少要一次)。
- 行字段是 §6.1 的 15 键闭集(逐字段 @JsonProperty,外层 rows/nextCursor 按 C9 原文 camelCase——
  命名差异是契约原文,不加"顺手统一"的适配层);meta.ip/ua 只匿名行有值(C12),登录行两项 null。
- 时间线格式降到整秒并对齐列精度(DATETIME 秒粒度;带纳秒的游标与列值比不出等值,
  同事务重读还会经一级缓存拿到内存对象):取舍方向是"宁可重复投递也不漏行",
  重复投递正是 C9 明写的 at-least-once(P127)。IT 侧 flush+clear 把读取摆回生产形态。
- 新 FcEventPublisher(§6.2/V62/V63/V64):RABBITMQ_HOST 未注入=整体 no-op + 启动一条说明日志;
  RabbitTemplate 走 ObjectProvider(可选依赖不该在缺 bean 时拖垮上下文);exchange fc.events.v1
  惰性 durable topic 声明(声明失败放回标志位允许重试);routing key fc.answer.{app_code}.{action};
  afterCommit 发布且信封在注册前按实体快照组好;发布失败只 warn 不抛(没有 outbox、没有死信)。
  信封十字段闭集、不含值文档(裁决 1:MQ 是通知通道不是数据通道)。
- 发布点三处:submit 写库段后=created(代录/导入同管线自动获得);两处编辑写库段=updated
  (能走到即说明未开冻结,V61 已在前面拦);两处软删实体 save 后=tombstoned(公共出口是发布器那一个方法)。
- 依赖与配套:pom 加 spring-boot-starter-amqp(BOM 管版本);yml 的 spring.rabbitmq.* 全从
  RABBITMQ_* env 现读,并关 rabbit 健康探针与 Boot 的 RabbitAdmin(dynamic=false)——
  后者启动就拨号声明拓扑,无 broker 环境实测把上下文启动拖到分钟级,拓扑已由发布器自己声明。

测试:OapiAnswersIT 8 例(闭集无 id、口径二分互不混用、limit 边界、after 翻页+重放+墓碑可见、
V70 软删前移 update_time 才让墓碑进窗口、复合游标带 uuid 尾、他校同文面、匿名行 meta)
+ FcEventPublisherTest 5 例(V63 十字段闭集、routing key、未配置即 no-op、afterCommit 之前不发、
异常被吞)+ MqDisabledContextIT 2 例(无 broker:enabled()=false 与 /actuator/health 仍 UP)。
门禁:定向 15 例全绿(s6-gate-2.log),本段另跑过一次全量 288 例全绿(mvn-full-2.log,
按协调口径后续段不再连发全量,全量留 S8 收口)。差额 P126/P127/P128。
2026-10-20 17:17:40 +08:00

141 lines
6.1 KiB
XML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath/>
</parent>
<groupId>com.yunhai</groupId>
<artifactId>form-center</artifactId>
<version>0.1</version>
<name>form-center</name>
<description>表单中心(动态表单:定义与版本/答卷与检索/选项字典/数据范围/导出;对外契约=《表单中心契约-20261014.md》)</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.yunhai.platform</groupId>
<artifactId>yh-platform-dependencies</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 基础平台全家桶(聚合 starter):CAS 认证 + 应用间签名 + 统一响应 + OpenAPI 客户端 +
actuator 健康探活 + 共享 IDHttp(出站自动签名),一行带齐(同 flow-center/svc-hall 约定) -->
<dependency>
<groupId>com.yunhai.platform</groupId>
<artifactId>yh-spring-boot-starter</artifactId>
</dependency>
<!-- 外观偏好同源读端点 GET /api/appearance(三态 proxy/local/off,默认 proxy 经 YschOpenCall
代理 UserHome /oapi/appearance,userhome 地址走平台 application-platform.yml 兜底);
前端壳的主题通道依赖它,与 flow-center 同款引入 -->
<dependency>
<groupId>com.yunhai.platform</groupId>
<artifactId>yh-appearance-spring-boot-starter</artifactId>
</dependency>
<!-- 平台 auth starter(0928 后快照)的 WeChatAuthAutoConfiguration 签名引用 StringRedisTemplate,
data-redis 为 optional,接入前提=应用自带(见该 starter pom 注释);缺失时 bean 签名解析直接
TypeNotPresentException,应用起不来 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- MQ 事件推送(契约 v2 §6.2,T17):**可选依赖**——RABBITMQ_HOST 未配置时 FcEventPublisher 整体
禁用、服务照跑(照上面 data-redis 那条先例:引依赖但不引运行期强耦合)。
版本由 BOM 管理(Boot 2.7.18 → amqp 2.4.x,Java 8 兼容)。
配套 yml:management.health.rabbit.enabled=false,否则无 broker 时 /actuator/health 直接 DOWN(V64)。 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- CAS 客户端(UserHome/Cms/svc-hall/flow-center 同款显式声明) -->
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 答卷导出(契约 §8 红线:导出受数据范围约束;方案 §5.5 流式写):
3.3.x 起 easyexcel 是 easyexcel-core 的聚合壳,版本随本行定死 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>form-center</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.yunhai.formcenter.FormCenterApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 默认 surefire 只收 *Test.java;本工程打真实 MySQL 的集成测试按 *IT 命名,
一并纳入 mvn test(CI 不跑单测,本地 mvn test 即门禁——任务书 §0.4) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Test.java</include>
<include>**/*IT.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</project>