陈同学
微服务
Accelerator
About
# 异构API数据处理实践 首先用下图阐述业务场景。 **基础服务**为各个业务服务(**服务A/B/C**) 提供API,同时基础服务数据又来源于第三方服务商。 各个服务商之间API的数据结构不同,本文不涉及不同服务商之间的安全通讯方式。 <img width="70%" src="https://blog-1256695615.cos.ap-shanghai.myqcloud.com/2018/05/09/528f1969aa234ac8932b96d486cce1f5.png"> ## 为什么需要多个服务商? > 例举我所遇到的两个因素 ### 系统稳定性考虑 以发送短信为例,若只有一个服务商,若服务商因某些因素中断服务,将导致依赖于短信的业务受到严重影响。 若对接了多个服务商,当其中一个无法使用,自动切换到可用的服务商即可。 ### 切换服务商 因各种因素导致商务合作终止,从而切换服务商 ## 异构数据的场景举例 先举两个例子加以说明: * **简单数据异构场景** 假设通过企查查、天眼查的API获取工商信息,对于企业名称字段,企业可能分别名称是`ENTNAME`、`org_name`,有的甚至是中文字段名`企业名称` * **复杂数据异构场景** 假设对接企业ERP中财务数据,A企业可能是金蝶系统、B企业是用友系统、其他企业可能是Oracle EBS或SAP系统。 这种场景不仅需要将异构数据处理成统一结构,而且处理过程中需要进行复杂的数据转换过程。 ## 异构数据处理简单Demo 数据处理的目的是可以通过配置,将不同服务商的异构数据统一解析,简化代码,增强拓展性。 这里以企业工商数据做演示。下面假设三种工商信息的数据结构,均使用JSON格式展示: ### 数据结构示例 * **自身标准数据结构** 业务系统中以自身的数据结构为准,假设字段名称是正常翻译: ```json { "organizationName":"企业名称", "taxpayerNumber":"纳税人识别号" } ``` * **A服务商API返回的数据结构** 假设字段名称是不规则简写: ```json { "ENTNAME":"企业名称", "TAXNUMBER":"纳税人识别号" } ``` * **B服务商API返回的数据结构** 假设字段名称是中文首字母简写: ```json { "QYMC":"企业名称", "NSRSBH":"纳税人识别号" } ``` ### 简单处理示例 先采用简单的方式处理,首先新建一个Domain表示企业工商信息: ```java public class Organization { private String organizationName; //企业名称 private String taxpayerNumber; //纳税人识别号 } ``` **将A服务商的数据转换为标准数据** > 假设JSONObject是阿里的fastjson ```java // JSONObject data = {"ENTNAME":"企业名称", "TAXNUMBER":"纳税人识别号"} Organization org = new Organization(); org.setOrganizationName(data.getString("ENTNAME")); org.setTaxpayerNumber(data.getString("TAXNUMBER")); ``` **将B服务商的数据转换为标准数据** ```java // JSONObject data = {"QYMC":"企业名称", "NSRSBH":"纳税人识别号"} Organization org = new Organization(); org.setOrganizationName(data.getString("QYMC")); org.setTaxpayerNumber(data.getString("NSRSBH")); ``` 上面看上去非常简单,但实际上API字段非常繁多,首先会导致大量的累赘代码,其次是有N个服务商就会有N种冗余代码。 ### 统一解析处理示例 使用注解在Domain上标记各个服务商的对应字段 **定义用于数据自动转换的注解** ```java @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface FiledMapper { String serviceA() default ""; // A服务商字段 String serviceB() default ""; // B服务商字段 } ``` **使用注解标记Domain的属性** 使用注解将异构数据的字段名与标准字段建立Mapping关系 ```java public class Organization { @FiledMapper(serviceA="ENTNAME", serviceB="QYMC") private String organizationName; //企业名称 @FiledMapper(serviceA="TAXNUMBER", serviceB="NSRSBH") private String taxpayerNumber; //纳税人识别号 } ``` **使用反射统一解析数据** ```java /** * 统一解析数据 * * @param source 数据源 * @param targetClass 目标类 * @param serviceProvider 服务提供商 * @return 目标类instance * @throws Exception */ public static Object parse(JSONObject source, Class targetClass, String serviceProvider) throws Exception { Object instance = targetClass.newInstance(); Field[] fields = targetClass.getDeclaredFields(); if (fields != null) { for (Field field : fields) { if (field.isAnnotationPresent(FiledMapper.class)) { FiledMapper filedMapper = field.getAnnotation(FiledMapper.class); field.setAccessible(true); field.set(instance, source.get("A".equals(serviceProvider) ? filedMapper.serviceA() : filedMapper.serviceB())); // 此处hardcode做演示 } } } return instance; } ``` **数据处理测试** ```java JSONObject dataA = JSON.parseObject("{\"ENTNAME\":\"企业A\", \"TAXNUMBER\":\"1001\"}"); JSONObject dataB = JSON.parseObject("{\"QYMC\":\"企业A\", \"NSRSBH\":\"1001\"}"); Organization orgA = (Organization) parse(dataA, Organization.class, "A"); Organization orgB = (Organization) parse(dataB, Organization.class, "B"); ``` ## 总结 本文仅提取了异构数据处理中的一个“点”做分析,为数据解析提供一种解决的思路。
本文由
cyj
创作,可自由转载、引用,但需署名作者且注明文章出处。
文章标题:
异构API数据处理实践
文章链接:
https://chenyongjun.vip/articles/27
扫码或搜索 cyjrun 关注微信公众号, 结伴学习, 一起努力