package jnpf.util; /** * 网关专用的 {@code jnpf.util.Ip2RegionUtil} 替身(2026-08-11,平台补丁 #15)。 * *

为什么要有这个类:上游把「IP 归属地工具类」和「它的数据文件」拆在了两个模块里—— *

* 而 gateway 依赖前者、不依赖后者(springaop 是 servlet 栈 + Sa-Token servlet 版, * 与 WebFlux 网关不可同进程,加不得)。于是 jnpf-common-core 的 * {@code CoreAutoConfiguration.afterPropertiesSet()} 里那句无条件预热调用: *
 *     initUserAgent();
 *     Ip2RegionUtil.getIpRegion(null);   // 传 null、返回值 pop 丢弃,纯粹为了触发类加载
 * 
* 就会触发原类的 static 块去读那两个不存在的 xdb,每次启动固定刷两条 ERROR: *
 *     ERROR jnpf.util.Ip2RegionUtil : failed to load content from `/ip2region/ip2region_v4.xdb`: ...
 *     ERROR jnpf.util.Ip2RegionUtil : failed to load content from `/ip2region/ip2region_v6.xdb`: ...
 * 
* *

为什么用替身而不是补数据文件:把 47MB 的 xdb 塞进 gateway 镜像, * 只为喂饱一句参数是 {@code null} 的预热调用——gateway 自身根本不解析归属地 * ({@code AuthFilter} / {@code ReactorUtil} 只取 IP 字符串),归属地解析发生在 cx-platform, * 那边有 springaop、xdb 正常加载。镜像刚从 5219MB 压到 762MB,不值当。 * *

行为与原类在「xdb 缺失」时完全一致(反编译核对过):原类加载失败后 * {@code SEARCHER_4}/{@code SEARCHER_6} 均为 null,{@code getIpRegion} 走到 * {@code aconst_null; areturn} 返回 {@code null},{@code getIp2RegionStr} 见 null 原样返回 null。 * 所以本替身返回 null 不是新行为,只是把「返回 null 之前先刷两条 ERROR」这一步省掉了。 * *

覆盖原理:Spring Boot fat jar 的 {@code LaunchedClassLoader} 里 * {@code BOOT-INF/classes/} 优先于 {@code BOOT-INF/lib/*.jar},故本类只在 gateway 生效, * 其余服务照常使用 jnpf-common-core 里的真实实现。 * *

回滚:删掉本文件即可(会退回「两条 ERROR + 返回 null」的原状态,功能无差别)。 * 详见 tasks/jnpf-platform-patches.md #15。 * * @author cx-team */ public class Ip2RegionUtil { /** 与原类在 xdb 缺失时的返回值一致:null。 */ public static String getIpRegion(String ip) { return null; } /** 与原类在 xdb 缺失时的返回值一致:null(原类内部就是 getIpRegion 返回 null 后原样透传)。 */ public static String getIp2RegionStr(String ip) { return null; } }