XinAnApiService 中 getDomainsIcp 逻辑非常糟糕,递归多次查询,没必要。帮我实现新的查询功能,保持原来的所有代码不要动,在类最后新写一个方法。但是保持入参、返回值和 原getDomainsIcp 一致。 # 域名备案查询方案 ## 目标 对一批域名进行备案查询。由于信安接口单次最多支持 100 个域名,因此需要对域名进行拆解、去重、分批查询,并最终为每个域名选出“最接近原始域名但有备案”的结果。 # 整体流程 ## ① 域名拆解(从左向右逐级截断) 对每个输入域名,按 `.` 分段,并从每个位置向右拼接成子域名列表。 最低拆到这种 `baidu.com` 程度作为最后一级,也就是主域名的上一级,不要拆到顶级域名 com,com 这种去查备案号没什么用。 主域名以 `List mainDomainCollections =mainDomainDao.findAll().stream().map(MainDomainPO::getDomain).collect(Collectors.toList()); ` 为优先,如果没在表中的默认拆到两级。 main_domain 的数据是这种: ``` or.id org.pg tw tel 信息 广东 ``` 注意表中可能出现 xj.cn 和 cn,要先main_domain排序后去匹配域名。 例如: - `a.b.c.baidu.com` ⟶ `a.b.c.baidu.com`, `b.c.baidu.com`, `c.baidu.com`, `baidu.com` - `a.b.c.d.baidu.com` ⟶ `a.b.c.d.baidu.com`, `b.c.d.baidu.com`, `c.d.baidu.com`, `d.baidu.com`, `baidu.com` - `a.b.c.d.org.pg` ⟶ `a.b.c.d.org.pg`, `b.c.d.org.pg`, `c.d.org.pg`, `d.org.pg` ## ② 全局去重 所有要查询的域名放入一个 Set,去掉重复项,例如 `baidu.com` 只会出现一次。 ## ③ 分批调用信安接口 规则: - 按 100 个域名一批切分 - 每批调用一次信安接口 - 将所有批次的结果合并成: recordMap:域名 → 备案信息 ## ④ 为每个原始域名选择“最佳备案” 对于一个域名的候选列表(从长到短): 例如: ``` [a.b.c.baidu.com, b.c.baidu.com, c.baidu.com, baidu.com] ``` 选择第一个在 `recordMap` 中“有备案”的域名,作为最终结果。 例: - a.b.c.baidu.com → 无备案 - b.c.baidu.com → 有备案(选它) 最终输出: ``` 原始域名 → 最匹配备案号 ``` --- 底层查询使用 `private Map queryDomainsIcpByGroup(List domains)`,已实现分组、重试直接用就行。代码要易读健壮优雅。 函数说明: ``` /** * 批量查询域名备案号 * @param domains 域名集合 * @return Map value: false:未备案;具体备案号:说明备案;"":信安未返回 */ private Map queryDomainsIcpByGroup(List domains) { Map result = Maps.newHashMap(); //list分组 List> lists = Lists.partition(domains, XINAN_DOMAIN_QUERY_SIZE); lists.parallelStream().forEach((temp -> { try { Map domainsIcpMap = queryDomainsIcp(temp); if (MapUtils.isNotEmpty(domainsIcpMap)) { result.putAll(domainsIcpMap); } } catch (Exception e) { log.error("queryDomainsIcpByGroup() -> 批量分组查询icp异常, domains:{}", JacksonUtils.toJSONString(domains), e); } })); return result; } ```