一套基于策略模式 + 配置驱动的通用灰度发布框架,支持白名单、黑名单、百分比、组合策略等多种切流模式,配置热更新零代码侵入。


1. 背景与问题

在大型业务系统中,新功能上线通常不能一蹴而就地全量放开,而是需要经历"内部验证 → 小范围灰度 → 逐步放量 → 全量切流"的渐进式发布过程。传统的 if-else 硬编码方式存在以下问题:

问题 描述
代码侵入强 每个灰度场景都需要写一套判断逻辑,散落在各业务代码中
调整需发版 修改白名单或百分比需要重新发布应用
缺乏一致性 不同场景的灰度实现方式五花八门,难以统一管控
无法一键熔断 发现问题时无法快速关闭灰度开关
难以组合 无法灵活组合多种灰度策略(如"白名单 + 百分比")

本框架的核心目标:一行代码接入、配置动态生效、策略可组合、一键可熔断


2. 整体架构

┌─────────────────────────────────────────────────────────────┐
│                       业务调用方                              │
│   grayStrategyService.isPassGrayStrategy(                    │
│       "YOUR_BIZ_CODE", targetId, params)                    │
└────────────────────────┬────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────┐
│                  GrayStrategyServiceImpl                     │
│                                                              │
│  ① 根据 bizCode 查询远程配置中心,获取 GrayStrategyConfig    │
│  ② 检查 switchOn 总开关                                     │
│  ③ 反序列化 modeList,逐个执行策略 Handler                    │
│  ④ all pass → true ; any fail → false                       │
│  ⑤ try-finally 打印决策 digest 日志                          │
└────────────┬────────────┬────────────┬──────────────────────┘
             │            │            │
    ┌────────▼──┐  ┌──────▼───┐  ┌────▼──────────┐
    │ Handler A │  │Handler B │  │  Handler C    │  ...
    │ (白名单)   │  │(百分比)  │  │(黑名单等)     │
    └───────────┘  └──────────┘  └───────────────┘

核心决策流程:

  1. 业务方传入 bizCode(灰度业务码)、targetId(通常是商户 ID)、params(维度参数)
  2. 根据 bizCode 从配置中心加载 GrayStrategyConfig
  3. 如果配置不存在或 switchOn=false,直接返回默认结果
  4. 遍历 modeList 中的策略模式,逐个执行对应的 Handler
  5. 任意一个 Handler 不通过,整体不通过(AND 语义)
  6. 全部通过,返回 true

3. 核心组件详解

3.1 配置模型 —— GrayStrategyConfig

每一条灰度配置包含 5 个字段:

字段 类型 说明 示例
bizCode String 灰度业务标识,定位到具体业务场景 "SUPPLY_B2B_MEMBER_WITH_REGISTER_FROM"
switchOn String 总开关,控制该场景灰度是否启用 "true" / "false"
modeList String JSON 数组,策略模式列表,支持多策略组合 ["WHITE_LIST","UID_PERCENTAGE"]
ruleMap String JSON 对象,白名单/黑名单的维度规则 {"userId":["uid1","uid2"],"instCode":["Z05"]}
cutPercentage String 百分比切流比例(0-100) "10" 表示 10%

关键设计 —— modeList 是数组: 同一个业务场景可以叠加多种策略模式。比如同时配置 ["WHITE_LIST","UID_PERCENTAGE"],表示先过白名单、再过百分比,全部满足才算通过

配置存储在远程配置中心(如 ComPara),修改后即时生效,无需发版

3.2 策略模式枚举 —— GrayStrategyModeEnum

将每种灰度策略封装为 枚举值 + Handler 的形式:

┌─────────────────────────────┬───────────────────────────────────────────────────┐
│ 枚举值                       │ 描述                                               │
├─────────────────────────────┼───────────────────────────────────────────────────┤
│ ALL_PASS                    │ 全量放行模式                                        │
│ WHITE_LIST                  │ 白名单模式(所有维度必须同时命中,AND 语义)         │
│ BLACK_LIST                  │ 黑名单模式(任意维度命中即拦截,OR 语义)           │
│ UID_PERCENTAGE              │ UID 分表位百分比切流(确定性,同一用户结果恒定)    │
│ REFERENCE_UID_PERCENTAGE    │ 引用 UID 百分比切流(hashCode 分桶,非标准 UID 用) │
│ WHITE_LIST_ANY_MATCH_ENOUGH │ 宽松白名单(任意一个维度命中即通过,OR 语义)        │
│ WHITE_LIST_WITH_PERCENTAGE  │ 白名单+百分比(核心维度直通,非核心维度再过百分比) │
└─────────────────────────────┴───────────────────────────────────────────────────┘

设计亮点 —— 枚举即路由表: 枚举的构造函数第三个参数直接持有对应的 Handler 实例:

WHITE_LIST("WHITE_LIST", "白名单模式", new WhiteListStrategyHandler()),

调用时通过 GrayStrategyModeEnum.getByCode(mode).getHandler() 即可获取处理器,省去了工厂类或 Map 映射。

3.3 策略处理器接口 —— GrayStrategyHandler

public interface GrayStrategyHandler {
    int PERCENTAGE_0 = 0;
    int PERCENTAGE_100 = 100;

    /**
     * @param config   灰度策略配置(含 ruleMap、cutPercentage 等)
     * @param targetId 切流目标 ID(通常是商户 userId)
     * @param param    运行时维度参数(如 userId、instCode、label 等)
     * @return true: 通过灰度决策 | false: 不通过
     */
    boolean handle(GrayStrategyConfig config, String targetId, Map<String, String> param);
}

三个参数的职责明确:

  • config:该场景的完整灰度配置,Handler 按需读取 ruleMap、cutPercentage 等字段
  • targetId:切流目标,通常传商户 userId
  • param:运行时维度参数,与 ruleMap 中的 key 对应用于匹配

3.4 调用方接口 —— GrayStrategyService

提供两个重载方法和一系列参数构建工具:

// 核心方法(defaultResult 默认 false)
boolean isPassGrayStrategy(String bizCode, String targetId, Map<String, String> params);

// 支持自定义默认结果的方法
boolean isPassGrayStrategy(String bizCode, String targetId, Map<String, String> params,
                           boolean defaultResult);

// 参数构建工具方法(static)
static Map<String, String> buildUidParamMap(String userId);
static Map<String, String> buildLabelParamMap(String label);
static Map<String, String> buildBizSceneParamMap(String bizScene);
static Map<String, String> buildInstCodeParamMap(String instCode);
static Map<String, String> buildParamMap(String key, String value);

defaultResult** 参数的含义:** 当配置不存在(即配置中心没有该 bizCode 的记录)时,返回什么默认值。一般传 false(保守,走老流程),也可以按业务需要传 true


4. 七种策略模式详解

4.1 ALL_PASS —— 全量放行

语义: 无条件放行,所有请求都通过。

适用场景: 灰度验证已结束,需要全量上线时,将 modeList 改为 ["ALL_PASS"] 即可。

实现: 直接返回 true

4.2 WHITE_LIST —— 严格白名单(AND 语义)

语义: ruleMap 中所有维度都必须命中白名单,才算通过。

决策流程:

传入参数: {userId: "A", instCode: "Z05"}
配置: ruleMap = {userId: ["A","B"], instCode: ["Z05"]}

遍历 ruleMap:
  ① userId 维度: param["userId"]="A" 在白名单 ["A","B"] 中 → 通过
  ② instCode 维度: param["instCode"]="Z05" 在白名单 ["Z05"] 中 → 通过

所有维度通过 → 返回 true
传入参数: {userId: "A", instCode: "Z99"}
配置: ruleMap = {userId: ["A","B"], instCode: ["Z05"]}

遍历 ruleMap:
  ① userId 维度: 通过
  ② instCode 维度: param["instCode"]="Z99" 不在白名单 ["Z05"] 中 → 不通过

存在维度不通过 → 返回 false

注意: 如果传入参数中缺少某个维度的值,直接返回 false。白名单是"证明你行"的逻辑,缺少证据即为不通过。

适用场景: 精确控制特定商户,需要同时满足多个维度条件。

4.3 BLACK_LIST —— 黑名单(OR 语义)

语义: ruleMap 中任意一个维度命中黑名单,即被拦截。

决策流程:

传入参数: {userId: "A", instCode: "Z05"}
配置: ruleMap = {userId: ["C","D"], instCode: ["Z99"]}

遍历 ruleMap:
  ① userId 维度: param["userId"]="A" 不在黑名单 ["C","D"] 中 → 不拦截
  ② instCode 维度: param["instCode"]="Z05" 不在黑名单 ["Z99"] 中 → 不拦截

全部未命中 → 返回 true(放行)

关键设计差异: 如果传入参数中缺少某个维度的值,黑名单模式选择 continue(跳过,不拦截),而非返回 false。这与白名单相反:黑名单是"证明你不行",缺少证据就不拦截。

适用场景: 排除特定商户,如已知有问题的商户 ID 需要暂时屏蔽新流程。

4.4 UID_PERCENTAGE —— UID 分表位百分比切流

语义: 根据 userId 的分表位(0-99)判断是否命中灰度比例。

决策流程:

1. 从配置读取 cutPercentage(如 "10")
2. 通过 DBPrimaryKeyUtil.getUserPartitionByUserId(userId) 获取分表位
3. 判断: userPartition < cutPercentage → 通过

设计亮点 —— 确定性: 使用分表位而不是 Random.nextInt(),保证了同一用户多次请求的结果恒定。这是灰度切流的关键要求——用户不能一会儿走新流程一会儿走老流程。

分表位算法内部还兼容了压测 UID(倒数第二位可能是字母 A-J),会做字母→数字的替换处理。

适用场景: 按比例灰度放量,如先放量 5%,观察后逐步提升到 10%、50%、100%。

4.5 REFERENCE_UID_PERCENTAGE —— 引用 UID 百分比切流

语义: 与 UID_PERCENTAGE 类似,但分桶算法不同。

关键区别:

模式 分桶算法 适用场景
UID_PERCENTAGE 分表位(DB 内部 ID 格式) 标准 ipay 内部 UID
REFERENCE_UID_PERCENTAGE hashCode() % 100 非 ipay 格式的引用 ID(如平台商的 seller ID)

设计亮点 —— 模板方法模式: 继承 PercentageStrategyHandler,只覆写 getUserPartitionByUserId 方法:

public class ReferenceUidPercentageStrategyHandler extends PercentageStrategyHandler {
    @Override
    protected int getUserPartitionByUserId(String referenceUserId) {
        return Math.abs(referenceUserId.hashCode() % 100);
    }
}

父类定义了百分比判定的骨架流程,子类只需替换分桶算法。

4.6 WHITE_LIST_ANY_MATCH_ENOUGH —— 宽松白名单(OR 语义)

语义: ruleMap 中任意一个维度命中白名单,即算通过。

决策流程:

传入参数: {userId: "A", instCode: "Z99"}
配置: ruleMap = {userId: ["A","B"], instCode: ["Z05"]}

遍历 ruleMap:
  ① userId 维度: param["userId"]="A" 在白名单 ["A","B"] 中 → 命中!
  
任意一条命中 → 返回 true(无需继续检查 instCode)

额外能力 —— 通配符 * 如果某个维度的白名单列表包含 "*",则该维度无条件通过:

配置: ruleMap = {instCode: ["*"]}
传入参数: {instCode: "任意值"}
→ 命中通配符,直接通过

与严格白名单的对比:

对比维度 WHITE_LIST(严格) WHITE_LIST_ANY_MATCH_ENOUGH(宽松)
语义 所有维度都要命中 任意维度命中即可
逻辑 AND OR
缺少维度参数 返回 false 不影响(其他维度命中即可)
通配符支持 支持 *

钩子方法设计: hintPercentageAfterMatch() 是一个钩子,当前实现直接返回 true,但为子类留了扩展点。

4.7 WHITE_LIST_WITH_PERCENTAGE —— 白名单 + 百分比

语义: 先做白名单匹配(OR 语义),命中后根据维度类型决定是否再做百分比淘汰。

核心逻辑(覆写钩子方法):

白名单命中后:
  ├── 命中的维度是核心维度 (userId / maInnerId)
  │   → 直接放行,不走百分比
  │
  └── 命中的维度是非核心维度 (instCode / label 等)
      → 还需要过百分比随机淘汰
      → RandomUtils.nextInt(0, 101) <= cutPercentage → 通过

设计智慧 —— 维度优先级区分:

  • 核心维度(userId、maInnerId):白名单精确到具体商户,确定性高,不需要百分比。配置了某个 userId 就一定放行该用户。
  • 非核心维度(instCode、label 等):白名单覆盖范围大(如某个 instCode 下可能有大量商户),需要百分比来渐进放量,避免一次性放开太多。

百分比注意点: 这里的百分比用的是 RandomUtils.nextInt()(随机),与 UID_PERCENTAGE 的分表位(确定性)不同。这是有意为之——白名单阶段已经做了维度筛选,百分比阶段是对非核心维度的补充过滤,随机性可以接受。


5. 策略组合机制

modeList 支持配置多个策略模式,实现灵活组合:

5.1 多策略 AND 语义

配置示例:"modeList": ["WHITE_LIST","UID_PERCENTAGE"]

决策过程:先过白名单 → 再过百分比 → 全部通过才算通过

请求进入
  │
  ▼
WHITE_LIST Handler
  ├── 不通过 → 返回 false
  └── 通过 ↓
      ▼
UID_PERCENTAGE Handler
  ├── 不通过 → 返回 false
  └── 通过 → 返回 true

5.2 单策略场景

配置示例:"modeList": ["WHITE_LIST_ANY_MATCH_ENOUGH"]

只走一种策略模式,通过即通过。

5.3 全量切流

配置示例:"modeList": ["ALL_PASS"]

等价于关闭灰度,所有请求都走新流程。也可以直接将 switchOn 设为 "true" 配合 ALL_PASS


6. 核心决策引擎流程

private boolean doGrayDecide(String bizCode, String userId,
                             Map<String, String> params, boolean defaultResult) {

    // 1. bizCode 为空 → 返回 defaultResult
    if (Objects.isNull(bizCode)) {
        return defaultResult;
    }

    // 2. 从配置中心查询 GrayStrategyConfig
    GrayStrategyConfig strategyConfig = queryGrayStrategyConfig(bizCode);

    // 3. 配置不存在 → 返回 defaultResult
    if (Objects.isNull(strategyConfig)) {
        return defaultResult;
    }

    // 4. 总开关关闭 → 返回 false(一键熔断)
    if (!Boolean.parseBoolean(strategyConfig.getSwitchOn())) {
        return false;
    }

    // 5. 解析 modeList
    List<String> grayModes = JSONObject.parseObject(strategyConfig.getModeList(),
        new TypeReference<List<String>>() {});
    if (CollectionUtils.isEmpty(grayModes)) {
        return false;
    }

    // 6. 遍历执行每个策略 Handler(AND 语义)
    for (String grayMode : grayModes) {
        GrayStrategyModeEnum modeEnum = GrayStrategyModeEnum.getByCode(grayMode);
        if (Objects.isNull(modeEnum)) {
            return false;  // 不支持的模式 → 不通过
        }
        if (!modeEnum.getHandler().handle(strategyConfig, userId, params)) {
            return false;  // 任一策略不通过 → 整体不通过
        }
    }

    return true;  // 所有策略都通过
}

关键设计决策总结:

步骤 条件 结果 设计意图
bizCode 为空 无法决策 返回 defaultResult 兜底安全,由调用方决定
配置不存在 未配置灰度规则 返回 defaultResult 未配置 != 拦截,尊重业务方的默认倾向
switchOn=false 主动关闭 返回 false 一键熔断,紧急情况下快速回滚
modeList 为空 无策略 返回 false 有配置但无策略,保守处理
不支持的模式 配置错误 返回 false 防止配置错误导致误放行
Handler 不通过 策略拦截 返回 false AND 语义,任意失败即终止

7. 配置示例

示例 1:简单白名单(仅允许指定用户)

{
  "grayBizCode": "MY_FEATURE_SWITCH",
  "switchOn": "true",
  "modeList": "[\"WHITE_LIST\"]",
  "ruleMap": "{\"userId\":[\"2088123456\",\"2088789012\"]}",
  "cutPercentage": "0"
}

调用方式:

grayStrategyService.isPassGrayStrategy(
    "MY_FEATURE_SWITCH",
    userId,
    GrayStrategyService.buildUidParamMap(userId)
);

示例 2:白名单 + 百分比组合(白名单用户直通,非白名单用户按 instCode 10% 放量)

{
  "grayBizCode": "MY_FEATURE_SWITCH",
  "switchOn": "true",
  "modeList": "[\"WHITE_LIST_WITH_PERCENTAGE\"]",
  "ruleMap": "{\"userId\":[\"2088123456\"],\"instCode\":[\"Z05\"]}",
  "cutPercentage": "10"
}

调用方式:

Map<String, String> params = new HashMap<>();
params.put("userId", userId);
params.put("instCode", instCode);
grayStrategyService.isPassGrayStrategy("MY_FEATURE_SWITCH", userId, params);
  • userId 命中白名单 → 核心维度,直通
  • instCode 命中白名单但 userId 未命中 → 非核心维度,10% 随机放量
  • 都未命中 → 不通过

示例 3:全量切流

{
  "grayBizCode": "MY_FEATURE_SWITCH",
  "switchOn": "true",
  "modeList": "[\"ALL_PASS\"]",
  "ruleMap": "{}",
  "cutPercentage": "0"
}

示例 4:黑名单排除(排除特定商户)

{
  "grayBizCode": "MY_FEATURE_SWITCH",
  "switchOn": "true",
  "modeList": "[\"BLACK_LIST\"]",
  "ruleMap": "{\"userId\":[\"2088problem1\",\"2088problem2\"]}",
  "cutPercentage": "0"
}

示例 5:多策略组合(先过白名单,再过百分比)

{
  "grayBizCode": "MY_FEATURE_SWITCH",
  "switchOn": "true",
  "modeList": "[\"WHITE_LIST\",\"UID_PERCENTAGE\"]",
  "ruleMap": "{\"instCode\":[\"Z05\"]}",
  "cutPercentage": "30"
}
  • instCode 必须是 Z05(白名单 AND 语义)
  • 且分表位 < 30(百分比切流)
  • 两者都满足才通过

8. 灰度生命周期管理

一个完整的灰度切流应经历以下阶段:

阶段 1: 内部验证
  配置: modeList=["WHITE_LIST"], ruleMap={userId: ["内部测试UID"]}
  目标: 仅对内部用户开放

       ↓ 验证通过

阶段 2: 小范围灰度
  配置: modeList=["WHITE_LIST_ANY_MATCH_ENOUGH"], ruleMap={instCode: ["Z05"]}
  目标: 指定 instCode 下的商户开放

       ↓ 观察稳定

阶段 3: 渐进放量
  配置: modeList=["WHITE_LIST_WITH_PERCENTAGE"], ruleMap={instCode: ["Z05"]}, cutPercentage="10"
  目标: 非核心维度命中后 10% 放量

       ↓ 逐步提升 cutPercentage: 10 → 30 → 50 → 80

阶段 4: 全量切流
  配置: modeList=["ALL_PASS"]
  目标: 全量开放

       ↓ 运行稳定

阶段 5: 下线灰度代码
  目标: 移除灰度判断逻辑,删除 ComPar配置,清理 GrayBizCodeEnum

重要提醒: 阶段 5 常常被忽略。灰度配置不是永久的,切流完成后要及时下线灰度代码和配置,否则代码中会残留大量无用的灰度判断逻辑,增加维护成本。


9. 设计模式总结

设计模式 应用位置 效果
策略模式 GrayStrategyHandler + 7 种实现 不同灰度判定算法可独立变化,互不影响
模板方法模式 PercentageStrategyHandlerReferenceUidPercentageStrategyHandler 复用百分比切流骨架,只替换分桶算法
模板方法模式 AnyMatchEnoughWhiteListStrategyHandlerAnyMatchEnoughWhiteListAndPercentageStrategyHandler 复用白名单匹配逻辑,只扩展命中后的百分比判断
枚举即路由表 GrayStrategyModeEnum 持有 Handler 实例 省去工厂类,枚举值 = 策略码 + 处理器
配置驱动 配置中心存储 GrayStrategyConfig 策略规则热更新,无需发版
组合模式 modeList 数组 多个策略 AND 组合,实现精细化切流控制

10. 接入指南

10.1 新增灰度场景

Step 1:GrayBizCodeEnum 中添加业务码枚举(可选,建议添加以获得编译期检查):

public enum GrayBizCodeEnum {
    // ...
    /** 你的业务场景描述 */
    YOUR_BIZ_SCENE_CODE,
    // ...
}

Step 2: 在配置中心(ComPara)添加 iexpmprodGrayStrategyConfig 配置项,grayBizCode 填写你的业务码。

Step 3: 在业务代码中调用:

@SofaReference
private GrayStrategyService grayStrategyService;

public void yourBusinessMethod() {
    String userId = getCurrentUserId();
    boolean isNewFlow = grayStrategyService.isPassGrayStrategy(
        GrayBizCodeEnum.YOUR_BIZ_SCENE_CODE.name(),
        userId,
        GrayStrategyService.buildUidParamMap(userId),
        false  // 配置不存在时默认走老流程
    );

    if (isNewFlow) {
        // 新流程
    } else {
        // 老流程
    }
}

10.2 新增灰度模式

如果现有 7 种模式不满足需求,扩展步骤如下:

Step 1: 实现 GrayStrategyHandler 接口:

public class YourCustomHandler implements GrayStrategyHandler {
    @Override
    public boolean handle(GrayStrategyConfig config, String targetId,
                          Map<String, String> param) {
        // 你的灰度判定逻辑
        return true; // or false
    }
}

Step 2:GrayStrategyModeEnum 中添加枚举值:

YOUR_MODE("YOUR_MODE", "你的模式描述", new YourCustomHandler()),

Step 3: 在配置中心的 modeList 中使用 "YOUR_MODE" 即可。

10.3 参数构建速查

场景 构建方法
按 userId 灰度 GrayStrategyService.buildUidParamMap(userId)
按 instCode 灰度 GrayStrategyService.buildInstCodeParamMap(instCode)
按 label 灰度 GrayStrategyService.buildLabelParamMap(label)
按 bizScene 灰度 GrayStrategyService.buildBizSceneParamMap(bizScene)
按 loginId 灰度 GrayStrategyService.buildLoginIdParamMap(loginId)
按 salePlanCode 灰度 GrayStrategyService.buildSalePlanCodeParamMap(salePlanCode)
自定义维度 GrayStrategyService.buildParamMap("yourKey", "yourValue")
多维度组合 自行构建 Map 并 put 多个 key-value

11. 最佳实践

11.1 命名规范

灰度业务码应清晰表达场景语义,推荐格式:{业务域}_{功能描述}_{灰度目的}

✅ SUPPLY_B2B_MEMBER_WITH_REGISTER_FROM   (绑定会员指定 registerFrom)
✅ PORTAL_ONBOARD_STRUCTURE_CHANGE_ISNTCODE (门户入驻解耦-主体维度)
✅ MERCHANT_TRANSACTION_RISK_LIMIT        (商户交易限制)
✅ ONBOARD_HK_Z05_SWITCH                  (香港商户切流到 Z05)

11.2 defaultResult 的选择

  • 保守策略(推荐):传 false,配置不存在时走老流程。适用于新功能上线初期。
  • 激进策略:传 true,配置不存在时走新流程。适用于老流程即将下线的场景。

11.3 日志可观测

每次灰度决策都有 digest 日志输出:

[GrayStrategyService-digest]bizCode=YOUR_BIZ_CODE,targetId=2088xxx,params={userId=2088xxx},isPassGrayStrategy=true.

利用这个日志可以进行线上灰度效果统计和问题排查。

11.4 切流节奏建议

1% → 观察 2-3 天 → 5% → 观察 2-3 天 → 10% → 30% → 50% → 80% → 100% → ALL_PASS

每次调整百分比只需修改配置中心的 cutPercentage 值,即时生效。


12. 类图总览

GrayStrategyService (接口)
    │
    └── GrayStrategyServiceImpl (决策引擎)
            │
            ├── GrayStrategyConfig (配置模型)
            │       bizCode / switchOn / modeList / ruleMap / cutPercentage
            │
            ├── GrayStrategyModeEnum (策略路由)
            │       ALL_PASS ────→ DefaultStrategyHandler
            │       WHITE_LIST ──→ WhiteListStrategyHandler
            │       BLACK_LIST ──→ BlackListStrategyHandler
            │       UID_PERCENTAGE → PercentageStrategyHandler
            │                           └── ReferenceUidPercentageStrategyHandler
            │       WHITE_LIST_ANY_MATCH_ENOUGH → AnyMatchEnoughWhiteListStrategyHandler
            │                                       └── AnyMatchEnoughWhiteListAndPercentageStrategyHandler
            │       WHITE_LIST_WITH_PERCENTAGE ──→ (同上)
            │
            └── GrayBizCodeEnum (业务码)
                    FIX_ALI_TRIP_SETTLE_CHANNEL
                    SUPPLY_B2B_MEMBER_WITH_REGISTER_FROM
                    PORTAL_ONBOARD_STRUCTURE_CHANGE_ISNTCODE
                    ... (40+ 业务码)

Logo

一站式 AI 云服务平台

更多推荐