概述
首先我们先来看一下自定义数据源,Flink系统提供的一些功能
我们可以从下面这个图看出来数据源的source和sink类的集成关系
当我们要实现自定义数据源的时候,我们需要先实现DynamicTableSourceFactory, DynamicTableSinkFactory这两个工厂类,在工厂类里面去实现参数定义和数据源的创建,然后再数据源DynamicTableSource和DynamicTableSink里面去初始化数据源的一些信息,最终在source类型的数据源的ScanRuntimeProvider或者LookupTableSource或者sink类型的数据源的SinkRuntimeProvider实现类里面去实现具体功能。
具体实现
第一步 实现工厂类
Dynamic Table Factories
动态表工厂用于根据目录和会话信息为外部存储系统配置动态表连接器。
org.apache.flink.table.factories.DynamicTableSourceFactory
可以实现构造一个DynamicTableSource
.
org.apache.flink.table.factories.DynamicTableSinkFactory
可以实现构造一个DynamicTableSink
.
默认情况下,使用connector
选项的值作为工厂标识符和 Java 的服务提供者接口来发现工厂。
在 JAR 文件中,可以将对新实现的引用添加到服务文件中:
需要在resource目录下新建META-INF/services/目录,并且新建org.apache.flink.table.factories.Factory文件
META-INF/services/org.apache.flink.table.factories.Factory
然后在文件里面添加实现类的路径:com.flink.sql.connector.http.table.HttpDynamicTableFactory,只需要添加这个类路径就行,其他的不需要
如果没有这个文件个文件里面的内容,flink系统识别不到我们自定义的数据源信息
类文件的内容如下:HttpDynamicTableFactory.class
package com.flink.sql.connector.http.table;
import org.apache.flink.api.common.serialization.DeserializationSchema;
import org.apache.flink.api.common.serialization.SerializationSchema;
import org.apache.flink.configuration.ConfigOption;
import org.apache.flink.configuration.ConfigOptions;
import org.apache.flink.configuration.ReadableConfig;
import org.apache.flink.table.api.TableSchema;
import org.apache.flink.table.connector.format.DecodingFormat;
import org.apache.flink.table.connector.format.EncodingFormat;
import org.apache.flink.table.connector.sink.DynamicTableSink;
import org.apache.flink.table.connector.source.DynamicTableSource;
import org.apache.flink.table.data.RowData;
import org.apache.flink.table.factories.DeserializationFormatFactory;
import org.apache.flink.table.factories.DynamicTableSinkFactory;
import org.apache.flink.table.factories.DynamicTableSourceFactory;
import org.apache.flink.table.factories.FactoryUtil;
import org.apache.flink.table.factories.SerializationFormatFactory;
import org.apache.flink.table.types.DataType;
import org.apache.flink.util.Preconditions;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
// 我这里是同时实现了source和sink,也可以单独去实现,写在一起可以减少很多重复代码
public class HttpDynamicTableFactory implements DynamicTableSourceFactory, DynamicTableSinkFactory {
/**
首先定义一些数据源的参数信息,就是连接器的所有参数都需要先定义,这样才能在SQL里面去使用
*/
public static final String IDENTIFIER = "http";
public static final ConfigOption<String> URL = ConfigOptions.key("url")
.stringType().noDefaultValue().withDescription("the jdbc database url.");
public static final ConfigOption<String> HEADERS = ConfigOptions.key("headers")
.stringType().noDefaultValue().withDescription("the http header.");
private static final ConfigOption<String> BODY = ConfigOptions.key("body")
.stringType().noDefaultValue().withDescription("the http body params.");
private static final ConfigOption<String> TYPE = ConfigOptions.key("type")
.stringType().noDefaultValue().withDescription("the http type.");
private static final ConfigOption<String> FORMAT = ConfigOptions.key("format")
.stringType().noDefaultValue().withDescription("the http type.");
public HttpDynamicTableFactory() {
}
// 构造source类型的数据源对象
public DynamicTableSource createDynamicTableSource(Context context) {
FactoryUtil.TableFactoryHelper helper = FactoryUtil.createTableFactoryHelper(this, context);
ReadableConfig config = helper.getOptions();
helper.validate();
this.validateConfigOptions(config);
HttpSourceInfo httpSourceInfo = this.getHttpSource(config);
// discover a suitable decoding format
final DecodingFormat<DeserializationSchema<RowData>> decodingFormat = helper.discoverDecodingFormat(
DeserializationFormatFactory.class,
FactoryUtil.FORMAT);
// derive the produced data type (excluding computed columns) from the catalog table
final DataType producedDataType = context.getCatalogTable().getSchema().toPhysicalRowDataType();
return new HttpDynamicTableSource(httpSourceInfo, decodingFormat, producedDataType);
}
// 构造sink类型的数据源对象
@Override
public DynamicTableSink createDynamicTableSink(Context context) {
FactoryUtil.TableFactoryHelper helper = FactoryUtil.createTableFactoryHelper(this, context);
ReadableConfig config = helper.getOptions();
helper.validate();
th