1.代码与含义解释

1.1 思路

Flink 获取数据流后,需要做数据过滤那么首先就要有一下几个步骤:

构建运行环境 接入数据流 链接数据库,写入数据

1.2 直接上代码

public static void main(String[] args) throws Exception {
    // 构建执行环境
    final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
    env.setParallelism(5);
    env.enableCheckpointing(2000, CheckpointingMode.EXACTLY_ONCE);
    // 读取文本数据 DataStreamSource 是数据源
    DataStreamSource<String> visitinfos = env.readTextFile("TheFilePaths");

    // Mysql JDBC 连接器
    JdbcConnectionOptions jdbcConnectionOptions = new JdbcConnectionOptions.JdbcConnectionOptionsBuilder()
            .withUrl("jdbc:mysql://localhost:3306/xxx")
            .withDriverName("com.mysql.cj.jdbc.Driver")
            .withUsername("username")
            .withPassword("passwd")
            .build();


    SingleOutputStreamOperator<List<String>> results = visitinfos.flatMap(new FlatMapFunction<String, List<String>>() {
        @Override
        public void flatMap(String value, Collector<List<String>> out) throws Exception {
            JSONObject jsonObject = JSON.parseObject(value);
            List<String> result = new ArrayList<>();
            for (String valuekey : jsonObject.keySet()) {
                result.add((String) jsonObject.get(valuekey));
            }
            out.collect(result);
        }
    });


    // 插入Mysql数据库
    // results 是来自于那个数据流 本阶段采用的是SingleOutputStreamOperator<List<String>> results 的 list 也可以使用DataStream<String> visitinfos 但需要 解析visitinfos
    results.addSink(
            JdbcSink.sink(
                    "insert into visit_info " +
                            "(Column_name)\n" +
                            "values(values)",
                    new JdbcStatementBuilder<List<String>>() {
                        @Override
                        public void accept(PreparedStatement preparedStatement, List<String> strings) throws SQLException {
                            for (int i = 0; i < strings.size(); i++) {
                                preparedStatement.setString(i + 1, strings.get(i));
                            }
                        }
                    },
                    jdbcConnectionOptions
            )
    );

    env.execute();

}

}

1.3 代码注释

1.首先还是构建 Flink 运行环境

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

2.获取数据源

DataStreamSource visit_info = env.readTextFile(" ThePath"); 此数据源可以是文本文档也可以是其他例如 端口或 Kafka 数据流,此处可以理解为数据流输入端

3.处理数据

SingleOutputStreamOperator<List> results = visitinfos.flatMap(new FlatMapFunction<String, List>() { @Override public void flatMap(String value, Collector<List> out) throws Exception { JSONObject jsonObject = JSON.parseObject(value); List result = new ArrayList<>(); for (String valuekey : jsonObject.keySet()) { result.add((String) jsonObject.get(valuekey)); } out.collect(result); } }); 4.创建JDBC 链接

JdbcConnectionOptions jdbcConnectionOptions = new JdbcConnectionOptions.JdbcConnectionOptionsBuilder() .withUrl("jdbc:mysql://localhost:3306/xxx") .withDriverName("com.mysql.cj.jdbc.Driver") .withUsername("username") .withPassword("password") .build(); 5.数据写入

results.addSink( JdbcSink.sink( "insert into visit_info " + "(column_names)\n" + "values(values)", new JdbcStatementBuilder<List>() { @Override public void accept(PreparedStatement preparedStatement, List strings) throws SQLException { for (int i = 0; i < strings.size(); i++) { preparedStatement.setString(i + 1, strings.get(i)); } } }, jdbcConnectionOptions ) ); 核心代码说明:

它使用了JdbcSink,一个通常与流式数据处理框架(如Apache Flink)中的数据库输出操作相关的组件。下面是对这段代码的逐行解释:

results.addSink( ... );

这一行是在一个叫做results的对象上调用addSink方法。这通常意味着你想为这个数据流添加一个输出(或“接收器”)以将数据发送到某个目的地,这里是一个数据库。 JdbcSink.sink( ... )

这是创建JdbcSink对象的方法调用。JdbcSink是一个能够将数据写入数据库的接收器。 "insert into visit_info " + "(column_names)\n" + "values(values)"

这是一个SQL插入语句的字符串,它将被用于向数据库中的visit_info表插入数据。这里column_names和values应该是占位符,实际使用时应该被实际的列名和值替换。 new JdbcStatementBuilder<List>() { ... }

这里创建了一个新的JdbcStatementBuilder对象。这个对象用于构建数据库操作语句,并将数据绑定到这些语句中。 @Override public void accept(PreparedStatement preparedStatement, List strings) throws SQLException { ... }

这是JdbcStatementBuilder接口的accept方法的实现。这个方法将接收一个PreparedStatement对象和一个字符串列表作为参数。 for (int i = 0; i < strings.size(); i++) { ... }

这是一个for循环,用于遍历传入的字符串列表。 preparedStatement.setString(i + 1, strings.get(i));

在循环内部,这一行代码将列表中的每个字符串值设置到PreparedStatement的对应参数位置。i + 1是因为PreparedStatement的参数索引是从1开始的。 }, jdbcConnectionOptions )

这部分代码关闭了JdbcStatementBuilder的匿名内部类定义,并传递jdbcConnectionOptions作为参数来配置JdbcSink的数据库连接选项。

2.思考

1.写入数据时数据表结构设计(数据模型)与数据流 如何动态匹配?

2.写入 Kafka 的话代码如何写?