Spark SQL

Spark SQL

  • 一、Spark SQL概述
  • 二、准备Spark SQL的编程环境
  • 三、Spark SQL程序编程的入口
  • 四、DataFrame的创建
  • 五、DataFrame的编程风格
  • 六、DataSet的创建和使用
  • 七、Spark SQL的函数操作

一、Spark SQL概述

Spark SQL属于Spark计算框架的一部分,是专门负责结构化数据的处理计算框架,Spark SQL提供了两种数据抽象:DataFrame、Dataset,都是基于RDD之上的一种高级数据抽象,在RDD基础之上增加了一个schema表结构。

DataFrame是以前旧版本的数据抽象(untyped类型的数据抽象),Dataset是新版本的数据抽象(typed有类型的数据抽象),新版本当中DataFrame底层就是Dataset[Row]。

Spark SQL特点

  • 易整合
  • 统一的数据访问方式
  • 兼容Hive
  • 标准的数据库连接

二、准备Spark SQL的编程环境

1、创建Spark SQL的编程项目,scala语言支持的

2、引入编程依赖

spark-core_2.12
hadoop-hdfs
spark-sql_2.12

spark-hive_2.12

hadoop的有一个依赖jackson版本和scala2.12版本冲突了,Spark依赖中也有这个依赖,但是默认使用的是pom.xml先引入的那个依赖,把hadoop中jackson依赖排除了即可。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.kang</groupId><artifactId>spark-sql-study</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><name>spark-sql-study</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-hdfs</artifactId><version>3.1.4</version><exclusions><exclusion><groupId>com.fasterxml.jackson.module</groupId><artifactId>*</artifactId></exclusion><exclusion><groupId>com.fasterxml.jackson.core</groupId><artifactId>*</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.apache.spark</groupId><artifactId>spark-core_2.12</artifactId><version>3.1.1</version></dependency><dependency><groupId>org.apache.spark</groupId><artifactId>spark-sql_2.12</artifactId><version>3.1.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.18</version></dependency>
<!--    spark sql on hive--><dependency><groupId>org.apache.spark</groupId><artifactId>spark-hive_2.12</artifactId><version>3.1.1</version></dependency></dependencies>
</project>

三、Spark SQL程序编程的入口

1、SQLContext:只能做SQL编程,无法操作Hive以及使用HQL操作。

2、HiveContext:专门提供用来操作和Hive相关的编程。

3、SparkSession:全新的Spark SQL程序执行入口,把SQLContext和HiveContext功能全部整合了,SparkSession底层封装了一个SparkContext,而且SparkSession可以开启Hive的支持。

package studyimport org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{DataFrame, SparkSession}
/*** Spark SQL的基本案例执行*/
object Demo01 {def main(args: Array[String]): Unit = {/*** 1、创建Spark SQL的程序编程入口*/val sparkConf:SparkConf = new SparkConf()val sc:SparkSession = SparkSession.builder().appName("test").master("local[*]").config(sparkConf).getOrCreate()import sc.implicits._/*** 2、创建DataFrame或者Dataset数据抽象*/val rdd:RDD[(String,Int)] = sc.sparkContext.makeRDD(Array(("zs",20),("ls",30)))val df:DataFrame = rdd.toDF("name","age")df.printSchema()df.show()sc.stop()}
}

四、DataFrame的创建

  • 1、使用隐式转换函数从RDD、Scala集合创建DataFrame
    toDF() toDF(columnName*)

    • 机制:如果集合或者RDD的类型不是Bean,而且再toDF没有传入任何的列名,那么Spark会默认按照列的个数给生成随机的列名,但是如果类型是一个Bean类型,那么toDF产生的随机列名就是bean的属性名。

    • package create.methon1import org.apache.spark.SparkConf
      import org.apache.spark.sql.{DataFrame, SparkSession}
      /*** 1、通过隐式转换函数从Scala集合创建DataFrame*   如果使用隐式转换函数 那么必须引入spark定义的隐式转换函数代码*   sparksession的对象名.implicits._*/
      object Demo01 {def main(args: Array[String]): Unit = {val sparkConf:SparkConf = new SparkConf()val ss:SparkSession = SparkSession.builder().appName("seq to df").master("local[*]").config(sparkConf).getOrCreate()//隐式转换必须导入隐式转换函数类import ss.implicits._/*** 从集合创建DataFrame* 集合一般都是T类型的 T类型如果是Scala自带类型,toDF后面需要跟列名,不跟列名也可以* 集合必须是Seq类型的 而且必须显示的声明为Seq类型*/val array:Seq[(String,Int)] = Array(("zs",20),("ls",30))val df:DataFrame = array.toDF("name","age")df.printSchema()df.show()val array1:Seq[Student] = Array(Student("zs",21),Student("ls",25))val df1:DataFrame = array1.toDF()df1.printSchema()df1.show()ss.stop()}
      }
      
    • package create.methon1import org.apache.spark.SparkConf
      import org.apache.spark.rdd.RDD
      import org.apache.spark.sql.{DataFrame, SparkSession}
      /*** 1、通过隐式转换函数从RDD创建DataFrame*   如果使用隐式转换函数 那么必须引入spark定义的隐式转换函数代码*   sparksession的对象名.implicits._*/
      object Demo02 {def main(args: Array[String]): Unit = {val sparkConf:SparkConf = new SparkConf()val ss:SparkSession = SparkSession.builder().appName("seq to df").master("local[*]").config(sparkConf).getOrCreate()//隐式转换必须导入隐式转换函数类import ss.implicits._/*** 从RDD创建DataFrame*/val array:Seq[(String,Int)] = Array(("zs",20),("ls",30))val rdd:RDD[(String,Int)] = ss.sparkContext.makeRDD(array)val df:DataFrame = rdd.toDF()df.printSchema()df.show()val array1:Seq[Student] = Array(Student("zs",21),Student("ls",25))val rdd1:RDD[Student] = ss.sparkContext.makeRDD(array1)val df1:DataFrame = rdd1.toDF()df1.printSchema()df1.show()ss.stop()}
      }
      
    • package create.methon1case class Student(name:String,age:Int)
      
  • 2、通过SparkSession自带的createDataFrame函数从集合或者RDD中创建DataFrame—使用并不多

    • package create.methon2import org.apache.spark.SparkConf
      import org.apache.spark.sql.types.{DataType, DataTypes, StructField, StructType}
      import org.apache.spark.sql.{DataFrame, Row, SparkSession}
      /*** createDataFrame函数从集合中创建DataFrame*/
      object Demo01 {def main(args: Array[String]): Unit = {val sparkConf: SparkConf = new SparkConf()val ss: SparkSession = SparkSession.builder().appName("seq to df").master("local[*]").config(sparkConf).getOrCreate()/*** 1、通过Scala的seq集合创建DataFrame 列名是自动生成的*/val array:Seq[(String,Int)] = Array(("zs",20),("ls",30))val df:DataFrame = ss.createDataFrame(array)df.printSchema()df.show()val array1:Seq[Student] = Array(Student("zs",20),Student("ls",30))val df1:DataFrame = ss.createDataFrame(array1)df1.printSchema()df1.show()/*** 2、从java集合中创建DataFrame,如果是Java集合,必须传入一个BeanClass* 同时如果Java集合中存放的数据类型是Row类型,那么必须传入StructType指定row的结构** java集合中如果使用BeanClass构建DaraFrame,要求Java集合中存放的数据类型也必须是Bean的类型* BeanClass必须有getter和setter方法*/val list: java.util.List[Student] = java.util.Arrays.asList(Student("ls",20),Student("zs",30))val df2 = ss.createDataFrame(list,classOf[Student])df2.printSchema()df2.show()/*** 3、java集合的类型为row类型*/val list1: java.util.List[Row] = java.util.Arrays.asList(Row("ls",20),Row("zs",30))val df3 = ss.createDataFrame(list1,StructType(java.util.Arrays.asList(StructField("name",DataTypes.StringType),StructField("age",DataTypes.IntegerType))))df3.printSchema()df3.show()ss.stop()}
      }
      
    • package create.method2import create.methon2.Student
      import org.apache.spark.SparkConf
      import org.apache.spark.rdd.RDD
      import org.apache.spark.sql.types.{DataTypes, StructField, StructType}
      import org.apache.spark.sql.{DataFrame, Row, SparkSession}import java.util/*** createDataFrame函数从RDD中创建DataFrame(操作手法完全一致的)*/
      object Demo02 {def main(args: Array[String]): Unit = {val sparkConf: SparkConf = new SparkConf()val ss: SparkSession = SparkSession.builder().config(sparkConf).appName("seq to df").master("local[*]").getOrCreate()/*** 1、通过Scala的seq集合创建DataFrame 列名是自动生成的*/val array:Seq[(String,Int)] = Array(("zs",20),("ls",30))val rdd:RDD[(String,Int)] = ss.sparkContext.makeRDD(array)val df:DataFrame = ss.createDataFrame(rdd)df.printSchema()df.show()val array1: Seq[Student] = Array(Student("zs",20))val rdd1:RDD[Student] = ss.sparkContext.makeRDD(array1)val df1: DataFrame = ss.createDataFrame(rdd1,classOf[Student])df1.printSchema()df1.show()/*** 3、java集合的类型为row类型*/val array2:Array[Row] = Array(Row("zs",20),Row("ww",30))val rdd2:RDD[Row] = ss.sparkContext.makeRDD(array2)val df3 = ss.createDataFrame(rdd2, StructType(Array(StructField("name", DataTypes.StringType), StructField("age", DataTypes.IntegerType))))df3.printSchema()df3.show()ss.stop()}
      }
      
    • package create.methon2import scala.beans.BeanPropertycase class Student(@BeanProperty var name:String, @BeanProperty var age:Int)
      
  • 3、从Spark SQL支持的数据源创建DataFrame(HDFS、Hive、JSON文件、CSV文件等等):使用频率最高的

    • 外部存储HDFS中读取数据成为DataFrame

      • ss.read.format(“jsonxx”).load(“path”) 不太好用
      • ss.read.option(key,value).option(…).csv/json(path)
    • 从jdbc支持的数据库创建DataFrame

      • ss.read.jdbc(url,table,properties)
      package create.methon3import org.apache.spark.SparkConf
      import org.apache.spark.sql.{DataFrame, SparkSession}import java.util.Properties/*** 从外部存储读取数据成为DataFrame*/
      object Demo01 {def main(args: Array[String]): Unit = {val sparkConf:SparkConf = new SparkConf()val ss:SparkSession = SparkSession.builder().appName("storage to df").master("local[*]").getOrCreate()/*** 从csv文件读取数据成为DataFrame*/val df:DataFrame = ss.read.option("header","true").format("csv").load("file:///D://Desktop/Student.csv")df.printSchema()df.show()/*** 读取模式有三种:* permissive:默认的* dropMalformed* failfast*/val df1:DataFrame = ss.read.option("header","true").format("csv").option("mode","permissive").csv("file:///D://Desktop/Student.csv")df1.printSchema()df1.show()/*** 从json文件创建DataFrame* json文件中要求一个json对象独占一行*/val df2:DataFrame = ss.read.option("mode","dropMalformed").json("file:///D://Desktop/Student.json")df2.printSchema()df2.show()/*** 从普通的文本文档创建DataFrame---不太实用*/val df3 = ss.read.text("file:///D://Desktop/Student.csv")df3.printSchema()df3.show()/*** 从JDBC可以连接的数据库(rdbms、Hive)创建DataFrame*/val prop:Properties = new Properties()prop.setProperty("user","root")prop.setProperty("password","root")val df4 = ss.read.jdbc("jdbc:mysql://localhost:3306/spark?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8","student",prop)df4.printSchema()df4.show()ss.stop()}
      }
      
    • 读取Hive数据成为DataFrame

      • 1、通过SparkSession开启Hive的支持

      • 2、引入spark-hive的编程依赖

      • 3、通过ss.sql()

      • package create.methon3import org.apache.spark.SparkConf
        import org.apache.spark.sql.{DataFrame, SparkSession}/*** 连接Hive创建DataFrame:*   1、jdbc方式(基本的操作只能查询表中的所有字段 所有数据)*   2、Spark SQL On Hive:用Hive作为数据存储,用Spark直连Hive 操作Hive中的数据*     不是使用JDBC的方式,而是使用的Hive的元数据库来完成的*     两步操作:(1)需要把Hive的配置文件放到项目的resources目录下,如果在集群环境下,我们需要把hive的配置文件放到spark的conf目录下,(2)需要开启SparkSession的hive支持*/
        object Demo02 {def main(args: Array[String]): Unit = {val sparkConf:SparkConf = new SparkConf()val sparkSession:SparkSession = SparkSession.builder().appName("spark sql on hive").master("local[*]").config(sparkConf).enableHiveSupport().getOrCreate()/*** 从Hive中读取数据创建DataFrame*/val df:DataFrame = sparkSession.sql("select * from project.ods_user_behavior_origin")df.printSchema()df.show()//新建数据表sparkSession.sql("create table test (name string,age int,sex string) row format delimited fields terminated by '*'")sparkSession.stop()}
        }
        
  • 4、从其他的DataFrame转换的来

五、DataFrame的编程风格

  • 通过代码来操作计算DataFrame中数据

  • DSL编程风格

    • DataFrame和Dataset提供了一系列的API操作,API说白了就是Spark SQL中算子操作,可以通过算子操作来获取DataFrame或者Dataset中的数据。

    • 转换算子

      • RDD具备的算子DataFrame基本上都可以使用。
      • DataFrame还增加了一些和SQL操作有关的算子:
        selectExpr、where/filter、groupBy、orderBy/sort、limit、join
      操作算子算子概念
      limit获得指定前n行数据并形成新的 dataframe
      where、filter条件过滤
      select根据传入的 string 类型字段名,获取指定字段的值,以 DataFrame 类型返回
      join按指定的列进行合并两个dataframe
      groupBy按指定字段进行分组,后面可加聚合函数对分组后的数据进行操作
      orderBy、sort按指定字段排序
      selectExpr对指定字段进行特殊处理,可以对指定字段调用 UDF 函数或者指定别名;selectExpr 传入 string 类型的参数,返回 DataFrame 对象。
    • 行动算子

      • RDD具备的行动算子DataFrame和Dataset也都具备一些

      • collect/collectAsList:不建议使用,尤其是数据量特别庞大的情况下

      • foreach/foreachPartition

      • 获取结果集的一部分数据

        • first/take(n)/head(n)/takeAsList(n)/tail(n)
        • 获取的返回值类型就是Dataset存储的数据类型
      • printSchema:获取DataFrame或者Dataset的表结构的

      • show()/show(num,truncate:boolean)/show(num,truncate:Int)/show(num,truncate:Int,ver:boolean)

      • 保存输出的算子

        • 文件系统

          • df/ds.write.mode(SaveMode).csv/json/parquet/orc/text(path–目录)
          • text纯文本文档要求DataFrame和Dataset的结果集只有一列 而且列必须是String类型
        • JDBC支持的数据库

          • df/ds.write.mode().jdbc

          • foreach|foreachPartition

          • package opratorimport org.apache.spark.SparkConf
            import org.apache.spark.sql.{Dataset, SaveMode, SparkSession}import java.util.Propertiesobject Demo03 {def main(args: Array[String]): Unit = {val sparkConf: SparkConf = new SparkConf()val ss: SparkSession = SparkSession.builder().appName("action").master("local[*]").config(sparkConf).enableHiveSupport().getOrCreate()import ss.implicits._/*** 创建DataFrame*/val array:Seq[(String,Int,String)] = Array(("zs",20,"man"),("ls",30,"woman"),("ww",40,"man"),("ml",50,"woman"))val dataset:Dataset[(String,Int,String)] = array.toDS()
            //    dataset.show()/*** 保存到MySQL当中  JDBC连接保存*/val prop = new Properties()prop.setProperty("user","root")prop.setProperty("password","root")dataset.write.mode(SaveMode.Overwrite).jdbc("jdbc:mysql://localhost:3306/spark?serverTimezone=Asia/Shanghai","Student",prop)ss.stop()}
            }
            
          • 执行前

          image-20230930105818773

          • 执行后

          image-20230930105855493

        • Hive

          • df/ds.write.mode().saveAsTable(“库名.表名”)

          • 1、保证hive支持开启的

          • 2、保存的数据底层在HDFS上以parquet文件格式保存的

          • dataset.write.mode(SaveMode.Append).saveAsTable("default.demo")
            
          • image-20230930110937382

  • SQL编程风格

    • 1、将创建的DataFrame加载为一个临时表格
    • 2、然后通过ss.sql(sql语句)进行数据的查询
    package opratorimport org.apache.spark.SparkConf
    import org.apache.spark.sql.{DataFrame, SparkSession}object Demo01 {def main(args: Array[String]): Unit = {val sparkConf:SparkConf = new SparkConf()val ss:SparkSession = SparkSession.builder().appName("spark sql on hive").enableHiveSupport().master("local[*]").getOrCreate()/*** 从Hive中读取数据创建DataFrame*/val df:DataFrame = ss.sql("select * from project.ods_user_behavior_origin")df.createTempView("test_spark_sql")val df1 = ss.sql("select ip_addr,parse_url(request_url,'HOST') as host,age from test_spark_sql")df1.show()df.selectExpr("ip_addr","parse_url(request_url,'HOST') as host").show()df.select("age","ip_addr").where("age>40").show()ss.stop()}
    }
    

六、DataSet的创建和使用

Dataset有类型,DataFrame无类型的。

创建

  • 1、隐式转换,toDS()

    • package createdatasetimport org.apache.spark.SparkConf
      import org.apache.spark.sql.{Dataset, SparkSession}import scala.beans.BeanProperty
      case  class Student(@BeanProperty var name:String,@BeanProperty var age:Int)
      object Demo01 {def main(args: Array[String]): Unit = {val sparkConf:SparkConf = new SparkConf()val sparkSession:SparkSession = SparkSession.builder().appName("createds").config(sparkConf).master("local[*]").getOrCreate()import sparkSession.implicits._/*** 通过隐式转换从集合或者rdd创建Dataset*/val array:Seq[(String,Int)] = Array(("zs",20),("ls",30))val ds:Dataset[(String,Int)] = array.toDS()ds.printSchema()ds.show()val array1:Seq[Student] = Array(Student("zs",30),Student("ls",20))val ds1:Dataset[Student] = array1.toDS()ds1.printSchema()ds1.show()sparkSession.stop()}
      }
      
    • image-20230930102553512

  • 2、通过SparkSession的createDataset函数创建

    • /***  通过SparkSession的createDataset函数创建*/
      val rdd:RDD[Student] = sparkSession.sparkContext.makeRDD(array1)
      val ds2:Dataset[Student] = sparkSession.createDataset(rdd)
      ds2.show()
      
    • image-20230930103045838

  • 3、通过DataFrame转换得到Dataset
    df.as[类型-Bean对象必须有getter、setter方法]
    也是需要隐式转换的

    • /*** 通过DataFrame转换得到Dataset*/
      val df:DataFrame = sparkSession.createDataFrame(rdd, classOf[Student])
      val ds3:Dataset[Student] = df.as[Student]
      ds3.show()
      
    • image-20230930104153414

七、Spark SQL的函数操作

Spark SQL基本上常见的MySQL、Hive中函数都是支持的。

package functionimport org.apache.spark.SparkConf
import org.apache.spark.sql.{DataFrame, SparkSession}object Demo01 {def main(args: Array[String]): Unit = {val sparkConf:SparkConf = new SparkConf()val ss:SparkSession = SparkSession.builder().appName("function").master("local[*]").enableHiveSupport().config(sparkConf).getOrCreate()import ss.implicits._val array:Seq[(Int,String,Int)] = Array((1,"zs",80),(1,"ls",90),(1,"ww",65),(1,"ml",70),(2,"zsf",70),(2,"zwj",67),(2,"qf",76),(2,"dy",80))val df:DataFrame = array.toDF("classId","studentName","score")df.createOrReplaceTempView("student_score_temp")ss.sql("select *,row_number() over(partition by classId order by score desc) as class_rank from student_score_temp").show()ss.stop()}
}

image-20230930112644035

ss.sql("select * from (select *,row_number() over(partition by classId order by score desc) as class_rank from student_score_temp) as temp where temp.class_rank < 2").show()

image-20230930112904468

val array: Seq[(String, String)] = Array(("zs", "play,eat,drink"), ("ls", "play,game,run"))
val df: DataFrame = array.toDF("name", "hobby")
df.createOrReplaceTempView("temp")
/*** zs play,eat,drink* ls play,game,run* zs play* zs eat*/
ss.sql("select temp.name,a.bobby from temp lateral view explode(split(hobby,',')) a as bobby").show()

image-20230930114025740

自定义函数

  • ss.udf.register(name,函数)
package functionimport org.apache.spark.SparkConf
import org.apache.spark.sql.expressions.Aggregator
import org.apache.spark.sql.{DataFrame, Encoder, Encoders, SparkSession}object Demo02 {def main(args: Array[String]): Unit = {val sparkConf: SparkConf = new SparkConf()val ss: SparkSession = SparkSession.builder().appName("createMyFunction").master("local[*]").config(sparkConf).enableHiveSupport().getOrCreate()import ss.implicits._ss.udf.register("my_length",(name:String)=>{name.length})val array: Seq[(String, String)] = Array(("zs", "play,eat,drink"), ("ls", "play,game,run"))val df: DataFrame = array.toDF("name", "hobby")df.selectExpr("my_length(hobby)").show()ss.udf.register("my_avg",new My())val array1: Seq[(String, Int)] = Array(("zs", 20), ("ls", 30))val df1: DataFrame = array1.toDF("name", "score")df1.selectExpr("my_avg(score)").show()ss.stop()}
}
class My_AVG extends Aggregator[Int,(Int,Int),java.lang.Double]{/*** 设置初始值的 是缓冲区的初始值* @return*/override def zero: (Int, Int) = (0,0)/*** 当输入一个结果之后,缓冲区如何对输入的结果进行计算** @param b 缓冲区* @param a 输入的某一个值* @return*/override def reduce(b: (Int, Int), a: Int): (Int, Int) = {(b._1+a,b._2+1)}/*** 分区之间的合并** @param b1* @param b2* @return*/override def merge(b1: (Int, Int), b2: (Int, Int)): (Int, Int) = {(b1._1+b2._1,b1._2+b2._2)}/*** 最后的结果** @param reduction* @return*/override def finish(reduction: (Int, Int)): java.lang.Double = {reduction._1.toDouble / reduction._2}override def bufferEncoder: Encoder[(Int, Int)] = Encoders.product[(Int, Int)]override def outputEncoder: Encoder[java.lang.Double] = Encoders.DOUBLE
}
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
package functionimport org.apache.spark.sql.Row
import org.apache.spark.sql.expressions.{MutableAggregationBuffer, UserDefinedAggregateFunction}
import org.apache.spark.sql.types.{DataType, DataTypes, StructField, StructType}class My extends UserDefinedAggregateFunction{override def inputSchema: StructType = StructType(Array(StructField("score",DataTypes.IntegerType)))override def bufferSchema: StructType = StructType(Array(StructField("sum",DataTypes.IntegerType),StructField("count",DataTypes.IntegerType)))override def dataType: DataType = DataTypes.DoubleTypeoverride def deterministic: Boolean = trueoverride def initialize(buffer: MutableAggregationBuffer): Unit = {buffer(0) = 0buffer(1) = 0}override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {buffer(0) = buffer.getInt(0)+input.getInt(0)buffer(1) = buffer.getInt(1)+1}override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {buffer1(0) = buffer1.getInt(0) + buffer2.getInt(0)buffer1(1) = buffer1.getInt(1) + buffer2.getInt(1)}override def evaluate(buffer: Row): Any = {buffer.getInt(0).toDouble/buffer.getInt(1)}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/91893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NIO基础

nio : non-blocking io 非阻塞IO 1. 三大组件 1.1 channel和buffer channel 有点像stream &#xff0c;他就是读写数据的双向通道&#xff0c;可以从channel将数据读入buffer&#xff0c;也可以将buffer的数据写入channel&#xff0c;之前的stream 要么输入&#xff0c;要么…

建筑能源管理(3)——建筑能源监管

为了全面落实科学发展观&#xff0c;提高建筑能源管理水平&#xff0c;进一步降低能源和水资源消耗、合理利用资源&#xff0c;以政府办公建筑和大型公共建筑的运行节能管理为突破口&#xff0c;建立了既有政府办公建筑和大型公共建筑运行节能监管体系&#xff0c;旨在提高政府…

28271-2012 米制超细牙螺纹 公差

声明 本文是学习GB-T 28271-2012 米制超细牙螺纹 公差. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了米制超细牙螺纹的公差和标记。 本标准适用于精密仪器和电子设备等领域的螺纹连接。 2 规范性引用文件 下列文件对于本文件…

windows server 2019 、win11安装docker desktop

Docker Desktop Docker Desktop是可以部署在windows运行docker的应用服务&#xff0c;其基于windos的Hyper-V服务和WSL2内核在windos上创建一个子系统(linux)&#xff0c;从而实现其在windows上运行docker。 前提条件 WSL 查看wsl是否安装 我们可以直接在 cmd 或 powershe…

MySql出错点

一、DDL 1.修改表&#xff0c;添加新的字段时&#xff0c;不要加引号 2.在修改表中字段的类型时&#xff0c;会发生数据截断。 像DATETIME 转化为 TIME 二、DML 1.插入和删除的注意点 2.可以通过 select 来协助插入 3.

Linux 基本语句_4_指针和函数

指针函数 顾名思义&#xff0c;即返回值为指针的函数 int * f (int n){int *p NULL;//空指针return p;//返回一个地址 }函数指针 指向函数的指针&#xff0c;每个函数都有自己的入口地址&#xff0c;函数指针专门指向这些地址#include <stdio.h>int max(int a, int b)…

【Linux】完美解决ubuntu18.04下vi不能使用方向键和退格键

今天在刚安装完ubuntu18.04&#xff0c;发现在使用vi命令配置文件时使用方向键并不能移动光标&#xff0c;而是出现一堆奇怪的英文字母&#xff0c;使用退格键也不能正常地删除内容&#xff0c;用惯了CentOS的我已经感觉到ubuntu没有centos用着丝滑&#xff0c;但是没办法&…

【C++】类和对象(中)

一、类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。但是空类中并不是真的什么都没有&#xff0c;任何类在什么都不写的时候&#xff0c;编译器会自动生成以下 6 个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生成…

5G消息发展的前景与挑战

随着5G技术的快速发展和普及&#xff0c;5G消息正逐渐成为全球通信领域的新焦点。 随着5G技术的快速发展和普及&#xff0c;5G消息正逐渐成为全球通信领域的新焦点。 5G消息发展呈现规模化、产业化趋势 自2020年4月国内三大运营商联合发布5G消息白皮书以来&#xff0c;已经过…

【C语言】通讯录系统实现 (保姆级教程,附源码)

目录 1、通讯录系统介绍 2、代码分装 3、代码实现步骤 3.1、制作菜单menu函数以及游戏运行逻辑流程 3.2、封装人的信息PeoInfo以及通讯录Contact结构体类型 3.3、初始化通讯录InitContact函数 3.4、增加联系人AddContact函数 3.5、显示所有联系人ShowContact函数 3.6、…

【Idea】idea、datagrip设置输入法

https://github.com/RikudouPatrickstar/JetBrainsRuntime-for-Linux-x64/releases/tag/jbr-release-17.0.6b829.5https://github.com/RikudouPatrickstar/JetBrainsRuntime-for-Linux-x64/releases/tag/jbr-release-17.0.6b829.5 下载后解压并重命名为 jbr, 然后替换对应 ide…

CTF-XSS

知识 例子 。2022 CNSS夏令营 To_be_Admin_Again_and_Again XSS攻击. 与admin有关, 可以尝试http://1.117.6.207:65005/admin, 显示Get out, HACKER! Only admin can see the flag!, 说明需要一个admin的验证, 这里想到获取admin的cookie. 每条留言会自动查看, 可以使用XS…

Python-Flask:编写自动化连接demo脚本:v1.0.0

主函数&#xff1a; # _*_ Coding : UTF-8 _*_ # Time : 13:14 # Author : YYZ # File : Flask # Project : Python_Project_爬虫 import jsonfrom flask import Flask,request,jsonify import sshapi Flask(__name__)# methods: 指定请求方式 接口解析参数host host_info[…

TSM动作识别模型【详解】

文章目录 本文使用的是somethingv2数据集&#xff0c;解压后是如下形式&#xff1b; 由于该压缩数据进行了分卷操作&#xff0c;需要合并后才能进行解压。首先我们将下面4个json文件剪贴到其他文件夹&#xff0c;只保留00-19的文件&#xff0c;然后在该文件夹下打开cmd&#xf…

模块化CSS

1、什么是模块化CSS 模块化CSS是一种将CSS样式表的规则和样式定义封装到模块或组件级别的方法&#xff0c;以便于更好地管理、维护和组织样式代码。这种方法通过将样式与特定的HTML元素或组件相关联&#xff0c;提供了一种更具可维护性、可复用性和隔离性的方式来处理样式。简单…

机器人制作开源方案 | 四轴飞行器

1. 概述 基于探索者搭建的模块化四轴飞行器研究平台&#xff0c;采用独特的设计方式&#xff0c;可实现在室内完成对四轴飞行器、无人机等运动控制的原理研究&#xff0c;以及学习飞行控制的原理知识。 2. 组装 请按照下图进行机架的组装。 整体图 请解压文末资料中的 /软件/Mi…

【LeetCode热题100】--226.翻转二叉树

226.翻转二叉树 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …

【聊天系统的优化】RPC方式的优化

RPC方式的优化 聊天系统的中RPC的选择Jsonprotobufmsgpack 聊天系统的中RPC的选择 在RPC方式中&#xff0c;常用的三种方式&#xff1a;Json&#xff0c;protobuf&#xff0c;Msgback 设定一个简单的加和服务&#xff0c;客户端发送一个list给服务端&#xff0c;需要将list的…

QT的ui设计中改变样式表的用法

在QT的ui设计中,我们右键会弹出一个改变样式表的选项,很多人不知道这个是干什么的。 首先我们来看下具体的界面 首先我们说一下这个功能具体是干嘛的, 我们在设置很多控件在界面上之后,常常都是使用系统默认的样式,但是当有些时候为了美化界面我们需要对一些控件进行美化…

Kafka-Kerberos票据刷新问题

线上kafka使用了 kerberos 认证&#xff0c;每隔24小时&#xff0c;票据过期&#xff0c;无法自动续期&#xff0c;出现消息发送失败问题。 从日志可以发现会有如下报错&#xff1a; 2023-09-14 17:48:47,144 [kafka-kerberos-refresh-thread-kafka/hdp-1HADOOP.COM] [] WARN …