java特殊文件、日志技术、多线程

一、属性文件

1.1 特殊文件概述

像这种普通的文本文件,没有任何规律可言,不方便程序对文件中的数据信息处理。

在以后的Java开发过程中还会遇到一些特殊的文本文件,这些文件是有一些格式要求的,方便程序对文件中的数据进行处理。

1.2 Properties属性文件

属性文件的格式:

  1. 属性文件后缀以.properties结尾

  2. 属性文件里面的每一行都是一个键值对,键和值中间用=隔开。比如: admin=123456

  3. #表示这样是注释信息,是用来解释这一行配置是什么意思。

  4. 每一行末尾不要习惯性加分号,以及空格等字符;不然会把分号,空格会当做值的一部分。

  5. 键不能重复,值可以重复

如下图所示

接下来,我们学习如何读取属性文件中的数据。这里需要给同学们,介绍一个来叫Properties.

1.Properties是什么?Properties是Map接口下面的一个实现类,所以Properties也是一种双列集合,用来存储键值对。    但是一般不会把它当做集合来使用。2.Properties核心作用?Properties类的对象,用来表示属性文件,可以用来读取属性文件中的键值对。
  • 使用Properties读取属性文件中的键值对,需要用到的方法如下。

实用Properties读取属性文件的步骤如下

1、创建一个Properties的对象出来(键值对集合,空容器)
2、调用load(字符输入流/字节输入流)方法,开始加载属性文件中的键值对数据到properties对象中去
3、调用getProperty(键)方法,根据键取值

代码如下:

/*** 目标:掌握使用Properties类读取属性文件中的键值对信息。*/
public class PropertiesTest1 {public static void main(String[] args) throws Exception {// 1、创建一个Properties的对象出来(键值对集合,空容器)Properties properties = new Properties();System.out.println(properties);
​// 2、开始加载属性文件中的键值对数据到properties对象中去properties.load(new FileReader("properties-xml-log-app\\src\\users.properties"));System.out.println(properties);
​// 3、根据键取值System.out.println(properties.getProperty("赵敏"));System.out.println(properties.getProperty("张无忌"));
​// 4、遍历全部的键和值。//获取键的集合Set<String> keys = properties.stringPropertyNames();for (String key : keys) {//再根据键获取值String value = properties.getProperty(key);System.out.println(key + "---->" + value);}properties.forEach((k, v) -> {System.out.println(k + "---->" + v);});}
}
  • 使用Properties往属性文件中写键值对,需要用到的方法如下

往Properties属性文件中写键值对的步骤如下

1、先准备一个.properties属性文件,按照格式写几个键值对
1、创建Properties对象出来,
2、调用setProperty存储一些键值对数据
3、调用store(字符输出流/字节输出流, 注释),将Properties集合中的键和值写到文件中注意:第二个参数是注释,必须得加;

先准备一个users.properties属性文件,如下图所示

接下来,编写代码读取上面的属性文件。代码如下:

public class PropertiesTest2 {public static void main(String[] args) throws Exception {// 1、创建Properties对象出来,先用它存储一些键值对数据Properties properties = new Properties();properties.setProperty("张无忌", "minmin");properties.setProperty("殷素素", "cuishan");properties.setProperty("张翠山", "susu");
​// 2、把properties对象中的键值对数据存入到属性文件中去properties.store(new FileWriter("properties-xml-log-app/src/users2.properties"), "i saved many users!");
​}
}

运行上面的代码,user2.properties 配置文件打开效果如下图所示。

二、XML文件

2.1 XML文件概述

首先,我们来认识一下,什么是XML?

XML是可扩展的标记语言,意思是它是由一些标签组成 的,而这些标签是自己定义的。本质上一种数据格式,可以用来表示复杂的数据关系。

XML文件有如下的特点:

  • XML中的<标签名> 称为一个标签或者一个元素,一般是成对出现的。

  • XML中的标签名可以自己定义(可扩展),但是必须要正确的嵌套

  • XML中只能有一个根标签。

  • XML标准中可以有属性

  • XML必须第一行有一个文档声明,格式是固定的<?xml version="1.0" encoding="UTF-8"?>

  • XML文件必须是以.xml为后缀结尾

如下图所示

新建一个XML文件,试试!

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 注释:以上抬头声明必须放在第一行,必须有 -->
<!--  根标签只能有一个 -->
<users><user id="1" desc="第一个用户"><name>张无忌</name><sex>男</sex><地址>光明顶</地址><password>minmin</password></user><people>很多人</people><user id="2"><name>敏敏</name><sex>女</sex><地址>光明顶</地址><password>wuji</password></user>
</users>

上面XML文件中的数据格式是最为常见的,标签有属性、文本、还有合理的嵌套。XML文件中除了写以上的数据格式之外,还有一些特殊的字符不能直接写。

  • <,>,&等这些符号不能出现在标签的文本中,因为标签格式本身就有<>,会和标签格式冲突。

    如果标签文本中有这些特殊字符,需要用一些占位符代替。

    &lt;  表示 <
    &gt;  表示 >
    &amp; 表示 &
    &apos; 表示 '
    &quot; 表示 "
    <data> 3 &lt; 2 &amp;&amp; 5 &gt; 4 </data>
  • 如果在标签文本中,出现大量的特殊字符,不想使用特殊字符,此时可以用CDATA区,格式如下

    <data1><![CDATA[3 < 2 && 5 > 4]]>
    </data1>

XML在实际开发中有什么作用?

2.2 XML解析1

使用程序读取XML文件中的数据,称之为XML解析。这里并不需要我们自己写IO流代码去读取xml文件中的数据。其实有很多开源的,好用的XML解析框架,最知名的是DOM4J(第三方开发的)

由于DOM4J是第三方提供的,所以需要把第三方提供的Jar包导入到自己的项目中来,才可以使用。具体步骤如下:

DOM4J解析XML文件的思想是:文档对象模型(意思是把整个XML文档、每一个标签、每一个属性都等都当做对象来看待)。Dowument对象表示真个XML文档、Element对象表示标签(元素)、Attribute对象表示属性、标签中的内容就是文本

DOM4J解析XML需要用到的方法如下图所示

XML解析的过程,是从根元素开始,从外层往里层解析。 我们先把Document对象,和根元素获取出来

public class Dom4JTest1 {public static void main(String[] args) throws Exception {// 1、创建一个Dom4J框架提供的解析器对象SAXReader saxReader = new SAXReader();
​// 2、使用saxReader对象把需要解析的XML文件读成一个Document对象。Document document =saxReader.read("properties-xml-log-app\\src\\helloworld.xml");
​// 3、从文档对象中解析XML文件的全部数据了Element root = document.getRootElement();System.out.println(root.getName());}
}

2.3 XML解析2

获取到XML文件的根元素之后,接下来,就可以用根元素在获取到它里面的子元素(包括子标签、表属性等)。需要用到的方法如下图所示

接下来,把上面的方法先一个一个的演示一下。

public class Dom4JTest1 {public static void main(String[] args) throws Exception {// 1、创建一个Dom4J框架提供的解析器对象SAXReader saxReader = new SAXReader();
​// 2、使用saxReader对象把需要解析的XML文件读成一个Document对象。Document document =saxReader.read("properties-xml-log-app\\src\\helloworld.xml");
​// 3、从文档对象中解析XML文件的全部数据了Element root = document.getRootElement();System.out.println(root.getName());
​// 4、获取根元素下的全部一级子元素。// List<Element> elements = root.elements();List<Element> elements = root.elements("user");for (Element element : elements) {System.out.println(element.getName());}
​// 5、获取当前元素下的某个子元素。Element people = root.element("people");System.out.println(people.getText());
​// 如果下面有很多子元素user,默认获取第一个。Element user = root.element("user");System.out.println(user.elementText("name"));
​// 6、获取元素的属性信息呢?System.out.println(user.attributeValue("id"));Attribute id = user.attribute("id");System.out.println(id.getName());System.out.println(id.getValue());
​List<Attribute> attributes = user.attributes();for (Attribute attribute : attributes) {System.out.println(attribute.getName() + "=" + attribute.getValue());}
​// 7、如何获取全部的文本内容:获取当前元素下的子元素文本值System.out.println(user.elementText("name"));System.out.println(user.elementText("地址"));System.out.println(user.elementTextTrim("地址")); // 取出文本去除前后空格System.out.println(user.elementText("password"));
​Element data = user.element("data");System.out.println(data.getText());System.out.println(data.getTextTrim()); // 取出文本去除前后空格}
}

2.4 XML文件写入

XML解析,意思就是使用程序把XML文件中的数据读取出来。反过来能不能往XML文件中写入数据呢? 答案是可以的。

DOM4J也提供了往XML文件中写标签的方法,但是用起来比较麻烦。这里不建议使用

我们自己使用StringBuilder按照标签的格式拼接,然后再使用BufferedWriter写到XML文件中去就可以了。

public class Dom4JTest2 {public static void main(String[] args) {// 1、使用一个StringBuilder对象来拼接XML格式的数据。StringBuilder sb = new StringBuilder();sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n");sb.append("<book>\r\n");sb.append("\t<name>").append("从入门到跑路").append("</name>\r\n");sb.append("\t<author>").append("dlei").append("</author>\r\n");sb.append("\t<price>").append(999.99).append("</price>\r\n");sb.append("</book>");
​try (BufferedWriter bw = new BufferedWriter(new FileWriter("properties-xml-log-app/src/book.xml"));){bw.write(sb.toString());} catch (Exception e) {e.printStackTrace();}
​}
}

2.5 XML约束(了解)

什么是XML约束?

XML约束指的是限制XML文件中的标签或者属性,只能按照规定的格式写。

比如我在项目中,想约束一个XML文件中的标签只能写<书>、<书名>、<作者>、<售价>这几个标签,如果写其他标签就报错。

怎么才能达到上面的效果呢?有两种约束技术,一种是DTD约束、一种是Schame约束。

  • DTD约束案例

    如下图所示book.xml中引入了DTD约束文件,book.xml文件中的标签就受到DTD文件的约束

    DTD文件解释

    <!ELEMENT 书架(书+)>   表示根标签是<书架>,并且书架中有子标签<书>
    <!ELEMENT 书(书名、作者、售价)> 表示书是一个标签,且书中有子标签<书名>、<作者>、<售价>
    <!ELEMENT 书名(#PCDATA)>  表示<书名>是一个标签,且<书名>里面是普通文本
    <!ELEMENT 作者(#PCDATA)>  表示<作者>是一个标签,且<作者>里面是普通文本
    <!ELEMENT 售价(#PCDATA)>  表示<售价>是一个标签,且<售价>里面是普通文本

  • Schame约束案例

    如下图所示,左边的book2.xml文件就受到右边schame文件(.xsd结尾的文件)的约束。

三、日志技术

3.1 日志概述

想搞清楚什么是日志,其实可以通过下面几个问题来了解的。

  • 系统系统能记住某些数据被谁操作,比如被谁删除了?

  • 想分析用户浏览系统的具体情况,比如挖掘用户的具体喜好?

  • 当系统在开发中或者上线后出现了Bug,崩溃了,该通过什么去分析,定位Bug?

而日志就可以帮我们解决以上的问题。所以日志就好比生活中的日记,日记可以记录生活中的点点滴滴;而程序中的日志,通常就是一个文件,里面记录了程序运行过程中产生的各种数据。

日志技术有如下好处

  1. 日志可以将系统执行的信息,方便的记录到指定位置,可以是控制台、可以是文件、可以是数据库中。

  2. 日志可以随时以开关的形式控制启停,无需侵入到源代码中去修改。

3.2 日志的体系

所谓日志框架就是由一些牛人或者第三方公司已经做好的实现代码,后来者就可以直接拿过去使用。

日志框架有很多种,比如有JUL(java.util.logging)、Log4j、logback等。但是这些日志框架如果使用的API方法都不一样的话,使用者的学习成本就很高。为了降低程序员的学习压力,行内提供了一套日志接口,然后所有的日志框架都按照日志接口的API来实现就可以了。

这样程序员只要会一套日志框架,那么其他的也就可以通过用,甚至可以在多套日志框架之间来回切换。比较常用的日志框架,和日志接口的关系如下图所示

这里推荐使用Logback日志框架,也在行业中最为广泛使用的。

Logback日志分为哪几个模块

3.3 Logback快速入门

由于Logback是第三方提供的技术,所以首先需要啊将Jar包引入到项目中,具体步骤如下

  1. 在资料中找到slftj-api.jar、logback-core.jar、logback-classes.jar 这三个jar包,复制一下

  2. 在当前模块下面新建一个lib文件夹,把刚刚复制的三个jar包都粘贴到此处

  3. 从资料中找到logback.xml配置文件,将此文件复制粘贴到src目录下(必须是src目录)

  4. 然后就可以开始写代码了,在代码中创建一个日志记录日对象

    public static final Logger LOGGER = LoggerFactory.getLogger("当前类名");
  5. 开始记录日志,代码如下

    public class LogBackTest {// 创建一个Logger日志对象public static final Logger LOGGER = LoggerFactory.getLogger("LogBackTest");
    ​public static void main(String[] args) {//while (true) {try {LOGGER.info("chu法方法开始执行~~~");chu(10, 0);LOGGER.info("chu法方法执行成功~~~");} catch (Exception e) {LOGGER.error("chu法方法执行失败了,出现了bug~~~");}//}}
    ​public static void chu(int a, int b){LOGGER.debug("参数a:" + a);LOGGER.debug("参数b:" + b);int c = a / b;LOGGER.info("结果是:" + c);}
    }

当我们运行程序时,就可以看到控制台记录的日志

同时在文件中,也有一份这样的日志信息。文件在哪里内,从配置文件中去找

打开D:/log/itheima-data.log看一下文件中是否有记录日志吧!!

3.4 日志配置文件

Logback提供了一个核心配置文件logback.xml,日志框架在记录日志时会读取配置文件中的配置信息,从而记录日志的形式。具体可以做哪些配置呢?

1. 可以配置日志输出的位置是文件、还是控制台
2. 可以配置日志输出的格式
3. 还可以配置日志关闭和开启、以及哪些日志输出哪些日志不输出。
  • 如下图所示,控制日志往文件中输出,还是往控制台输出

  • 如下图所示,控制打开和关闭日志

  • 如下图所示,控制日志的输出的格式

    日志格式是由一些特殊的符号组成,可以根据需要删减不想看到的部分。比如不想看到线程名那就不要[%thread]。但是不建议同学们更改这些格式,因为这些都是日志很基本的信息。

3.5 配置日志级别

  • 在哪里配置日志级别呢?如下图所示

  • Logback只输出大于或者等于核心配置文件配置的日志级别信息。小于配置级别的日志信息,不被记录。

    配置的是trace,则trace、debug、info、warn、error级别的日志都被输出
    配置的是debug, 则debug、info、warn、error级别的日志被输出
    配置的是info,则info、warn、error级别的日志被输出
    ...

三、多线程

 线程其实是程序中的一条执行路径。

我们之前写过的程序,其实都是单线程程序,如下图代码,如果前面的for循环没有执行完,for循环下面的代码是不会执行的。

怎样的程序才是多线程程序呢? 如下图所示,12306网站就是支持多线程的,因为同时可以有很多人一起进入网站购票,而且每一个人互不影响。再比如百度网盘,可以同时下载或者上传多个文件。这些程序中其实就有多条执行路径,每一条执行执行路径就是一条线程,所以这样的程序就是多线程程序。

4.1 线程创建方式1

Java为开发者提供了一个类叫做Thread,此类的对象用来表示线程。创建线程并执行线程的步骤如下

1.定义一个子类继承Thread类,并重写run方法
2.创建Thread的子类对象
3.调用start方法启动线程(启动线程后,会自动执行run方法中的代码)

代码如下

public class MyThread extends Thread{// 2、必须重写Thread类的run方法@Overridepublic void run() {// 描述线程的执行任务。for (int i = 1; i <= 5; i++) {System.out.println("子线程MyThread输出:" + i);}}
}

再定义一个测试类,在测试类中创建MyThread线程对象,并启动线程

public class ThreadTest1 {// main方法是由一条默认的主线程负责执行。public static void main(String[] args) {// 3、创建MyThread线程类的对象代表一个线程Thread t = new MyThread();// 4、启动线程(自动执行run方法的)t.start(); 
​for (int i = 1; i <= 5; i++) {System.out.println("主线程main输出:" + i);}}
}

打印结果如下图所示,我们会发现MyThread和main线程在相互抢夺CPU的执行权(注意:哪一个线程先执行,哪一个线程后执行,目前我们是无法控制的,每次输出结果都会不一样

最后我们还需要注意一点:不能直接去调用run方法,如果直接调用run方法就不认为是一条线程启动了,而是把Thread当做一个普通对象,此时run方法中的执行的代码会成为主线程的一部分。此时执行结果是这样的。

4.2 线程创建方式2

接下来我们学习线程的第二种创建方式。Java为开发者提供了一个Runnable接口,该接口中只有一个run方法,意思就是通过Runnable接口的实现类对象专门来表示线程要执行的任务。具体步骤如下

1.先写一个Runnable接口的实现类,重写run方法(这里面就是线程要执行的代码)
2.再创建一个Runnable实现类的对象
3.创建一个Thread对象,把Runnable实现类的对象传递给Thread
4.调用Thread对象的start()方法启动线程(启动后会自动执行Runnable里面的run方法)

代码如下:先准备一个Runnable接口的实现类

/*** 1、定义一个任务类,实现Runnable接口*/
public class MyRunnable implements Runnable{// 2、重写runnable的run方法@Overridepublic void run() {// 线程要执行的任务。for (int i = 1; i <= 5; i++) {System.out.println("子线程输出 ===》" + i);}}
}

再写一个测试类,在测试类中创建线程对象,并执行线程

public class ThreadTest2 {public static void main(String[] args) {// 3、创建任务对象。Runnable target = new MyRunnable();// 4、把任务对象交给一个线程对象处理。//  public Thread(Runnable target)new Thread(target).start();
​for (int i = 1; i <= 5; i++) {System.out.println("主线程main输出 ===》" + i);}}
}

运行上面代码,结果如下图所示(注意:没有出现下面交替执行的效果,也是正常的)

主线程main输出 ===》1
主线程main输出 ===》2
主线程main输出 ===》3
子线程输出 ===》1
子线程输出 ===》2
子线程输出 ===》3
子线程输出 ===》4
子线程输出 ===》5
主线程main输出 ===》4
主线程main输出 ===》5

4.3 线程创建方式2—匿名内部类

现在我不想写Runnable实现类,于是可以直接创建Runnable接口的匿名内部类对象,传递给Thread对象。

代码如下

public class ThreadTest2_2 {public static void main(String[] args) {// 1、直接创建Runnable接口的匿名内部类形式(任务对象)Runnable target = new Runnable() {@Overridepublic void run() {for (int i = 1; i <= 5; i++) {System.out.println("子线程1输出:" + i);}}};new Thread(target).start();
​// 简化形式1:new Thread(new Runnable() {@Overridepublic void run() {for (int i = 1; i <= 5; i++) {System.out.println("子线程2输出:" + i);}}}).start();
​// 简化形式2:new Thread(() -> {for (int i = 1; i <= 5; i++) {System.out.println("子线程3输出:" + i);}}).start();
​for (int i = 1; i <= 5; i++) {System.out.println("主线程main输出:" + i);}}
}

4.4 线程的创建方式3

  • 假设线程执行完毕之后有一些数据需要返回,前面两种方式重写的run方法均没有返回结果。

    public void run(){...线程执行的代码...
    }
  • JDK5提供了Callable接口和FutureTask类来创建线程,它最大的优点就是有返回值。

    在Callable接口中有一个call方法,重写call方法就是线程要执行的代码,它是有返回值的

    public T call(){...线程执行的代码...return 结果;
    }

第三种创建线程的方式,步骤如下

1.先定义一个Callable接口的实现类,重写call方法
2.创建Callable实现类的对象
3.创建FutureTask类的对象,将Callable对象传递给FutureTask
4.创建Thread对象,将Future对象传递给Thread
5.调用Thread的start()方法启动线程(启动后会自动执行call方法)等call()方法执行完之后,会自动将返回值结果封装到FutrueTask对象中6.调用FutrueTask对的get()方法获取返回结果

代码如下:先准备一个Callable接口的实现类

/*** 1、让子类继承Thread线程类。*/
public class MyThread extends Thread{// 2、必须重写Thread类的run方法@Overridepublic void run() {// 描述线程的执行任务。for (int i = 1; i <= 5; i++) {System.out.println("子线程MyThread输出:" + i);}}
}

再定义一个测试类,在测试类中创建线程并启动线程,还要获取返回结果

public class ThreadTest3 {public static void main(String[] args) throws Exception {// 3、创建一个Callable的对象Callable<String> call = new MyCallable(100);// 4、把Callable的对象封装成一个FutureTask对象(任务对象)// 未来任务对象的作用?// 1、是一个任务对象,实现了Runnable对象.// 2、可以在线程执行完毕之后,用未来任务对象调用get方法获取线程执行完毕后的结果。FutureTask<String> f1  = new FutureTask<>(call);// 5、把任务对象交给一个Thread对象new Thread(f1).start();
​
​Callable<String> call2 = new MyCallable(200);FutureTask<String> f2  = new FutureTask<>(call2);new Thread(f2).start();
​
​// 6、获取线程执行完毕后返回的结果。// 注意:如果执行到这儿,假如上面的线程还没有执行完毕// 这里的代码会暂停,等待上面线程执行完毕后才会获取结果。String rs = f1.get();System.out.println(rs);
​String rs2 = f2.get();System.out.println(rs2);}
}

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

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

相关文章

机器学习-02-机器学习算法分类以及在各行各业的应用

总结 本系列是机器学习课程的第02篇&#xff0c;主要介绍机器学习算法分类以及在各行各业的应用 本门课程的目标 完成一个特定行业的算法应用全过程&#xff1a; 定义问题&#xff08;Problem Definition&#xff09; -> 数据收集(Data Collection) -> 数据分割(Data…

自然语言处理: 第十三章Xinference部署

项目地址: Xorbitsai/inference 理论基础 正如同Xorbits Inference&#xff08;Xinference&#xff09;官网介绍是一个性能强大且功能全面的分布式推理框架。可用于大语言模型&#xff08;LLM&#xff09;&#xff0c;语音识别模型&#xff0c;多模态模型等各种模型的推理。通…

Spring中 Unsupported class file major version 61 报错

初学Spring时遇到的一个错误&#xff1a;Unsupported class file major version 61 &#xff0c;如图所示&#xff1a; 网上查了一下大概是JDK的版本与Spring的版本不一致导致的错误&#xff1b;刚开始我用的Spring版本是&#xff1a; <dependencies><dependency>…

StarRocks实战——多维分析场景与落地实践

目录 一、OLAP 系统历史背景 1.1 历史背景与痛点 1.2 组件诉求 二、StarRocks 的特点和优势 2.1 极致的查询性能 2.2 丰富的导入方式 2.3 StarRocks 的优势特点 三、多维分析的运用场景 3.1 实时计算场景 / 家长监控中心 3.2 实时更新模型选择 3.2.1 更新模型UNIQU…

考研数据结构算法机试训练1

中南大学上机压轴题 测试数据&#xff1a; 3 500 0.6 100 0.8 200 0.7 100 输出 390首先要对输入的折扣进行排序&#xff0c;优先使用比率低的z进行支付。 然后用lowcost记录目前多少钱是打过折的。T-lowcost就是剩余没打折的。 每次循环用上一个人的折扣额度。若所有人折扣额…

nodejs 实现pdf与图片互转

PDF转图片 效果图 代码 const path require(path); const pdf require(pdf-poppler); const fs require(fs); // PDF文件路径 const pdfFilePath ./path/test.pdf; // 转换选项 const opts { format: png, // 输出图片格式&#xff0c;可以是 jpeg, png, ppm…

AIGC(生成式人工智能)如何掀起数字化转型的巨浪?

数字化转型已成为当下企业发展的必经之路&#xff0c;而生成式AI作为这场变革的强力引擎&#xff0c;正逐渐展现出其无与伦比的价值。今天&#xff0c;我们将深入探讨生成式AI在日志整理、数据清晰、产品设计等方面的应用&#xff0c;揭示它如何为数字化转型注入强大动力&#…

数据结构-关键路径

介绍 在AOV网的基础上&#xff0c;如果用对应边来表示活动持续时间&#xff0c;这种有向图被称为AOE网在AOE网中&#xff0c;入度为0的为源点&#xff0c;出度为0的为汇点&#xff0c;整张网看做是一件事情完成的过程&#xff0c;那么这两个点就是事情的开始和结束。每个活动持…

WPF的DataGrid自动生成中文列头

直接将一个对象集合绑定到DataGrid上面&#xff0c;设置自动生成列AutoGenerateColumns"True"&#xff0c;DataGrid会自动根据对象类的属性生成对应的列 示例类对象&#xff1a; public class DataModel{public int Id { get; set; }public string Name { get; set;…

Rocky Linux 运维工具yum

一、yum的简介 ​​yum​是用于在基于RPM包管理系统的包管理工具。用户可以通过 ​yum​来搜索、安装、更新和删除软件包&#xff0c;自动处理依赖关系&#xff0c;方便快捷地管理系统上的软件。 二、yum的参数说明 1、install 用于在系统的上安装一个或多个软件包 2、seach 用…

麒麟银河操作系统V10部署ffmpeg

麒麟银河操作系统V10部署ffmpeg 部署ffmpeg用来处理视频的各种操作 想使用ffmpeg&#xff0c;要先安装nasm&#xff0c;yasm&#xff0c;x264之后&#xff0c;否则会报错 nkvers 查看麒麟操作系统版本 cat /proc/version #查看linux版本信息 uname -a #查看linux版本和内核…

在TMP中计算书名号《》高度的问题

1&#xff09;在TMP中计算书名号《》高度的问题 2&#xff09;FMOD设置中关于Virtual Channel Count&Real Channel Count的参数疑问 3&#xff09;Unity 2021.3.18f1 ParticleSystemTrailGeometryJob粒子拖尾系统崩溃 4&#xff09;XLua打包Lua文件粒度问题 这是第375篇UWA…

数据库管理-第156期 Oracle Vector DB AI-07(20240227)

数据库管理156期 2024-02-27 数据库管理-第156期 Oracle Vector DB & AI-07&#xff08;20240227&#xff09;1 Vector相关DDL操作可以在现有的表上新增vector数据类型的字段&#xff1a;可以删除包含vector数据类型的列&#xff1a;可以使用CTAS的方式&#xff0c;从其他有…

Unity Shader - sahder变体剔除

文章目录 吐槽优化方案 - 目前最靠谱的方式shadercsharp 吐槽 我之所以单独写这边文章&#xff0c;是因为之前写的一篇&#xff1a; Unity Shader - Built-in管线下优化变体&#xff0c;编辑后&#xff0c;无法保存&#xff0c;一直提示&#xff1a;操作超时。 等了差不多 3…

【C语言】linux内核netdev_start_xmit函数

一、中文注释 static inline netdev_tx_t netdev_start_xmit(struct sk_buff *skb, struct net_device *dev, struct netdev_queue *txq, bool more) {// 获取网络设备操作集合const struct net_device_ops *ops dev->netdev_ops;int rc;// 调用实际发送数据包的函数&…

ElasticSearch之找到乔丹的空中大灌篮电影

写在前面 本文看一个搜索的实际例子&#xff0c;找到篮球之神乔丹的电影Space Jam&#xff0c;即空中大灌篮。 正式开始之前先来看下要查询的目标文档&#xff0c;以及查询的text&#xff1a; 要查询的目标文档 {..."title": "Space Jam",..."ove…

什么是智能合约

前言&#xff1a;在介绍智能合约的前提下&#xff0c;需要先介绍一下区块链 一.什么是区块链 区块链实质上是一个去中心化、分布式的可进行交易的数据库或账本&#xff0c;具有下列典型特征&#xff1a; 去中心化&#xff1a;简单来说&#xff0c;在网络上一个或多个服务器瘫…

Spring Boo项目中方法参数对象中字段上存在的自定义注解如何进行拦截解析

一、前言 在Spring Boot项目开发过程中&#xff0c;我们经常会使用到自定义注解的方式进行业务逻辑开发&#xff0c;此时注解我们一般是放在方法或者类上面&#xff0c;通过AOP切面拦截的方式进行自定义业务逻辑填充。但是如果自定义注解放在类的字段上&#xff0c;此时应该如…

XXE 漏洞简单研究

近期在做个基础的 web 常见漏洞的 ppt&#xff0c;主要参考 OWASP TOP 10 2017RC2&#xff0c;此版本中增加了 XXE 攻击&#xff0c;所以自己简单的研究下 XXE 攻击。XXE&#xff08;XML External Entity&#xff09;XML 外部实体&#xff0c;当前端和后端通信数据采用 xml&…

element el-date-picker 日期组件置灰指定日期范围、禁止日期范围日期选择

JS如何将当前日期或指定日期转时间戳_javascript技巧_脚本之家 小于指定日期前的日期置灰 比如这里 指定日期是 2024-02-20 10:48:15 disabledDate(time) time是一个函数提供的时间用于比较 他是一个时间戳↓ 理解为我们想要置灰的时间 time.getTime() < timeStamps- 1 *…