【Spring Boot】034-Spring Boot 整合 JUnit

【Spring Boot】034-Spring Boot 整合 JUnit

文章目录

  • 【Spring Boot】034-Spring Boot 整合 JUnit
  • 一、单元测试
    • 1、什么是单元
    • 2、什么是单元测试
    • 3、为什么要单元测试
  • 二、JUnit
    • 1、概述
      • 简介
      • 特点
    • 2、JUnit4
      • 概述
      • 基本用法
    • 3、JUnit5
      • 概述
      • 组成
    • 4、JUnit5 与 JUnit4 的常用注解对比
  • 三、Spring Boot 整合 JUnit
    • 1、Spring Boot 项目创建
    • 2、引入依赖
    • 3、外部库
    • 4、编写测试类
    • 5、运行结果截图
    • 6、`@SpringBootTest` 本身支持依赖注入
      • 编写组件
      • 依赖注入
    • 7、手动指定主启动类
      • 概述
      • 子包下可正常运行
      • 包外提示异常
      • 结构截图
      • 解决方案:显式声明主启动类的位置
  • 四、JUnit的断言机制
    • 1、概述
    • 2、基本使用
    • 3、组合条件断言
    • 4、异常抛出断言
    • 5、执行超时断言
    • 6、强制失败
  • 五、前置条件检查机制
    • 1、概述
    • 2、代码演示
    • 3、运行结果截图
  • 六、嵌套测试
    • 1、概述
    • 2、代码演示
    • 3、运行结果截图
    • 4、注意点
  • 七、带入参的单元测试
    • 1、概述
    • 2、参数化测试
    • 3、基本类型
      • 概述
      • 代码演示
      • 测试结果截图
    • 4、方法数据流返回
      • 概述
      • 代码演示
      • 测试结果截图

一、单元测试

1、什么是单元

单元:最终能分解的尽可能小的、独立的、可执行的元素。

对于 Java 程序:单元 = 类的方法。

2、什么是单元测试

对程序中的一个个单元进行测试,看看是否能够正常使用、是否存在问题等。

3、为什么要单元测试

通过最小测试范围确定出一个功能单元是否正常可用,通过单元测试的编写和执行,可以在尽可能早期筛查、发现出一些问题。

二、JUnit

1、概述

简介

JUnit 是针对 Java 语言的一个经典单元测试框架,它在测试驱动方面具有重大意义。JUnit 促进了“先测试后编码”的理论,它强调测试数据与程序代码的配合关系,使得开发者在程序开发中形成“编码一点,测试一点”的过程,这种编码习惯可以提高程序的正确性和稳定性,进而提高开发者的产出效率,减少后期排查错误的时间和精力。

特点

  • 开放的资源框架,用于编写和运行测试;
  • 提供注释来识别测试方法;
  • 提供断言来测试预期结果;
  • 提供测试运行来运行测试;
  • 允许编写代码更快,并能提高质量;
  • 测试代码编写优雅简洁,花费时间较少;
  • 测试代码可以自动运行并且检查自身结果并提供即时反馈,没有必要人工梳理测试结果的报告;
  • 测试代码可以被组织为测试套件,包含测试用例,甚至其他的测试套件;

2、JUnit4

概述

早期使用的 JUnit 版本为 4.x ,这个版本对 jdk 的最低限制是 jdk 1.5 ,整个 JUnit 4 的代码被整合到一个 jar 包中,使用时直接导入即可,主流的 IDE 都有对 JUnit 的原生支持。

基本用法

编写一个类 + 声明一个无参无返回值方法 + 加上@Test注解

使用 JUnit 4 的方式比较简单,只需要编写一个类,并声明一个无入参、无返回值的方法,并标注 @Test 注解即可被 IDE 识别且运行。

public class DemoTest {
    
    @Test
    public void test() {
        System.out.println("DemoTest test run ......");
    }
}

3、JUnit5

概述

一个单独 jar 包 => 一组 jar 包组合而成 + 支持用户定制!

2017 年 9 月,JUnit 5.0.0 正式发布,它最低支持的 Java 版本是 Java 8 ,而且它的构建不再由一个独立的 jar 包构成,而是以一组 jar 包共同组合而成。抛弃历史包袱,通过支持扩展(Extension),JUnit 5 给用户提供了定制特殊的测试需求与方式。

组成

总的来说,JUnit 5 由 3 个模块构成,分别是 JUnit Platform 、JUnit Jupiter 、JUnit Vintage 。

  • JUnit Platform :基于 JVM 上启动测试框架的基础,不仅支持 JUnit 的测试引擎,也可以兼容其他的测试引擎;
  • JUnit Jupiter :JUnit 5 的核心,提供 JUnit 5 的新的编程模型,内部包含一个测试引擎,该测试引擎会基于 JUnit Platform 运行;
  • JUnit Vintage :兼容 JUnit 4 、JUnit 3 支持的测试引擎。

使用 JUnit 5 的方式跟 JUnit 4 并无太大区别,同样是编写测试类,并声明方法,标注 @Test 注解即可,不再编写示例代码解释。

4、JUnit5 与 JUnit4 的常用注解对比

JUnit 5 相较于 JUnit 4 比较大的改动是注解的使用。下表展示了 JUnit 5 跟 JUnit 4 常用注解的对比。

注解意义JUnit 5JUnit 4
标注一个测试方法(无区别)@Test@Test
在每个测试方法前执行@BeforeEach@Before
在每个测试方法后执行@AfterEach@After
在当前类中的所有测试方法之前执行@BeforeAll@BeforeClass
在当前类中的所有测试方法之后执行@AfterAll@AfterClass
禁用测试方法/类@Disabled@Ignore
标记和过滤@Tag@Category
声明测试工厂进行动态测试(新增)@TestFactory/
嵌套测试(新增)@Nested/
注册自定义扩展(新增)@ExtendWith/

三、Spring Boot 整合 JUnit

1、Spring Boot 项目创建

image-20231113134810578

2、引入依赖

项目创建完成后已经自动引入了!spring-boot-starter-test

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.17</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zibo</groupId>
    <artifactId>study-junit</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>study-junit</name>
    <description>study-junit</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- 创建项目后,自动引入了该依赖! -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <image>
                        <builder>paketobuildpacks/builder-jammy-base:latest</builder>
                    </image>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

3、外部库

image-20231113135348801

4、编写测试类

package com.zibo.studyjunit;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class StudyJunitApplicationTests {

    @Test
    void contextLoads() {
        System.out.println("Hello World!");
    }

}

5、运行结果截图

image-20231113135706434

6、@SpringBootTest 本身支持依赖注入

编写组件

package com.zibo.studyjunit.component;

import org.springframework.stereotype.Component;

@Component
public class HelloComponent {

    public String sayHello() {
        return "Hello World!";
    }

}

依赖注入

package com.zibo.studyjunit;

import com.zibo.studyjunit.component.HelloComponent;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class StudyJunitApplicationTests {

    @Autowired
    private HelloComponent helloComponent;

    @Test
    void contextLoads() {
        helloComponent.sayHello();
    }

}

7、手动指定主启动类

概述

我们编写 SpringBoot 测试类时,不可能把全部的测试类都放到与 SpringBoot 主启动类同包下,当测试类一多,整个 test 目录会非常混乱。为了方便寻找与管理,我们还是需要将单元测试类也分包管理。但是请各位注意,当 SpringBoot 测试类被放到其他包的时候,运行 SpringBoot 测试类是有区别的。

子包下可正常运行

package com.zibo.studyjunit.demo;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Demo1Test {

    @Test
    void test1() {
        System.out.println("test1");
    }

}

包外提示异常

package demo;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Demo2Test {

    @Test
    void test2() {
        System.out.println("test2");
    }

}

结构截图

image-20231113141817929

解决方案:显式声明主启动类的位置

代码

package demo;

import com.zibo.studyjunit.StudyJunitApplication;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest(classes = StudyJunitApplication.class)
class Demo2Test {

    @Test
    void test2() {
        System.out.println("test2");
    }

}

运行结果截图

image-20231113142023402

四、JUnit的断言机制

1、概述

下面讲解 JUnit 5 中的经典使用方式:断言。在 JUnit 4 中我们使用 Assert 类进行断言,而到了 JUnit 5 中使用的类是 Assertions ,类名变了,使用方式却大差不差,下面通过几个简单示例讲解 JUnit 5 的断言使用。

2、基本使用

Assertions 提供的最简单的断言方法,包含比对两个值是否相等两个对象是否是同一个对象是否为 null ,以及全场景通用的判断表达式的值为 true / false 。下面是一个简单的使用示例。

    @Test
    void testSimple() {
        // 一、两个值是否相等
        // 最简单的断言,断言计算值与预期值是否相等
        int num = 3 + 5;
        Assertions.assertEquals(num, 8);

        double result = 10.0 / 3;
        // 断言计算值是否在浮点数的指定范围内上下浮动
        Assertions.assertEquals(result, 3, 0.5);
        // 如果浮动空间不够,则会断言失败
        // 断言失败!
        // Assertions.assertEquals(result, 3, 0.2);
        // 传入message可以自定义错误提示信息
        // 断言失败!
        // Assertions.assertEquals(result, 3, 0.2, "计算数值偏差较大!");

        // 二、两个对象是否是同一个
        // 断言两个对象是否是同一个
        Object o1 = new Object();
        Object o2 = o1;
        Object o3 = new Object();
        Assertions.assertSame(o1, o2);
        // 断言失败!
        // Assertions.assertSame(o1, o3);

        // 断言两个数组的元素是否完全相同
        String[] arr1 = {"aa", "bb"};
        String[] arr2 = {"aa", "bb"};
        String[] arr3 = {"bb", "aa"};
        Assertions.assertArrayEquals(arr1, arr2);
        // 断言失败!
        // Assertions.assertArrayEquals(arr1, arr3);

        // 三、对象是否为 null
        // 断言对象是否为 null
        Object o4 = null;
        Object o5 = new Object();
        Assertions.assertNull(o4);
        // 断言失败!
        // Assertions.assertNull(o5);


        // 四、判断表达式的值为 true / false
        // 断言表达式的值为 true
        int a = 10;
        int b = 20;
        Assertions.assertTrue(a < b);

        // 断言表达式的值为 false
        Assertions.assertFalse(a > b);
    }

3、组合条件断言

组合条件断言,实际上是要在一条断言中组合多个断言,要求这些断言同时、全部通过,则外部的组合断言才能通过。这种设计有点类似于父子断言。

    @Test
    void testCombination() {
        // 组合条件断言,只有当所有断言都成功时,才会断言成功
        int a = 10;
        int b = 20;
        int c = 30;
        // 断言 a < b 并且 b < c
        Assertions.assertAll("组合断言",
            () -> Assertions.assertTrue(a < b),
            () -> Assertions.assertTrue(b < c)
        );
    }

4、异常抛出断言

异常抛出的断言,指的是被测试的内容最终运行时必定会抛出一个异常,如果没有抛出异常则断言失败

    @Test
    void testException() {
        // 断言抛出指定类型的异常
        Assertions.assertThrows(ArithmeticException.class, () -> {
            int i = 10 / 0;
        });
    }

5、执行超时断言

执行超时断言是,针对的是被测试代码的执行速度。

    @Test
    void testTimeout() {
        // 断言在指定时间内完成
        // 断言失败!org.opentest4j.AssertionFailedError: execution timed out after 100 ms
        Assertions.assertTimeoutPreemptively(java.time.Duration.ofMillis(100), () -> {
            Thread.sleep(200);
        });
    }

6、强制失败

类似于最原始的抛出异常的方式,(当满足某些条件时)直接断言失败!

    @Test
    void testFail() {
        if (java.time.ZonedDateTime.now().getHour() > 12) {
            Assertions.fail();
        }
    }

五、前置条件检查机制

1、概述

前置条件的检查机制,同样应用在断言的场景中,它指的是:如果一个单元测试的前置条件不满足,则当前的测试会被跳过,后续的测试不会执行。使用前置条件检查机制,可以避免一些无谓的测试逻辑执行,从而提高单元测试的执行效率。

前置条件的检查使用的 API 是 Assumptions

2、代码演示

    @Test
    void testAssumptions() {
        // 假设条件为 true 时,才会执行后面的断言
        int num = 3 + 5;
        Assumptions.assumeTrue(num < 10);

        System.out.println("断言成功!");

        // 假设条件为 false 时,不会执行后面的断言
        Assumptions.assumeTrue(num > 10);

        // 断言失败!下面的代码不会执行
        System.out.println("断言失败!");
    }

3、运行结果截图

image-20231113145356361

六、嵌套测试

1、概述

嵌套测试是 JUnit 5 的一个高级特性,它支持我们在编写单元测试类时,以内部类的方式组织一些有关联的测试逻辑。有关嵌套测试的演示代码,在 JUnit 5 的官方文档中提供了一个非常全面的示例。

2、代码演示

package com.zibo.studyjunit.demo;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.EmptyStackException;
import java.util.Stack;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class TestingAStackDemo {

    Stack<Object> stack;

    // 测试用例:使用new关键字实例化堆栈
    @Test
    void isInstantiatedWithNew() {
        new Stack<>();
    }

    @Nested
    class WhenNew {

        @BeforeEach
        void createNewStack() {
            // 在每个测试方法之前创建一个新的堆栈实例
            stack = new Stack<>();
        }

        // 测试用例:堆栈在刚创建时是否为空
        @Test
        @DisplayName("is empty")
        void isEmpty() {
            assertTrue(stack.isEmpty());
        }

        // 测试用例:在空栈上执行pop操作是否抛出EmptyStackException异常
        @Test
        @DisplayName("throws EmptyStackException when popped")
        void throwsExceptionWhenPopped() {
            assertThrows(EmptyStackException.class, () -> stack.pop());
        }

        @Nested
        @DisplayName("after pushing an element")
        class AfterPushing {

            String anElement = "an element";

            @BeforeEach
            void pushAnElement() {
                // 在堆栈中推入一个元素
                stack.push(anElement);
            }

            // 测试用例:在推入元素后,堆栈是否不再为空
            @Test
            @DisplayName("it is no longer empty")
            void isNotEmpty() {
                assertFalse(stack.isEmpty());
            }

            // 测试用例:在推入元素后,执行pop操作是否返回推入的元素并使堆栈为空
            @Test
            @DisplayName("returns the element when popped and is empty")
            void returnElementWhenPopped() {
                assertEquals(anElement, stack.pop());
                assertTrue(stack.isEmpty());
            }
        }
    }

}

3、运行结果截图

image-20231113150426000

4、注意点

官方提供的测试代码都是可以执行通过的,从这段测试代码中需要各位了解的几个关键特性:

  • 单元测试类可以通过编写内部类,并标注 @Nested 注解,表明内部类也是一个单元测试类
  • 内部的单元测试类可以直接使用外部的成员属性,且可以利用外部定义的 @BeforeEach@BeforeAll@AfterEach@AfterAll 等前后置逻辑注解标注的方法;
  • 外部的单元测试无法利用内部类定义的前后置逻辑注解。

七、带入参的单元测试

1、概述

JUnit 5 中的一个重要特性是支持单元测试方法的参数依赖注入,这也打破了我们已有的认知。通常我们编写的测试方法是不能有方法入参的,但是 JUnit 5 允许我们在编写单元测试方法中予以声明方法入参。默认情况下 JUnit 5 支持以下几个参数类型的依赖注入:

  • TestInfo :内部组装了当前单元测试所属的 Class 、Method ,以及对应的展示名(DisplayName)等;
  • RepetitionInfo :如果一个方法被标注了 @RepeatedTest ,或者该方法是一个 @BeforeEach / @AfterEach 方法,则可以拿到 RepetitionInfo 的信息,可以通过 RepetitionInfo 获取到当前重复信息以及相应的@RepeatedTest的重复总数;
  • TestReporter :注入 TestReporter 后可以获得数据发布能力,可以向测试结果中注册一些特殊的数据,这些数据可以被 TestExecutionListener 获取到。

2、参数化测试

参数化测试是 JUnit 5 中提高单元测试效率的重要手段,它通过给单元测试方法传入特定的参数,可以使得 JUnit 在执行单元测试时逐个参数来检验和测试,这样做的好处是更加规整和高效地执行单元测试

参数化测试支持我们使用如下的方式赋予参数:

  • 基本类型:8 种基本数据类型 + String + Class
  • 枚举类型:自定义的枚举;
  • CSV 文件:可传入一个 CSV 格式的表格文件,使用表格文件中的数据作为入参;
  • 方法的数据返回:可以通过一个方法返回需要测试入参的数据(流的形式返回)。

3、基本类型

概述

在使用参数化测试时,标注的注解不再是 @Test ,取而代之的是 @ParameterizedTest ;另外还需要声明需要传入的数据,对于简单的基本类型而言,使用 @ValueSource 注解即可指定。

代码演示

package com.zibo.studyjunit.demo;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class ParameterizedTestDemo {

    @ParameterizedTest
    @ValueSource(strings = {"aa", "bb", "cc"})
    void testSimpleParameterized(String value) {
        System.out.println(value);
        Assertions.assertTrue(value.length() < 3);
    }
    
}

测试结果截图

image-20231113151330211

4、方法数据流返回

概述

参数化测试最吸引人的点是可以引用一个方法来实现测试数据的参数化,既然可以在一个方法中构造单元测试的入参数据,那么完全可以从数据库 / 缓存等任意位置加载数据,并构造为流的形式返回。以此法编写的参数化测试具有极大的灵活度和自由度。

代码演示

    @ParameterizedTest
    @MethodSource("dataProvider")
    // @MethodSource("getInteger")
    void testDataStreamParameterized(Integer value) {
        System.out.println(value);
        Assertions.assertTrue(value < 10);
    }

    private static Stream<Integer> dataProvider() {
        return Stream.of(1, 2, 3, 4, 5);
    }

    // 不能用这种方式,会报错
    // 返回值必须是Stream<T>或者Stream<Arguments>
    // private static Integer getInteger() {
    //     return 1;
    // }
    private static Stream<Arguments> getInteger() {
        return Stream.of(Arguments.of(1), Arguments.of(2), Arguments.of(3));
    }

测试结果截图

image-20231113152855091

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL学习(CTFhub)整数型注入,字符型注入,报错注入 -----手工注入+ sqlmap注入

目录 整数型注入 手工注入 为什么要将1设置为-1呢&#xff1f; sqlmap注入 sqlmap注入步骤&#xff1a; 字符型注入 手工注入 sqlmap注入 报错注入 手工注入 sqlmap注入 整数型注入 手工注入 先输入1 接着尝试2&#xff0c;3&#xff0c;2有回显&#xff0c;而3没有回显…

No199.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

11. 深度学习——强化学习

机器学习面试题汇总与解析——强化学习 本章讲解知识点 什么是强化学习 围棋举例 强化学习的两个特点和一个核心 最简单的强化学习算法 一个完整的强化学习问题 进一步深入强化学习的核心 本专栏适合于Python已经入门的学生或人士&#xff0c;有一定的编程基础。本专栏适…

Eclipse打包Springboot项目

首先&#xff0c;在pom.xml文件中添加配置&#xff0c;修改mainClass主函数&#xff1a; <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configurat…

二十、泛型(6)

本章概要 问题 任何基本类型都不能作为类型参数实现参数化接口转型和警告重载基类劫持接口 自限定的类型 古怪的循环泛型自限定参数协变 问题 本节将阐述在使用 Java 泛型时会出现的各类问题。 任何基本类型都不能作为类型参数 正如本章早先提到的&#xff0c;Java 泛型的…

qnx log 系统

前言 本文主要介绍QNX 系统中的 log 打印相关接口和使用方法 软件环境:qnx7.1 一、QNX查看 log 的工具 slog2info 1. slog2info 的相关介绍 和linux 中查看 kernel log 信息的 dmesg 命令一样, qnx 里面也有一个查看 log 信息的命令,那就是 slog2info 命令, 如下图所示是…

【LabVIEW学习】1.对labview的初步使用,控制数据流动

一。初步使用labview 1.程序图标 2.打开之后继续点击新建VI 原因&#xff1a;最后的程序后缀就是 .vi 3.新建之后&#xff0c;会有三个界面&#xff08;没有不要紧&#xff0c;找找肯定有&#xff09; 4.程序操作方法 1.拖动控件到前面板 2.此时程序框图会出现对应的控件 拖动…

基于卷积神经网络和客源注意力机制的OD客流预测模型

文章信息 论文题目为《An origin–destination passenger flow prediction system based on convolutional neural network and passenger source-based attention mechanism》&#xff0c;该文于2023年发表于Expert Systems With Applications期刊上。文章提出一种基于乘客源注…

Java面向对象(进阶)-- Object类的详细概述

文章目录 一、如何理解根父类二、 Object类的方法&#xff08;1&#xff09;引子&#xff08;2&#xff09;Object类的说明 三、了解的方法&#xff08;1&#xff09;clone( )1、介绍2、举例 &#xff08;2&#xff09;finalize( )1、介绍2、举例 &#xff08;3&#xff09;get…

EasyPOI实现excel文件导出

EasyPOI真的是一款非常好用的文件导出工具&#xff0c;相较于传统的一行一列的数据导出&#xff0c;这种以实体类绑定生成的方式真的非常方便&#xff0c;也希望大家能够了解、掌握其使用方法&#xff0c;下面就用一个实例来简单介绍一下EasyPOI的使用。 1.导入依赖 <!-- e…

使用Python的requests库模拟爬取地图商铺信息

目录 引言 一、了解目标网站 二、安装requests库 三、发送GET请求 四、解析响应内容 五、处理异常和数据清洗 六、数据存储和分析 七、数据分析和可视化 八、注意事项和最佳实践 总结 引言 随着互联网的快速发展&#xff0c;网络爬虫技术已经成为获取数据的重要手段…

CSS特效009:音频波纹加载律动

总第 009 篇文章&#xff0c; 查看专栏目录 本专栏记录的是经常使用的CSS示例与技巧&#xff0c;主要包含CSS布局&#xff0c;CSS特效&#xff0c;CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点&#xff0c;CSS特效主要是一些动画示例&#xff0c;CSS花…

Linux环境实现mysql所在服务器定时同步数据文件到备份服务器(异地容灾备份场景)

目录 概述 1、建立ssh连接 1.1、操作mysql所在服务器 1.2、操作备份文件服务器 2、创建脚本实现备份以及传输 3、配置定时任务 概述 应对异地容灾备份场景&#xff0c;mysql所在服务器和本分服务器需要建立ssh连接&#xff0c;每天mysql服务器通过定时任务执行脚本&…

OpenAI调查ChatGPT故障;向量搜索的优势与局限

&#x1f989; AI新闻 &#x1f680; OpenAI调查ChatGPT故障&#xff0c;发布新AI产品GPTs和GPT-4 Turbo 摘要&#xff1a;OpenAI的ChatGPT和其他服务出现故障&#xff0c;经过调查后发现是由于DDoS攻击导致的异常流量模式。OpenAI在首届开发者大会上发布了新的AI产品GPTs&am…

MATLAB | 官方举办的动图绘制大赛 | 第一周赛情回顾

嘿真的又是很久没见了&#xff0c;最近确实有点非常很特别小忙&#xff0c;今天带来一下MATHWORKS官方举办的迷你黑客大赛第三期(MATLAB Flipbook Mini Hack)的最新进展&#xff01;&#xff01;目前比赛已经刚好进行了一周&#xff0c;前两届都要求提交280个字符内的代码来生成…

老胡的周刊(第115期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 draw-a-ui[2] 利用 tldraw gpt-4-vision ap…

Linux技能篇-软链接和硬链接

文章目录 前言一、硬链接是什么&#xff1f;二、软链接是什么&#xff1f;三、硬链接和软链接的区别和共性1.区别2.共同点 总结 前言 在Linux系统中&#xff0c;有两个容易混淆的概念&#xff0c;就是软链接&#xff08;Soft Link&#xff09;和硬链接&#xff08;Hard Link&a…

时序数据库 TDengine + 高级分析软件 Seeq,助力企业挖掘时序数据潜力

作为一款制造业和工业互联网&#xff08;IIOT&#xff09;高级分析软件&#xff0c;Seeq 支持在工艺制造组织中使用机器学习创新的新功能。这些功能使组织能够将自己或第三方机器学习算法部署到前线流程工程师和主题专家使用的高级分析应用程序&#xff0c;从而使单个数据科学家…

EasyDarwin开源流媒体服务器

文章目录 前言一、EasyDarwin 简介二、EasyDarwin 主要功能特点三、安装部署四、推拉流测试1、进入控制页面2、推流测试3、拉流测试 前言 本文介绍一个十分实用的高性能开源 RTSP 流媒体服务器&#xff1a;EasyDarwin。 一、EasyDarwin 简介 EasyDarwin 是基于 go 语言研发&a…

【广州华锐视点】海外制片人VR虚拟情景教学带来全新的学习体验

虚拟现实&#xff08;Virtual Reality&#xff0c;简称VR&#xff09;是一种利用电脑模拟产生一个三维的虚拟世界&#xff0c;提供用户关于视觉、听觉、触觉等感官的模拟体验的技术。随着科技的进步&#xff0c;VR已经被广泛应用到许多领域&#xff0c;包括游戏、教育、医疗、房…