27、springboot自定义第三方框架和Starter组件及其测试完整版

news2025/1/15 23:35:36

介绍

★ 自定义自动配置=自动配置类+注册

所谓的自动配置,就是通过一个配置类,然后这个配置类在我们容器中定义了大量的bean,然后这些bean也不是直接定义,它是结合了条件注解,只有在某些特定的条件下,才会生效,这样我们的自动配置就可以根据我们的环境的配置(如yml配置文件),根据我们这个应用程序所使用的环境来决定这些bean的配置是否要生效。

自定义自动配置分为2步:

(1)使用@Configuration和条件注解定义自动配置类。

使用条件注解和@Bean注解在容器中定义整合框架所需要的组件(Bean)。

比如程序要整合MyCustomFrame框架,MyCustomFrame框架所需要核心组件就是WriterTemplate,

因此该自动配置就是负责在容器中自动配置WriterTemplate

(2)在META-INF/spring.factories中注册自动配置类。

   使用如下META-INF/spring.factories文件来注册自动配置类:
      org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
          cn.ljh.mycustomstarter.FrameAutoConfiguration

开发完自己的自动配置及Starter后,并不需要运行该项目,而是应该将Starter安装到本地资源库、甚至公司的中央资源库。

在Spring的Java配置类中,方法名默认将作为bean的id,因此不要让两个方法的方法名相同,这样会造成ID冲突。

★ 自定义Starter组件

官方推荐,一个完整的Spring Boot starter应该包含以下两个组件:

- auto-configure模块,包含自动配置类和META-INF\spring-factories文件。推荐名:xxx-spring-boot-autoconfigure

- Starter模块:负责管理自动配置模块及其他第三方的依赖,简而言之,添加本Starter就能开始使用该自动配置。
  
  推荐名:xxx-spring-boot-starter

  Spring Boot官方Starter名叫: spring-boot-stater-xxx

Starter并不包含任何class文件,它只负责管理依赖。
Starter JAR包下只包含xxx-starter.pom文件,该文件指定该Starter负责管理的自动依赖模块和第三方依赖。

【注意】:使用Maven开发Spring Boot的Starter组件时,不要添加spring Boot的Maven插件
——否则该Maven插件总以为你是一个Spring Boot项目,它总会尝试帮你找程序的主类。

代码演示:

需求分析总结:

创建一个自定义的第三方框架 MyCustomFrame , 创建一个自定义的 Starter 组件 MyCustomStarter,创建一个普通项目 CustomFrameTest 来添加 自定义的 starter 组件,进行测试。

测试:根据普通项目的配置,决定信息输出到数据库还是文件。

关系:
第三方框架 MyCustomFrame 作用:提供一个 WriterTemplate 工具类,用来实现一个功能。
功能:如果我们引入这个第三方框架的项目有连接数据库,那么就把要输出的信息输出到数据库,如果没有连接数据库,那么就把要输出的信息输出到指定的文件

自定义 Starter 组件的作用:核心就是提供一个 FrameAutoConfiguration 配置类,用来整合第三方框架 MyCustomStarter 时,需要的一些配置。
简单来说,这个 FrameAutoConfiguration 配置类 提供两个 Bean,根据我们的普通项目CustomFrameTest 是否有连接数据库,进行分析,有连接就返回输出到数据库的Bean,没有连接就返回输出到文件的bean。

文字大概这么描述,具体还得看截图一并分析。

代码截图分析:

开发第三方框架:MyCustomFrame

1、第一步:先创建一个maven项目,作为第三方框架,项目名叫:MyCustomFrame,
这个项目里面只有一个核心的类,WriterTemplate,作用是引入这个第三方框架的项目是否有连接数据库,有就把要输出的信息输出到数据库,如果没有连接数据库,那么就把要输出的信息输出到指定的文件 的功能。
然后把这个框架部署到本地资源库,双击 Ctrl 键,用 mvn install 操作把框架打包并且安装到我们的本地资源库

具体代码看文章最后:
在这里插入图片描述
代码:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

然后把这个第三方框架 通过 双击 Ctrl 键,输入 mvn install 命令 , 把这个框架打包成jar包,安装到本地的 maven 库里面。
可以理解成我们在项目中添加依赖一样。添加的依赖就会保存在 maven 仓库里面。

这样一个简单的第三方框架就可以了
在这里插入图片描述

开发 starter 组件:mycustomstarter

2、第二步:演示如何使用 spring 通过 自动配置来开发一个自动的 starter 组件,让我们的项目可以很简单的通过starter 来整合我这个自定义的第三方框架(MyCustomFrame)

现在开发starter组件
这个starter组件主要就是这两个类:属性处理类和配置类,还有一个注册配置类的文件。
在这里插入图片描述

详细:
FrameProperties 属性处理类:
在starter组件添加这个属性处理类,后面这个starter组件被引入到项目后,就可以获取到该项目指定前缀的一些配置文件的属性
在这里插入图片描述

FrameAutoConfiguration 配置类:
在这里插入图片描述
在这里插入图片描述

spring.factories 用来注册自动配置类FrameAutoConfiguration :
在这里插入图片描述

pom.xml 文件
在这里插入图片描述

到这里 starter组件就开发完成,现在就需要把这个组件也打包成jar包,安装到 maven 仓库里面。
开发完自己的自动配置(MyCustomFrame)及Starter(MyCustomStarter)后,并不需要运行该项目,而是应该将Starter安装到本地资源库、甚至公司的中央资源库。

双击 Ctrl 键,然后输入 mvn install 命令就可以了,就会自动保存到本地的maven仓库

如果修改了这个starter组件,要重新打包的话,我选择先删除target包,再重新编译下,再打包成jar包。
在这里插入图片描述

【注意】:使用Maven开发Spring Boot的Starter组件时,不要添加spring Boot的Maven插件
——否则该Maven插件总以为你是一个Spring Boot项目,它总会尝试帮你找程序的主类。

starter 组件不需要 这个 maven 插件,把这个删除掉,不然打包失败
在这里插入图片描述

针对自定义starter组件中一些代码的理解:

@Bean 表明在spring 容器中配置这个bean

1、@EnableConfigurationProperties
这里创建了属性处理类,这个类需要用 @EnableConfigurationProperties(value = FrameProperties.class) 这个注解来启用它,不然就会爆红,如图:
在这里插入图片描述
还需要配合这个注解,用来解析配置文件的属性
在这里插入图片描述

2、@ConditionalOnClass(WriterTemplate.class)
这是一个条件注解,被这个注解修饰的这个 FrameAutoConfiguration 配置类,如果要生效,项目中就必须有WriterTemplate这个类存在,不然就不生效。
因为这个WriterTemplate类是存在第三方框架MyCustomFrame里面的,所以需要引入第三方框架的依赖
在这里插入图片描述
3、@AutoConfigureAfter(DataSourceAutoConfiguration.class)
因为这个配置类添加的writerTemplate1这个bean需要Datasource作为参数,但是在加载的时候,可能加载 writerTemplate1 这个bean的时机 比加载 DataSourceAutoConfiguration这个类要快,所以需要添加这个条件注解@AutoConfigureAfter。
作用就是FrameAutoConfiguration这个配置类要在DataSourceAutoConfiguration类加载存在后才能加载。

@ConditionalOnMissingBean:
只有当项目中 没有 WriterTemplate 这个bean时,才自动为项目配置这个Bean,因为如果项目中有开发人员自己自定义开发 WriterTemplate 这个bean,那我们肯定不需要再额外自动配置 WriterTemplate 这个bean

@ConditionalOnSingleCandidate:
另外,Bean上面的这个@ConditionalOnSingleCandidate(DataSource.class)注解,表示只有当spring容器中有且仅有一个 DataSource Bean 的时候,下面这个bean配置方法才生效。
原因:因为下面这个配置必须给它依赖注入唯一的 DataSource ,有多个DataSource 就不行。
在这里插入图片描述

4、两个bean的执行顺序。
WriterTemplate1 这个bean是把数据输出数据库表中去
WriterTemplate2 这个bean是把数据输出到指定文件中去
在这里插入图片描述

5、WriterTemplate1 这个bean是把数据输出数据库表中去
这个starter组件中的处理类中的配置的WriterTemplate1 这个bean,传入的 DataSource ,应该是 引入这个starter组件的 CustomFrameTest 项目中的yml配置文件中配置的数据库连接。
因为这个数据库连接在项目中只有这一个,应该就算是唯一的。
这个bean的dataSource有且仅有一个,还理解的不够透彻,先把想法记下来。
在这里插入图片描述

6、WriterTemplate2 这个bean 的数据的获取,这个bean获取到引入这个starter组件的项目的yml配置文件中的要输出到指定文件中的dest和charset属性。
在这里插入图片描述

CustomFrameTest:普通测试项目

3、第3步:
创建一个项目,来使用这个 starter 组件,进行测试。
在这里插入图片描述

在启动类中通过类型获取 WriterTemplate 这个bean ,然后调用 write 方法,把要输出的信息作为参数传递过去,然后是输出到数据库还是输出到文件,
就是通过 starter组件+MyCustomFrame框架里面的逻辑来实现了。

在这里插入图片描述

从pom文件中可以看出,这个项目引入了starter组件,然后这个starter里面又包含了自定义的第三方框架MyCustomFrame
在这里插入图片描述

可以看出这个项目只有启动类和yml配置类,没有写任何逻辑代码,测试是输出到文件还是数据库的代码,都是通过引入 starter 组件来实现的。而starter组件是不需要运行的,是安装在maven库的。

测试:

输出到文件:

这个项目没有连接到数据库,所以是把信息输出到指定文件中去
在这里插入图片描述

在这里插入图片描述

输出到数据库:

如果要输出到数据库,那么就要有数据库的连接。需要创建对应的 customframe 数据库,然后再pom.xml 文件中添加数据库的连接的依赖。
在这里插入图片描述

可以看出因为添加了连接数据库的 jdbc 依赖,所以就是走输出信息到数据库逻辑去了。

在这里插入图片描述

打印的文字出自第三方框架这个类
在这里插入图片描述

======================================

详细代码:

MyCustomFrame框架

自定义第三方框架MyCustomFrame 里面的 WriterTemplate 工具类代码

package cn.ljh.myCustomFrame;

import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Objects;

/*
 * 这个类的作用:
 * 如果我们这个项目有连到数据库,那就把我们要输出的信息输出到数据库,
 * 如果没有连数据库,那么就把信息输出到文件
 *
 * 是一个工具类
 */

@Slf4j
public class WriterTemplate
{
    private final DataSource dataSource;
    private Connection conn;
    private final File dest;
    private final Charset charset;
    private RandomAccessFile raf;

    public WriterTemplate(DataSource dataSource) throws SQLException
    {
        this.dataSource = dataSource;
        this.dest = null;
        this.charset = null;
        if (Objects.nonNull(this.dataSource))
        {
            log.debug("==========获取数据库连接==========");
            this.conn = dataSource.getConnection();
        }
    }
    public WriterTemplate(File dest, Charset charset) throws FileNotFoundException
    {
        this.dest = dest;
        this.charset = charset;
        this.dataSource = null;
        this.raf = new RandomAccessFile(this.dest, "rw");
    }

    public void write(String message) throws IOException, SQLException
    {
        if (Objects.nonNull(this.conn))
        {
            // 查询当前数据库的customFrame_message表是否存在
            ResultSet rs = conn.getMetaData().getTables(conn.getCatalog(), null,
                    "customFrame_message", null);
            //  如果customFrame_message表不存在
            if (!rs.next())
            {
                log.debug("~~~~~~创建customFrame_message表~~~~~~");
                conn.createStatement().execute("create table customFrame_message " +
                        "(id int primary key auto_increment, message_text text)");
                rs.close();
            }
            log.debug("~~~~~~输出到数据表~~~~~~");
            // 插入要输出的字符串
            conn.createStatement().executeUpdate("insert into " +
                    "customFrame_message values (null, '" + message + "')");
        }
        else
        {
            log.debug("~~~~~~输出到文件~~~~~~");
            // 输出到文件
            raf.seek(this.dest.length());
            raf.write((message + "\n").getBytes(this.charset));
        }
    }
    // 关闭资源
    public void close() throws SQLException, IOException
    {
        if (this.conn != null)
        {
            this.conn.close();
        }
        if (this.raf != null)
        {
            this.raf.close();
        }
    }
}

自定义第三方框架MyCustomFrame 里面的 pom.xml 文件

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>cn.ljh.customframe</groupId>
<artifactId>MyCustomFrame</artifactId>
<version>1.0.0</version>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>8</source>
                <target>8</target>
            </configuration>
        </plugin>
    </plugins>
</build>
<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.20</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.6</version>
    </dependency>
</dependencies>

mycustomstarter 组件

mycustomstarter 组件的 FrameAutoConfiguration 配置类代码

package cn.ljh.mycustomstarter;


import cn.ljh.myCustomFrame.WriterTemplate;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


import javax.sql.DataSource;
import java.io.File;
import java.io.FileNotFoundException;
import java.nio.charset.Charset;
import java.sql.SQLException;


//这个配置类的作用就是用来整合第三方框架MyCustomFrame时,所需要的一些配置
// 用 @Configuration 修饰的类就是配置类
@Configuration
//启用这个 FrameProperties 属性处理类,不然属性处理类的@ConfigurationProperties注解会爆红
@EnableConfigurationProperties(value = FrameProperties.class)
//WriterTemplate类 代表了要整合的框架(WriterTemplate)的核心API,
//这个配置类要想生效,需要有这个WriterTemplate类存在
//这个WriterTemplate类是存在第三方框架MyCustomFrame里面的,所以需要引入第三方框架的依赖
//因为有了WriterTemplate这个类,所以 这个 FrameAutoConfiguration 配置类就能生效了,这就是这个类的生效过程
@ConditionalOnClass(WriterTemplate.class)
//指定这个自动配置类需要位于DataSourceAutoConfiguration之后生效
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class FrameAutoConfiguration {


    /*
     * 使用 条件注解 和 @Bean 注解在容器中定义整合第三方框架(WriterTemplate)所需要的组件
     * 项目要整合第三方框架(MyCustomFrame),MyCustomFrame框架所需要的核心组件就是 WriterTemplate
     * 因此这个自动配置类就是负责在容器中自动配置 WriterTemplate
     */

    //FrameProperties 属性处理类,该属性处理类负责读取整合 MyCustomFrame 框架相关的配置信息
    private final FrameProperties frameProperties;
    //构造器
    public FrameAutoConfiguration(FrameProperties frameProperties) {
        this.frameProperties = frameProperties;
    }

    //配置Bean
    //此处需要传入 DataSource 来构建这个 writerTemplate,因此这个自动配置类需要在 DataSource 创建出来之后运行,
    //因此应该让这个自动配置类位于 DataSourceAutoConfiguration 之后生效

    //这个bean是如果引入starter组件的项目有连接数据库的配置,那么就会返回这个bean
    @Bean
    //只有当项目中 没有 WriterTemplate 这个bean时,才自动为项目配置这个Bean,
    //因为如果项目中有开发人员自己自定义开发 WriterTemplate 这个bean,那我们肯定不需要再额外自动配置 WriterTemplate 这个bean
    @ConditionalOnMissingBean
    //只有当spring容器中有且仅有一个 DataSource Bean 的时候,下面这个配置才生效
    @ConditionalOnSingleCandidate(DataSource.class)
    public WriterTemplate writerTemplate1(DataSource dataSource) throws SQLException {

        return new WriterTemplate(dataSource);
    }

    //这个bean是如果引入starter组件的项目没有连接数据库的配置,那么就会返回这个bean
    //这个bean主要是获取到引入该starter组件的项目里面的配置文件里面的dest属性和charset属性
    //具体是如何输出到数据库或是文件的逻辑,是在第三方框架的WriterTemplate类实现的
    @Bean
    @ConditionalOnMissingBean
    public WriterTemplate writerTemplate2() throws FileNotFoundException {
        //创建文件
        File file = new File(frameProperties.getDest());
        //指定字符
        Charset charset = Charset.forName(frameProperties.getCharset());

        return new WriterTemplate(file, charset);
    }
}

mycustomstarter 组件的 FrameProperties 属性处理类代码

package cn.ljh.mycustomstarter;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

//@ConfigurationProperties 这个注解修饰的类就是属性处理类
//指定该属性处理类只读取配置文件中,以 cn.ljh.frame 开头的配置属性
@ConfigurationProperties(prefix = FrameProperties.FRAME_PREFIX)
@Data
public class FrameProperties {

    public static final String FRAME_PREFIX = "cn.ljh.frame";

    //定义一些常用信息
    private String dest;
    private String charset;

}

mycustomstarter 组件的 spring.factories 配置文件

# 注册自动配置类 FrameAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  cn.ljh.mycustomstarter.FrameAutoConfiguration

mycustomstarter 组件的 pom.xml 文件

<?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.4.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <!--  这个名称是符合springboot官方定义starter名的规格  -->
    <groupId>cn.ljh.mycustomstarter</groupId>
    <artifactId>mycustomframe-spring-boot-starter</artifactId>
    <version>1.0.0</version>

    <name>mycustomstarter</name>

    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>
        <!--
            因为 mycustomstarter 这个 starter 组件有添加这个 第三方框架MyCustomFrame 的依赖,
            因此在以后的开发中,只需要在项目中添加这个 mycustomstarter 组件 ,
            这个starter组件就会帮我们添加被整合的框架 ->第三方框架 MyCustomFrame
            -->
        <dependency>
            <groupId>cn.ljh.customframe</groupId>
            <artifactId>MyCustomFrame</artifactId>
            <version>1.0.0</version>
        </dependency>

        <!--  属性处理类需要的依赖,用来解析配置文件的属性  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

CustomFrameTest

CustomFrameTest 项目里面的pom.xml依赖

<?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 http://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.4.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>cn.ljh</groupId>
    <artifactId>CustomFrameTest</artifactId>
    <version>1.0.0</version>

    <properties>
        <java.version>8</java.version>
    </properties>
    <dependencies>

        <!--   添加mysql的驱动     -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--  添加自定义的starter组件  -->
        <dependency>
            <groupId>cn.ljh.mycustomstarter</groupId>
            <artifactId>mycustomframe-spring-boot-starter</artifactId>
            <version>1.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </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>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

在这里插入图片描述

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

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

相关文章

PHP实现每日蛋白质摄入量计算器

1.laravel 路由 //每日蛋白质摄入计算器Route::get(api/protein/intake, FormulaControllerproteinIntakeCal); 2.代码 /*** 每日蛋白质摄入计算器*/public function proteinIntakeCal(){$number intval($this->request(number));$goalFactor array(0.8, 1.16, 0.8, 1.16,…

[线程/C++]线程同(异)步和原子变量

文章目录 1.线程的使用1.1 函数构造1.2 公共成员函数1.2.1 get_id()1.2.2 join()2.2.3 detach()2.2.5 joinable()2.2.6 operator 1.3 静态函数1.4 call_once 2. this_thread 命名空间2.1 get_id()2.2 sleep_for()2.3 sleep_until()2.4 yield() 3. 线程同步之互斥锁3.1 std:mute…

微分流形学习之一:基本定义

微分流形学习之一&#xff1a;基本定义引入 引言一、微分流形的历史简介二、拓扑空间三、微分流形 引言 本文是作者在学习微分流形的时候的笔记&#xff0c;尽量严格完整&#xff0c;并带有一定理解&#xff0c;绝不是结论的简单罗列。如果读者知道数学分析中的 ϵ − δ \ep…

【Python】PyCharm配置外部工具

QT Designer配置 Designer绘制的UI文件转换成Python文件 1&#xff0c;File->Settings->Tools->External Tools 2,QT Designer配置 Program:...\Python\Python3.10.2\Lib\site-packages\PySide2\designer.exe Arguments:空 Working directory&#xff1a;$Projec…

小程序中display:flex和v-show,v-show不生效,uni-app

小程序中display:flex和v-show&#xff0c;v-show不生效、、 解决方案&#xff1a; display&#xff1a;flex样式的优先级高于了v-show &#xff0c;v-show其实就是display&#xff1a;none&#xff0c;display&#xff1a;flex优先级高于display&#xff1a;none。 使用 :s…

铜卡计混合法比热测试仪绝热量热计的高精度主动控制解决方案

摘要&#xff1a;在下落法比热容测试中绝热量热计的漏热是最主要误差源&#xff0c;为实现绝热量热计的低漏热要求&#xff0c;本文介绍了主动护热式等温绝热技术以及相应的解决方案。方案的核心一是采用循环水冷却金属圆筒给量热计和护热装置提供低温环境或恒定冷源&#xff0…

SpringBoot3集成Kafka

标签&#xff1a;Kafka3.Kafka-eagle3&#xff1b; 一、简介 Kafka是一个开源的分布式事件流平台&#xff0c;常被用于高性能数据管道、流分析、数据集成和关键任务应用&#xff0c;基于Zookeeper协调的处理平台&#xff0c;也是一种消息系统&#xff0c;具有更好的吞吐量、内…

0基础入门C++之类和对象上篇

目录 1.面向过程和面向对象初步认识2.类的引入3.类的定义3.1类的两种定义方式:3.2成员变量命名规则的建议 4.类的访问限定符及封装4.1访问限定符4.2封装 5.类的作用域6.类的实例化7.类对象模型7.1如何计算类对象的大小7.2 类对象的存储方式猜测 8.this指针8.1this指针的引出8.2…

C语言入门教程,C语言学习教程(非常详细)第六章 C语言数组

什么是数组&#xff1f;C语言数组的基本概念 在《C语言数据输出大汇总以及轻量进阶》一节中我们举了一个例子&#xff0c;是输出一个 44 的整数矩阵&#xff0c;代码如下&#xff1a; #include <stdio.h>#include <stdlib.h>int main(){int a120, a2345, a3700, a…

PHP自己的框架实现debug调试模式和时区(完善篇三)

1、实现效果通过config设置开关debug调试模式 2、debug调试模式设置和时区设置 error_reporting和display_errors点击查看详细讲解 public static function run(){//定义常量self::_set_const();//创建模块目录self::_mk_module();//加载文件self::_import_file();self::_set_…

java请求SAP系统,发起soap的xml报文,实体类转换,idea自动生成教程

1、将接口的网页地址&#xff0c;右键保存&#xff0c;然后修改文件后缀为wsdl文件 2、idea全局搜索 wsdl&#xff0c;找到自动转换javabean插件&#xff1a; 3、点击后&#xff0c;选择下载改完后缀的文件&#xff1a; 4、将无用的class文件删除掉 5、请求sap的地址为&#…

Ae 效果:CC Twister

过渡/CC Twister Transition/CC Twister CC Twister&#xff08;CC 扭曲器&#xff09;效果主要用于创造出扭曲、旋转的动画效果&#xff0c;适用于背景动画、文字动画以及过渡动画等场景。 ◆ ◆ ◆ 效果属性说明 Completion 完成度 控制过渡的进度&#xff0c;0 %时为动画起…

hive中get_json_object函数不支持解析json中文key

问题 今天在 Hive 中 get_json_object 函数解析 json 串的时候&#xff0c;发现函数不支持解析 json 中文 key。 例如&#xff1a; select get_json_object({ "姓名":"张三" , "年龄":"18" }, $.姓名);我们希望的结果是得到姓名对应…

直播系统源码协议探索篇(二):网络套接字协议WebSocket

上一篇我们分析了直播平台的会话初始化协议SIP&#xff0c;他关乎着直播平台的实时通信和多方互动技术的实现&#xff0c;今天我们来讲另一个协议&#xff0c;叫网络套接字协议WebSocket&#xff0c;WebSocket基于TCP在客户端与服务器建立双向通信的网络协议&#xff0c;并且可…

博客系统之自动化测试

背景&#xff1a;针对个人博客项目进行测试&#xff0c;个人博客主要由四个页面构成&#xff1a;登录页、列表页、详情页和编辑页&#xff0c;主要功能包括&#xff1a;用户登录功能、发布博客功能、查看文章详情功能、查看文章列表功能、删除文章功能、退出功能。对于个人博客…

mysql全文检索使用

数据库数据量10万左右&#xff0c;使用like %test%要耗费30秒左右&#xff0c;放弃该办法 使用mysql的全文检索 第一步:建立索引 首先修改一下设置: my.ini中ngram_token_size 1 可以通过 show variables like %token%;来查看 接下来建立索引:alter table 表名 add f…

C#与西门子PLC1500的ModbusTcp服务器通信1--项目背景

最近在一个120万元的项目中&#xff0c;涉及到modbustcp通信&#xff0c;我作为软件总工负责项目的通信程序开发&#xff0c;modbus是一个在工业自动化领域中的通信协议&#xff0c;可以是modbusrtu&#xff0c;modbusascii&#xff0c;modbustcp三个形式&#xff0c;具体来说是…

QT VS编译环境无法打开包括文件type_traits

这问题&#xff0c;别人给的处理方法都是&#xff1a; 添加环境变量执行vsvars32.bat/vcvarsall.bat/vsdevcmd.bat重新安装QT项目&#xff1a;执行qmake。。。。 个人不推荐配置环境编译&#xff0c;除非你非常熟&#xff0c;因为配置环境变量需要你知道有哪些路径需要添加&a…

SpringBoo t+ Vue 微人事 (十一)

职位修改操作 在对话框里面做编辑的操作 添加对话框 <el-dialogtitle"修改职位":visible.sync"dialogVisible"width"30%"><div><el-tag>职位名称</el-tag><el-input size"small" class"updatePosIn…

Vue2-全局事件总线、消息的订阅与发布、TodoList的编辑功能、$nextTick、动画与过渡

&#x1f954;&#xff1a;高度自律即自由 更多Vue知识请点击——Vue.js VUE2-Day9 全局事件总线1、安装全局事件总线2、使用事件总线&#xff08;1&#xff09;接收数据&#xff08;2&#xff09;提供数据&#xff08;3&#xff09;组件销毁前最好解绑 3、TodoList中的孙传父&…