feat(openapi): FlowCenterClient 切 SDK appCode 寻址(显式>legacy>fallback),application.yml 出厂 base-host 默认内部网关
build / build-push (push) Successful in 1m18s
build / build-push (push) Successful in 1m18s
This commit is contained in:
@@ -13,7 +13,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -26,9 +25,9 @@ import java.util.Map;
|
||||
*
|
||||
* <p>主路径走 SDK 类型化门面 {@code YschFlowOpenApi}(服务目录 key=flow-center:
|
||||
* yh.call.targets > yh.open.services > 枚举 base-host 兜底,《子应用配置优化方案》§4.2
|
||||
* 零专属地址配置);目录未显式配置时回落 legacy 键 {@code svchall.flow.base-url}(ad-hoc
|
||||
* 零专属地址配置);目录未显式配置且提供 legacy 时回落 legacy 键 {@code svchall.flow.base-url}(ad-hoc
|
||||
* TargetSpec,可配带/不带 context-path 两种形态,构造时拆成 host+basePath,迁移期兼容)。
|
||||
* 两条路径的 per-target base-path 剥离语义一致(同 {@link CmsSiteDirectoryImpl})。
|
||||
* 无 legacy 时使用 SDK 可解析目标。两条路径的 per-target base-path 剥离语义一致(同 {@link CmsSiteDirectoryImpl})。
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@@ -38,7 +37,7 @@ public class FlowCenterClient implements FlowClient {
|
||||
private final ObjectMapper objectMapper;
|
||||
private final boolean enabled;
|
||||
private final TargetSpec flowSpec;
|
||||
/** 服务目录显式配置了 flow-center(targets/services)则主路径走门面命名目标 */
|
||||
/** 显式目录或无 legacy 时 SDK 可解析 flow-center,则走门面命名目标 */
|
||||
private final boolean directoryResolved;
|
||||
|
||||
public FlowCenterClient(YschOpenCall openCall, ObjectMapper objectMapper,
|
||||
@@ -48,8 +47,11 @@ public class FlowCenterClient implements FlowClient {
|
||||
this.objectMapper = objectMapper;
|
||||
this.enabled = enabled;
|
||||
String base = trimTrailing(baseUrl == null ? "" : baseUrl.trim());
|
||||
this.directoryResolved = openCall != null && openCall.hasTarget(
|
||||
com.yunhai.platform.openapi.core.PlatformService.FLOW_CENTER.key());
|
||||
// 保持 explicit > legacy;没有 legacy 时允许 SDK 枚举/标准网关解析。
|
||||
this.directoryResolved = openCall != null && (openCall.hasTarget(
|
||||
com.yunhai.platform.openapi.core.PlatformService.FLOW_CENTER.key())
|
||||
|| (base.isEmpty() && openCall.canResolve(
|
||||
com.yunhai.platform.openapi.core.PlatformService.FLOW_CENTER.key())));
|
||||
if (directoryResolved) {
|
||||
com.yunhai.platform.openapi.flow.YschFlowOpenApi.setCall(openCall);
|
||||
}
|
||||
@@ -58,12 +60,9 @@ public class FlowCenterClient implements FlowClient {
|
||||
// enabled=false(显式未接入)时不校验——地址本就不需要。
|
||||
throw new IllegalStateException("流程中心调用地址未配置:请配置服务目录 yh.open.services."
|
||||
+ com.yunhai.platform.openapi.core.PlatformService.FLOW_CENTER.key()
|
||||
+ "(推荐,容器直连完整 URL)或回落键 svchall.flow.base-url");
|
||||
+ ",或平台网关 yh.open.base-host,或回落键 svchall.flow.base-url");
|
||||
}
|
||||
URI uri = URI.create(base);
|
||||
String host = uri.getScheme() + "://" + uri.getRawAuthority();
|
||||
String path = uri.getRawPath() == null ? "" : uri.getRawPath();
|
||||
this.flowSpec = TargetSpec.of(host, path);
|
||||
this.flowSpec = !enabled || directoryResolved || base.isEmpty() ? null : TargetSpec.fromUrl(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -86,23 +86,18 @@ yh:
|
||||
"100019": "flow-center-dev-secret-100019"
|
||||
open:
|
||||
# 身份密钥唯一来源 = yh.app-auth.app-key/app-secret(本文件 app-auth 段),open.* 副本已删
|
||||
base-host: http://base.yunhaixingtong.com
|
||||
# 服务目录(子应用配置优化方案 §4.2):跨服务出站唯一地址来源,命名目标走 SDK 门面 /
|
||||
# YschOpenCall。cms 未晋升 PlatformService 枚举(按名直调);flow-center 已入枚举。
|
||||
# 完整 URL 拆 host+ctx,per-target base-path 与提供方 context-path 对齐 → 签名天然一致。
|
||||
# 生产改容器直连:flow-center=http://flow-center-service:10008/flow-center、
|
||||
# cms=http://yschcms-service:10005/yschcms。
|
||||
# (base-path /userbase 已删 2026-10-05,对齐 Notice 形态:该键代码默认值即 /userbase,删键无行为变化,
|
||||
# 回调前缀推导读的是 yh.flow-callback.target/base-path 三层回落,与本键无关)
|
||||
base-host: ${YH_OPEN_BASE_HOST:http://open-gateway-service:10013}
|
||||
# 标准后端按 appCode 走统一内部 open-gateway,无需逐应用 URL。
|
||||
# 本地直连只在运行时显式覆盖 yh.open.services.{appCode};不要写入出厂 jar。
|
||||
services:
|
||||
# 生产零配置:不配则枚举兜底 = base-host(网关)+/flow-center;此处显式覆盖仅本地开发用
|
||||
# (Notice 同款)。生产如仍被平台层注入容器直连值,属平台配置项(projman yh.open.services 段)。
|
||||
flow-center: http://localhost:8085
|
||||
# flow-center: http://localhost:8085
|
||||
cms: http://base.yunhaixingtong.com:10005/yschcms
|
||||
# form-center 刻意<b>不写本地默认值</b>(TASK_1 交付说明第 2 条的同一取舍):本文件里写
|
||||
# http://localhost:80xx 会被打进 jar,部署实例就去连容器内的 localhost(2026-09-18 事故)。
|
||||
# 本机跨应用联调请运行时注入:YH_OPEN_SERVICES_FORMCENTER=http://localhost:<FC 实际端口>;
|
||||
# 生产不注入即走目录第 3 级兜底(base-host 网关 + PlatformService.FORM_CENTER 的 ctx)。
|
||||
# 不配条目则走标准 appCode fallback:base-host 网关 + /form-center(无需枚举)。
|
||||
# form-center: ${YH_OPEN_SERVICES_FORMCENTER:}
|
||||
|
||||
# 流程中心回调接收端 starter(2026-09-20 迁移;2026-10-05 收敛 Notice 形态):
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.yunhai.svchall.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.yunhai.platform.openapi.core.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class FlowCenterClientRoutingTest {
|
||||
private YschOpenCall call(String gateway) {
|
||||
OpenApiProperties open = new OpenApiProperties();
|
||||
open.setBaseHost(gateway);
|
||||
return new YschOpenCall(new YschCallProperties(), open, new ObjectMapper(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void enabledWithoutExplicitTargetUsesSdk() {
|
||||
YschOpenCall call = call("http://gateway:10013");
|
||||
assertFalse(call.hasTarget("flow-center"));
|
||||
FlowCenterClient client = new FlowCenterClient(call, new ObjectMapper(), true, "");
|
||||
assertTrue(client.enabled());
|
||||
assertEquals(true, ReflectionTestUtils.getField(client, "directoryResolved"));
|
||||
assertNull(ReflectionTestUtils.getField(client, "flowSpec"));
|
||||
assertEquals("http://gateway:10013/form-center", call.resolveTarget("form-center").resolveBaseUrl());
|
||||
assertDoesNotThrow(() -> new FormCenterCatalogClient(call));
|
||||
assertDoesNotThrow(() -> new FcSubmissionClient(call));
|
||||
assertDoesNotThrow(() -> new FormSyncClient(call));
|
||||
}
|
||||
|
||||
@Test
|
||||
void explicitThenLegacyThenSdkPriority() {
|
||||
YschCallProperties props = new YschCallProperties();
|
||||
props.getTargets().put("flow-center", TargetSpec.of("http://explicit", "/flow-center"));
|
||||
YschOpenCall explicit = new YschOpenCall(props, new ObjectMapper(), null);
|
||||
FlowCenterClient client = new FlowCenterClient(explicit, new ObjectMapper(), true, "http://legacy/ctx");
|
||||
assertEquals(true, ReflectionTestUtils.getField(client, "directoryResolved"));
|
||||
client = new FlowCenterClient(call("http://gateway"), new ObjectMapper(), true, "http://legacy/ctx");
|
||||
assertEquals(false, ReflectionTestUtils.getField(client, "directoryResolved"));
|
||||
TargetSpec spec = (TargetSpec) ReflectionTestUtils.getField(client, "flowSpec");
|
||||
assertEquals("http://legacy/ctx", spec.resolveBaseUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
void enabledWithoutResolvableAddressFailsButDisabledDoesNot() {
|
||||
assertThrows(IllegalStateException.class,
|
||||
() -> new FlowCenterClient(call(null), new ObjectMapper(), true, ""));
|
||||
assertThrows(IllegalStateException.class,
|
||||
() -> new FlowCenterClient(call("http://gateway/open-gateway"), new ObjectMapper(), true, ""));
|
||||
assertFalse(new FlowCenterClient(call(null), new ObjectMapper(), false, "").enabled());
|
||||
assertFalse(new FlowCenterClient(call(null), new ObjectMapper(), false, "unused-legacy-value").enabled());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user