Apache Dubbo的@SPI接口应用

记录:472

场景:使用Apache Dubbo的@SPI接口加载实现类搭建框架。

版本:JDK 1.8,dubbo-common-3.0.0。

SPI全称Service Provider Interface。

1.基础

1.1引用依赖

XML 复制代码
<dependency>
  <groupId>org.apache.dubbo</groupId>
  <artifactId>dubbo-common</artifactId>
  <version>3.0.0</version>
</dependency>

1.2应用

(1)使用@SPI注解作用在自定义接口com.hub.example.pf.adapter.IPfDataAdapter。

(2)业务类TCityAdapterImpl、TProvinceAdapterImpl等实现接口IPfDataAdapter。

(3)在..\src\main\resources目录下,新建\META-INF\services目录

(4)在\META-INF\services目录新建配置文件:com.hub.example.pf.adapter.IPfDataAdapter,文件名称就是@SPI注解作用的接口全路径名称。

(5)在\META-INF\services\com.hub.example.pf.adapter.IPfDataAdapter配置文件中添加入下内容(key=value键值对):

XML 复制代码
t_province=com.hub.example.process.adapter.TProvinceAdapterImpl
t_city=com.hub.example.process.adapter.TCityAdapterImpl

(6)根据配置文件中key名称和接口名称获取实现类,如下:

java 复制代码
IPfDataAdapter var= ExtensionLoader.getExtensionLoader(IPfDataAdapter.class).getExtension(tableName);

1.3逻辑

Apache Dubbo框架对使用@SPI注解接口,会在..\src\main\resources\META-INF\services目录下扫描配置并加载。

2.示例场景

(1)从某数据源(比如数据库)中读取数据存放在:Map<String, Object> data。

(2)组装成Tuple3<String, String, Map<String, Object>> in数据格式,其中Tuple3第一个参数数:表名称,第二参数:指定的字段名称,第三个参数就是数据。

(3)使用计算框架com.hub.example.pf.function.PfDataMapFunction计算业务

输入:Tuple3<String, String, Map<String, Object>> in;

输出:Tuple3<String, String, Map<String, String>> out;

(4)把Tuple3<String, String, Map<String, String>> out传递给下游处理。比如数据写入到HBase等目的端。

3.示例代码

3.1接口和抽象类

(1)接口 IPfDataAdapter

全称:com.hub.example.pf.adapter.IPfDataAdapter

代码:

java 复制代码
@SPI
public interface IPfDataAdapter {
    Tuple3<String, String, Map<String, String>> getPfData(Map<String, Object> value);
}

(2)抽象类

全称:com.hub.example.pf.adapter.PfDataAdapterAbstract

代码:

java 复制代码
public abstract class PfDataAdapterAbstract implements IPfDataAdapter {
    public PfDataAdapterAbstract() {
    }
    public Tuple3<String, String, Map<String, String>> getPfData(Map<String, Object> data) {
        try {
            Map<String, String> result = new HashMap(data.size());
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                if (entry.getValue() != null) {
                    result.put(entry.getKey(), entry.getValue().toString());
                }
            }
            return new Tuple3(this.getTableName(), this.getRowKeyColumns(), result);
        } catch (Exception e) {
            return new Tuple3(null, null, new HashMap<>());
        }
    }
    public abstract String getDataType();
    public String getTableName() {
        return TableConfig.getTableName(this.getDataType());
    }
    public String getRowKeyColumns() {
        return TableConfig.getRowKeyColumns(this.getDataType());
    }
}

3.2计算框架

全称:com.hub.example.pf.function.PfDataMapFunction

代码:

java 复制代码
public class PfDataMapFunction {
    public PfDataMapFunction() {
    }
    public Tuple3<String, String, Map<String, String>> map(Tuple3<String, String, Map<String, Object>> data) {
        try {
            String tableName = (String) data.f0;
            IPfDataAdapter dataAdapter = ExtensionLoader.getExtensionLoader(IPfDataAdapter.class).getExtension(tableName);
            if (dataAdapter == null) {
                return new Tuple3();
            } else {
                return dataAdapter.getPfData((Map) data.f2);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Tuple3();
        }
    }
}

3.3业务类

(1)业务类TProvinceAdapterImpl对应表:t_province

全称:com.hub.example.process.adapter.TProvinceAdapterImpl

代码:

java 复制代码
public class TProvinceAdapterImpl extends PfDataAdapterAbstract {
    public TProvinceAdapterImpl() {
    }
    @Override
    public String getDataType() {
        return "T_PROVINCE";
    }
    public Tuple3<String, String, Map<String, String>> getPfData(Map<String, Object> data) {
        if (data.get("PROVINCE_ID") == null) {
            return new Tuple3();
        }
        return super.getPfData(data);
    }
}

(2)业务类TCityAdapterImpl对应表:t_city

全称:com.hub.example.process.adapter.TCityAdapterImpl

代码:

java 复制代码
public class TCityAdapterImpl extends PfDataAdapterAbstract {
    @Override
    public String getDataType() {
        return "T_CITY";
    }

    public Tuple3<String, String, Map<String, String>> getPfData(Map<String, Object> data) {
        if (data.get("CITY_ID") == null) {
            return new Tuple3();
        }
        return super.getPfData(data);
    }
}

3.4配置文件

(1)配置目录..\META-INF\services

目录:..\src\main\resources\META-INF\services

(2)配置文件com.hub.example.pf.adapter.IPfDataAdapter

文件名:com.hub.example.pf.adapter.IPfDataAdapter

文件内容:

java 复制代码
t_province=com.hub.example.process.adapter.TProvinceAdapterImpl
t_city=com.hub.example.process.adapter.TCityAdapterImpl

3.5配置类

全称:com.hub.example.config.TableConfig

代码:

java 复制代码
public class TableConfig {
    private static ConcurrentHashMap<String, String> tableConfig = new ConcurrentHashMap<>();
    static {
        tableConfig.put("TABLE:T_PROVINCE", "HUB:T_PROVINCE");
        tableConfig.put("ROW_KEY:T_PROVINCE", "V_DATA_DATE,PROVINCE_ID");
        tableConfig.put("TABLE:T_CITY", "HUB:T_CITY");
        tableConfig.put("ROW_KEY:T_CITY", "V_DATA_DATE,CITY_ID");
    }
    public static String getTableName(String tableName) {
        return tableConfig.get("TABLE:" + tableName.toUpperCase());
    }
    public static String getRowKeyColumns(String tableName) {
        return tableConfig.get("ROW_KEY:" + tableName.toUpperCase());
    }
}

3.6实体类

全称:com.hub.example.api.Tuple3

代码:

java 复制代码
public class Tuple3<T0, T1, T2> implements Serializable {
    private static final long serialVersionUID = 1L;
    public T0 f0;
    public T1 f1;
    public T2 f2;

    public Tuple3() {
    }

    public Tuple3(T0 f0, T1 f1, T2 f2) {
        this.f0 = f0;
        this.f1 = f1;
        this.f2 = f2;
    }

    public static String arrayAwareToString(Object o) {
        String arrayString = Arrays.deepToString(new Object[]{o});
        return arrayString.substring(1, arrayString.length() - 1);
    }

    public String toString() {
        return "(" + arrayAwareToString(this.f0) + ";" + arrayAwareToString(this.f1) + ";" + arrayAwareToString(this.f2) + ")";
    }
}

4.示例测试

全称:com.hub.example.process.ExampleApplicationSPI

代码:

java 复制代码
public class ExampleApplicationSPI {
    public static void main(String[] args) throws Exception {
        PfDataMapFunction dataPfMapFunction = new PfDataMapFunction();
        //操作t_province
        String table01 = "t_province";
        Map<String, Object> data01 = getTProvince();
        Tuple3<String, String, Map<String, Object>> in01 = new Tuple3(table01, data01.get("PROVINCE_ID"), data01);
        Tuple3<String, String, Map<String, String>> out01 = dataPfMapFunction.map(in01);
        System.out.println("操作表t_province后数据: " + out01.toString());
        //操作t_city
        String table02 = "t_city";
        Map<String, Object> data02 = getTCity();
        Tuple3<String, String, Map<String, Object>> in02 = new Tuple3(table02, data02.get("CITY_ID"), data02);
        Tuple3<String, String, Map<String, String>> out02 = dataPfMapFunction.map(in02);
        System.out.println("操作表t_city后数据: " + out02.toString());
    }
    public static Map<String, Object> getTProvince() {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("PROVINCE_ID", 33001694333578181L);
        dataMap.put("V_DATA_DATE", "20230910");
        dataMap.put("PROVINCE_NAME", "浙江");
        dataMap.put("GROSS", 7.77D);
        return dataMap;
    }
    public static Map<String, Object> getTCity() {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("CITY_ID", 33011694333578181L);
        dataMap.put("V_DATA_DATE", "20230911");
        dataMap.put("CITY_NAME", "杭州");
        dataMap.put("GROSS", 1.88D);
        return dataMap;
    }
}

以上,感谢。

2023年9月10日

相关推荐
流烟默3 天前
Centos7.6使用yum安装jdk1.8
yum·jdk1.8
大阳1233 天前
ARM.8(ADC,SPI)
单片机·嵌入式硬件·adc·spi
proware17 天前
rk3588适配MCP2515 SPI转CAN
can·spi·3588
曦月合一20 天前
在CentOS 6.5系统中OpenJDK 1.7升级更新 OpenJDK 1.8,并部署
linux·centos·jdk1.8
W.W.H.1 个月前
嵌入式系统硬件接口全景图
经验分享·uart·iic·gpio·spi
我在人间贩卖青春2 个月前
SPI总线
stm32·spi
π同学2 个月前
ESP-IDF+vscode开发ESP32第六讲——SPI
vscode·esp32·spi
weifengdq2 个月前
SJA1124 SPI转4路LIN STM32 测试笔记
stm32·spi·nxp·lin·sja1124·spi4lin
青桔柠薯片2 个月前
I.MX6ULL 裸机开发:SPI 总线与多点触摸屏驱动原理剖析
imx6ull·spi·adxl345·多点触控
Qt程序员2 个月前
Linux 内核 SPI 驱动
linux·linux内核·嵌入式开发·spi