缉查布控操作

package com.shujia.streaming

import org.apache.spark.broadcast.Broadcast
import org.apache.spark.sql.SparkSession
import org.apache.spark.streaming.dstream.{DStream, ReceiverInputDStream}
import org.apache.spark.streaming.{Durations, StreamingContext}

import java.sql.{Connection, DriverManager, PreparedStatement, ResultSet, Statement}
import scala.collection.mutable

object Demo04BuKong {
  def main(args: Array[String]): Unit = {
    /**
     * 缉查布控:
     * 在MySQL中有一份黑名单
     * create table mdn_blacklist(
     *  mdn varchar(255) comment '人员mdn'
     *  );
     *  插入数据:
     *  insert into mdn_blacklist values
     * ('47BE1E866CFC071DB19D5E1C056BE28AE24C16E7'),
     * ('82044609CB65BA7139205E7808144D5C254C419F'),
     * ('96CBCC934720F3CA9C7A1E384594204494A24AAD'),
     * ('2070972D4CC6FB1A6DBCBF70051D8BDEF6485AAF'),
     * ('00744B1DAC6A4DC575B24EF68838CCD0248F2E1C');
     *
     * 使用nc -lk 8888 模拟消息队列 手动的“采集”数据
     *
     * 使用SparkStreaming实时处理数据 一旦发现数据中有黑名单中提供的人员
     * 即将数据过滤出来并写入MySQL
     */
    /**
     * 为什么不用本地的List而用MySQL去保存黑名单信息?
     * 动态的增加或删除黑名单中的人员,如果直接使用本地的List则需要重启应用
     */

    val spark: SparkSession = SparkSession
      .builder()
      .appName("Demo04BuKong")
      .master("local[2]")
      .getOrCreate()

    val ssc: StreamingContext = new StreamingContext(spark.sparkContext, Durations.seconds(5))

    val lineDS: ReceiverInputDStream[String] = ssc.socketTextStream("master", 8888)

    /**
     * 从MySQL获取黑名单的信息
     */

    //构建一个集合Set用于保存从MySQL获取到的黑名单 并用于过滤
//    val mdnSet: mutable.HashSet[String] = mutable.HashSet()
//
//    val conn: Connection = DriverManager.getConnection("jdbc:mysql://master:3306/bukong", "root", "123456")
//    val stat: Statement = conn.createStatement()
//    val rs: ResultSet = stat.executeQuery("select mdn from mdn_blacklist")
//    while(rs.next()){
//      val mdn: String = rs.getString("mdn")
//      mdnSet.add(mdn);
//    }
//    stat.close()
//    conn.close()

    /**
     * 一个Batch会封装成一个RDD进行处理
     * 问题:
     * 1、需要实现动态的增加删除黑名单中的人员
     */
//    lineDS
//      .filter(line=>{
//
//        /**
//         * 直接放在filter算子内部
//         * 相当于每个Batch中的每条记录都会创建一次连接 效率很低
//         */
//        val mdnSet: mutable.HashSet[String] = mutable.HashSet()
//
//        val conn: Connection = DriverManager.getConnection("jdbc:mysql://master:3306/bukong", "root", "123456")
//        val stat: Statement = conn.createStatement()
//        val rs: ResultSet = stat.executeQuery("select mdn from mdn_blacklist")
//        while(rs.next()){
//          val mdn: String = rs.getString("mdn")
//          mdnSet.add(mdn);
//        }
//        stat.close()
//        conn.close()
//
//        //从数据中提取mdn 与 黑名单进行比较
//        val mdn: String = line.split(",")(0)
//        mdnSet.contains(mdn)
//      })
//      .print()
val filterDS: DStream[String] = lineDS
  //每个Batch会执行一次 可以将Batch变成RDD进行处理
  //transform的作用实际上是让我们能够使用RDD的API去处理数据
  .transform(rdd => {
    //使用RDD的API进行处理
    //每个Batch 即 每5s会建立一次连接
    val mdnSet: mutable.HashSet[String] = mutable.HashSet()
    val conn: Connection = DriverManager.getConnection("jdbc:mysql://master:3306/bukong", "root", "123456")
    val stat: Statement = conn.createStatement()
    val rs: ResultSet = stat.executeQuery("select mdn from mdn_blacklist")
    while (rs.next()) {
      val mdn: String = rs.getString("mdn")
      mdnSet.add(mdn);
    }
    stat.close()
    conn.close()
    //算子内部使用了算子外部的集合 可以进行广播
    val mdnSetBro: Broadcast[mutable.HashSet[String]] = spark.sparkContext.broadcast(mdnSet)
    rdd.mapPartitions(iter => {
      //将建立连接放在每个Batch内部的RDD然后进行mapPartitions
      //相当于每个Batch中的RDD的每个分区会建立一次连接

      iter.filter(line => {
        //从数据中提取mdn 与 黑名单进行比较
        val mdn: String = line.split(",")(0)
        mdnSetBro.value.contains(mdn)
      })
    })
  })
    //将结果写入MySQL
    filterDS

      /**
       * foreachRDD vs transform
       * 都可以将每个Batch即DStream变成一个个RDD进行处理
       * 如果要写入外部系统 ===> foreachRDD
       * 如果想对数据进行转换 ===> transform
       */
      .foreachRDD(rdd=>{
        //这里的代码还是会在Driver端执行 所以不能在此建立连接
        rdd
          .foreachPartition(iter=>{
            val conn: Connection = DriverManager.getConnection("jdbc:mysql://master:3306/bukong", "root", "123456")
            val preSet: PreparedStatement = conn.prepareStatement("insert into blacklist_info values(?,?,?,?)")
            iter.foreach(line=>{
              val splits: Array[String] = line.split(",")
              val mdn: String = splits(0)
              val start_date: String = splits(1)
              val longitude: String = splits(4)
              val latitude: String = splits(5)
              preSet.setString(1,mdn)
              preSet.setString(2,start_date)
              preSet.setString(3,longitude)
              preSet.setString(4,latitude)
              preSet.addBatch()//将RDD中的每一个分区作为一个批次 使用批量插入
            })
            preSet.executeBatch()
            preSet.close()
            conn.close()
          })
      })

    //启动
    ssc.start()
    ssc.awaitTermination()
    ssc.stop()

  }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值