c3p0,DBCP,Druid(德鲁伊)数据库连接池

news2024/11/18 2:32:39

c3p0,DBCP,Druid(德鲁伊)数据库连接池

在这里插入图片描述


每博一文案

佛说:前世 500 次的回眸,才换来今生的一次擦肩而过。
人与人之间的缘分,真的无需强求,并不是所有的感情都能天长地久,正如《越过山丘》里唱的:总有人幸福白头,
总有人哭着分手,无论相遇还是不相遇,都是献给岁月的序曲人生。
这场长途跋涉的旅程中,有花繁盛开的世外桃源,也有遍地荒芜的戈壁沙漠,有注定的失去,也有没有结果的相遇,
遇见谁发生怎样的故事,大体都是缘分,有时候,有些事不用开口也明白。
有时候,有些路不走也会变长,在一起的时候,就用力爱,不留遗憾。
如果无法继续携手前行,缘分到头的时候,就痛快的说一声再见,他们只是你人生的过客,在你的生活当中,
陪你做过一段路,共同经历一些风景,然后经过时间的节点,在某个不经意间,又演了一场离别,是一场结束,
却是一场开始,放手才能感受解脱,失去了才懂得珍惜,我们要悄然收起过往的心酸,继续自己的人生。
有些人走进你的生命,只是为了证明你们没有缘分,不需说再见。
愿你得到而不喜,失而不忧。所有失去的,都会以另一种方式归来。
                                                ——————   一禅心灵庙语

文章目录

  • c3p0,DBCP,Druid(德鲁伊)数据库连接池
    • 每博一文案
    • 1. JDBC数据库连接池的必要性
      • 1.2 JDBC 连接数据库
    • 2. 数据库连接池技术
      • 2.1 数据库连接池技术的优点
    • 3. 多种开源的数据库连接池
    • 4. C3P0数据库连接池
    • 5. DBCP数据库连接池
    • 6. Druid(德鲁伊)数据库连接池
    • 7. 总结:
    • 8. 最后:


1. JDBC数据库连接池的必要性

  • 在使用开发基于数据库的 web 程序时,传统的模式基本是按以下步骤执行的

    1. 在主程序 (如 servlet,beans) 中建立数据库连接
    2. 执行相关的 sql语句操作数据库
    3. 使用完后关闭数据库连接

    如下图示:

在这里插入图片描述


传统方式的连接数据库,存在的问题:

  1. 普通的 JDBC 数据库连接使用 DriverManager 来获取到连接的,每次向数据库请求建立连接的时候,都要将 Connection 加载到内存中,再验证用户名和密码(需要花费0.05s ~ 1s的时间 ) 。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接,这样的方式,将会消耗大量的资源和时间。数据库的连接资源并没有得到一个很好的重复利用 ,如果同时有 几百人甚至 几千人 在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。本博客后面会作相应的演示,请大家继续往后看下去。
  2. 对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。 何为Java的内存泄漏
  3. 这种开发不能控制被创建的连接对象数,不能很好的管理连接的资源信息,系统资源会被毫无顾忌的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。

1.2 JDBC 连接数据库

这里我们演示使用传统的数据库连接池,将向 Mysql数据库请求 5000 次的连接,看看会发生什么事情 ???

包如下错误: java.sql.SQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"

package Blogs.blogs04;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCTest {
    public static void main(String[] args) {
        // 读取配置文件信息
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");  // 默认读取的是src目录下的文件

        try {
            Properties properties = new Properties();   // 创建读取.properties后缀的配置文件的对象
            properties.load(is);  // 以简单的线性格式输入字符读取属性列表(关键字/元素对)

            // 通过对象传入关键字获取到其中的信息
            String driverClass = properties.getProperty("driverClass");
            String url = properties.getProperty("url");
            String user = properties.getProperty("user");
            String password = properties.getProperty("password");

            // 3. 加载/注册驱动
            Class.forName(driverClass);

            // 测试连接 5000 次
            for(int i = 0; i < 5000; i ++) {
                // 连接数据库
                Connection connection = DriverManager.getConnection(url,user,password);

            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }


    }
}

在这里插入图片描述


2. 数据库连接池技术

为此,为了解决传统开发中的数据库连接问题,基本上也就是上述提到的三个问题,可以采用 数据库连接池技术

  • 数据库连接池的基本思想: 就是为数据库连接建立了一个 “连接池/缓冲池”。预先在连接池/缓冲池中放入一定数量的已经连接上数据库 的连接对象,当我们需要建立数据库连接时,只需要从 “连接池/缓冲池”中取出一个,使用完毕之后再 “归还给数据库了连接池”
  • 数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。
  • 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。大大提高了连接数据库的效率
  • 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由 最小数据库连接数设定的 (可以自行设定其最小连接数)。无论这些存放在数据库连接池中的连接是否被使用上,连接池都将一直保证至少含有这么多的连接数量,数据库连接池的 最多数据库连接数量 限定了这个连接池能占有的最大连接数,如果数据库连接池设定的最多连接数量都被占用了,这时候,当应用程序向数据库连接池请求连接时。这些连接请求将会加入到 等待队列 中,如果到达一定时间,还没有获取到连接,就会丢弃该连接请求。
  • 如下图示:

在这里插入图片描述

在这里插入图片描述

工作原理:

在这里插入图片描述

这里我们使用一个生动形象的例子来说明传统 JDBC 数据库连接,与使用数据库连接池的连接:

比如我们要从上海 ——> 北京的天安门:

  • 传统的 JDBC 数据库连接是,我们自己手动的制造出一台汽车,然后开着这台我们自己制造的汽车,前往北京的天安门,到达天安门以后,我们就将汽车销毁了。到我们返回 上海的时候,再造一台汽车返回上海,到达上海后又将其销毁了。别人都不可以用。
  • 数据库连接池是:我们乘坐直达的公共汽车到达北京的天安门,然后下车,公共汽车不销毁,可以继续载其他的人,当我们返回上海是,继续乘坐公共汽车,到达上海,同样公共汽车不销毁,可以继续乘载其他人。减少了资源的浪费。可以不断的重复利用。

在这里插入图片描述


2.1 数据库连接池技术的优点

  1. 资源重用

由于数据库连接得以重用 ,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的 平稳性 .

  1. 更快的系统反应速度

数据库连接池在初始化过程中,往往已经创建了若干个数据库连接存放于连接池 中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用的连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间。

  1. 新的资源分配手段

对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源。

  1. 统一的连接管理,避免数据库连接泄漏

在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用的连接,从而避免了常规数据库连接操作中可能出现的资源的泄漏问题。


3. 多种开源的数据库连接池

JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口通常由服务器(Weblogic,WebSphere,Tomcat) 提供实现,也有一些开源组织提供实现了:如下

  • DBCP 是Apache 提供的数据库连接池。tomcat 服务器自带 dbcp 数据库连接池,速度比 c3p0 较快,但因自身存在 BUG,Hibernate3 已不再提供支持了
  • C3P0 是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以,Hibernate 官方推荐使用
  • Proxoolsourceforge 下的一个开源项目数据库连接池,有监控连接状态的功能,稳定性较 C3P0 差一点。
  • BoneCP 是一个开源组织提供的数据库连接池,速度快
  • Druid 是阿里提供的数据库连接池,据说集 DBCP,C3P0,Proxool 优点于一身的数据库连接池,但是速度不确定是否有 BoneCP 快。市面上大多都是使用 该数据库连接池

DataSource 通常被称为数据源,是在javax.sql.DataSource包下的一个接口。它包含连接池和管理连接池两部分,习惯上也经常把 DataSource 称为连接池

DataSource 用来取代 DriverManager 来获取 Connection 连接,获取速度快,同时可以大幅度提高数据库访问速度。

特别注意:

  1. DataSource数据源(数据库连接池)和数据库连接不同,数据库连接池不需要创建多个,我们可以把它比作是生产数据库连接 的工厂,当我们的连接数量不够时,可以通过配置增加数据库连接池中的存储的连接,因此整个应用只需要一个数据库连接池(数据源)即可 。创建过多的数据库连接池,反而会适得其反。
  2. 当访问数据库,操作数据库结束后,程序还是像以前一样关闭数据连接:connection.close(),不过使用数据库连接池不同的是,这里仅仅是把数据库连接 归还 数据库连接池,并不是真正关闭对数据库的连接。这个连接还在。

虽然它们使用都是 Connection.close() 方法,但是所在的包路径是不同的,因为实现方式是不同的。在’com.mysql.cj.jdbc.ConnectionImpl’包中的是真正的关闭与数据库的连接,而在``包下是 归还 连接给数据库连接池。

javax.sql.DataSource 包下的 DataSource 接口的文档:

在这里插入图片描述

在这里插入图片描述


4. C3P0数据库连接池

C3P0 是第三方的封装的数据库连接池,所以我们需要导入相关的 c3p0-0.9.1.2-jdk1.3.jar 包才可以使用:如下

在这里插入图片描述

相关的jar 文件,我已经提交到 Github ,Gitee 当中的了,如有需要的可以自行获取。

  • Mysql数据库驱动/数据库连接池驱动 · 彩虹海/软件和配置 - 码云 - 开源中国 (gitee.com)
  • software-and-configuration/Mysql数据库驱动/数据库连接池驱动 at master · China-Rainbow-sea/software-and-configuration (github.com)

这里我使用的是 IDEA 编辑器,下面为我们的项目中导入 c3p0-0.9.1.2-jdk1.3.jar 包,操作如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这里就导入jar包成功了,后面的 DBCP,Druid 同样也是需要这样导入相关的 jar 包也是这样操作。


  • 获取c3p0数据库连接池中的连接的方式一: 通过传入相关配置参数,先创建 c3p0 数据库连接池,再从创建的 c3p0 数据库连接池中获取其中的连接。这种方式不推荐

至于如何创建 c3p0 数据库连接池以及 获取其中的连接,我们可以打开我们下载到的 c3p0 文档中路径为 c3p0\c3p0-0.9.1.2 下找了一个名为 index.html 的帮助文档,打开它,里面有相关的 c3p0 的使用

在这里插入图片描述

打开显示如下效果:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

import com.mchange.v2.c3p0.*;
	
...
	
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass( "org.postgresql.Driver" ); //loads the jdbc driver            
cpds.setJdbcUrl( "jdbc:postgresql://localhost/testdb" );
cpds.setUser("dbuser");                                  
cpds.setPassword("dbpassword");  

我们按照上面的创建 c3p0 的案例演示,创建 c3p0 数据库连接池并获取其中连接池中的连接

package Blogs.blogs04;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

public class C3P0Test {
    public static void main(String[] args) {
        try {
            // 通过传入配置参数,创建 c3p0 数据库连接池
            ComboPooledDataSource cpds = new ComboPooledDataSource();
            cpds.setDriverClass( "com.mysql.cj.jdbc.Driver" );   // 注册数据库驱动信息
            cpds.setJdbcUrl( "jdbc:mysql://localhost:3306/test");  // 实际连接的数据库的url在网络中所在的位置
            cpds.setUser("root");  // 用户名
            cpds.setPassword("MySQL123");  // 密码

            // 从c3p0 数据库连接池中获取连接数据库的对象
            Connection connection = cpds.getConnection();

            System.out.println(connection); // 打印连接的地址
            System.out.println(connection.getClass()); // 打印显示实现该类的所在包路径

        } catch (PropertyVetoException e) {
            throw new RuntimeException(e);   // 将编译异常转换为运行异常抛出
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

在这里插入图片描述


  • 使用C3P0数据库连接池的配置文件方式,获取数据库的连接方式二:推荐

关于如何编写 c3p0 的配置文件,同样查看其 index.html 的文档,如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


<c3p0-config>
  <default-config>
    <property name="automaticTestTable">con_test</property>
    <property name="checkoutTimeout">30000</property>
    <property name="idleConnectionTestPeriod">30</property>
    <property name="initialPoolSize">10</property>
    <property name="maxIdleTime">30</property>
    <property name="maxPoolSize">100</property>
    <property name="minPoolSize">10</property>
    <property name="maxStatements">200</property>

    <user-overrides user="test-user">
      <property name="maxPoolSize">10</property>
      <property name="minPoolSize">1</property>
      <property name="maxStatements">0</property>
    </user-overrides>

  </default-config>

  <!-- This app is massive! -->
  <named-config name="intergalactoApp"> 
    <property name="acquireIncrement">50</property>
    <property name="initialPoolSize">100</property>
    <property name="minPoolSize">50</property>
    <property name="maxPoolSize">1000</property>

    <!-- intergalactoApp adopts a different approach to configuring statement caching -->
    <property name="maxStatements">0</property> 
    <property name="maxStatementsPerConnection">5</property>

    <!-- he's important, but there's only one of him -->
    <user-overrides user="master-of-the-universe"> 
      <property name="acquireIncrement">1</property>
      <property name="initialPoolSize">1</property>
      <property name="minPoolSize">1</property>
      <property name="maxPoolSize">5</property>
      <property name="maxStatementsPerConnection">50</property>
    </user-overrides>
  </named-config>
</c3p0-config>

需要注意的是:c3p0 的配置文件名是:c3p0-config.xml 是不可以修改的,默认使用的就是这个文件名.

我们使用的是 IDEA 编译器,下面是如果在 IDEA 中创建 xml 文件,有的 IDEA 中 new 没有 xml,这时候就需要我们自己手动配置了。具体操作如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


接下来就是仿照上面 index.html 中 c3p0-config.xml 配置文件案例编写配置文件信息了。具体的编写的配置信息如下,大家可以直接复制粘贴上去,就可以直接使用了。不对,大家还要手动修改一下你所对应的 user用户名和 password 密码,以及 url 实际数据库的网络位置。其他的到没有什么问题了。
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?> <!-- 这句不要动,表示xml的版本,以及读取的编码-->
<c3p0-config>
    <named-config name="helloc3p0">   <!-- 表示创建c3p0数据库连接池时,查询的文件名来源,可以手动修改;-->
        <!-- 获取连接的4个基本信息 -->
        <property name="user">root</property>
        <property name="password">MySQL123</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true</property>
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>

        <!-- 涉及到数据库连接池的管理的相关属性的设置 -->
        <!-- 若数据库中连接数不足时, 一次向数据库服务器申请多少个连接 -->
        <property name="acquireIncrement">5</property>
        <!-- 初始化数据库连接池时连接的数量 -->
        <property name="initialPoolSize">5</property>
        <!-- 数据库连接池中的最小的数据库连接数,注意初始化连接个数与最小连接个数不要出现冲突 -->
        <property name="minPoolSize">5</property>
        <!-- 数据库连接池中的最大的数据库连接数 -->
        <property name="maxPoolSize">10</property>
        <!-- C3P0 数据库连接池可以维护的 Statement 的个数 -->
        <property name="maxStatements">20</property>
        <!-- 每个连接同时可以使用的 Statement 对象的个数 -->
        <property name="maxStatementsPerConnection">5</property>

    </named-config>
</c3p0-config>

我们编写好相关的 c3p0-config.xml 配置文件以后,就可以通过访问配置文件中的信息,创建c3p0数据库连接池,以及获取其中的连接了。

具体代码实现如下:

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

public class C3P0Test {
    // 方式二: 通过读取配置文件中的信息,创建c3p0数据库连接池
    public static void main(String[] args) {
        // 创建c3p0数据库连接池
        DataSource dataSource = new ComboPooledDataSource("helloc3p0");

        try {
            // 获取到数据库连接池中的连接
            Connection connection = dataSource.getConnection();
            System.out.println(connection);  // 打印连接地址
            System.out.println(connection.getClass()); // 打印类所在包下的路径
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }
    }
}

在这里插入图片描述


对 c3p0 数据库连接池进行一个封装,封装到 JDBCUtils 类当中。

错误演示:

package Blogs.blogs04;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.Connection;
import java.sql.SQLException;

public class JDBCUtils {
    public static Connection getConnection() {
        // 通过 c3p0-config.xml 配置文件,创建c3p0数据库连接池
        ComboPooledDataSource cpds = new ComboPooledDataSource("helloc3p0");
        
        Connection connection = null;
        try {
            connection = cpds.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }
        
        return connection;
    }
}

错误原因:

我们把创建 c3p0数据库连接池 放到了,调用返回连接中了。

在这里插入图片描述

把创建c3p0数据库连接池定义在方法中的后果是:我们每次调用该方法获取连接池,都会创建一个新的 c3p0 数据库连接池,一个连接池的创建的消耗远远比创建一个连接消耗来的大,而我们这么做就是:每创建一个连接就需要创建一个数据库连接池,还不如不用数据库连接池呢。

所以注意:一个应用使用一个数据库连接池就足够了,需要连接时,从数据库连接池中获取,如果数据库连接池中的连接不够了,可以通过配置增加数据库连接池中存有的连接,就把数据库连接池比作是一个生产连接的工厂。

综上所述:我们只要一个数据库连接池,所以我们可以将创建 c3p0 数据库连接池定义成静态 static 的类属性,和类一起加载到内存当中,只定义一次,所有对象共用这个数据库连接池

修改代码如下:

在这里插入图片描述

package Blogs.blogs04;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.Connection;
import java.sql.SQLException;

public class JDBCUtils {
    // 通过 c3p0-config.xml 配置文件,创建c3p0数据库连接池
    private static ComboPooledDataSource cpds = new ComboPooledDataSource("helloc3p0"); // 作为类属性存在
    public static Connection getC3p0Connection() {
        Connection connection = null;
        try {
            connection = cpds.getConnection();  // static 静态不要使用 this的引用
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }

        return connection;
    }
}

比较传统的 JDBC 连接数据库,和 C3P0 使用数据连接池的性能

jdbc 与 c3p0 都与数据库连接 5000 次,比较连接完后所消耗的时间:

传统的 JDBC 连接数据库 5000 次

package Blogs.blogs04;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCTest {
    public static void main(String[] args) {
        // 读取配置文件信息
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");  // 默认读取的是src目录下的文件

        try {
            Properties properties = new Properties();   // 创建读取.properties后缀的配置文件的对象
            properties.load(is);  // 以简单的线性格式输入字符读取属性列表(关键字/元素对)

            // 通过对象传入关键字获取到其中的信息
            String driverClass = properties.getProperty("driverClass");
            String url = properties.getProperty("url");
            String user = properties.getProperty("user");
            String password = properties.getProperty("password");

            // 3. 加载/注册驱动
            Class.forName(driverClass);

            long start = System.currentTimeMillis();  // 获取到 5000 次连接数据库的前的时间点:单位:毫秒

            // 测试连接 5000 次
            for(int i = 0; i < 5000; i ++) {
                // 连接数据库
                Connection connection = DriverManager.getConnection(url,user,password);

                if(connection != null) {
                    try {
                        connection.close(); // 关闭数据库连接
                    } catch(SQLException e) {
                        throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
                    }
                }

            }

            long end = System.currentTimeMillis();   // 5000次连接数据库结束的时间点:单位:毫秒
            System.out.println("jdbc 5000 次连接数据库所消耗的时间:" + (end - start));

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }


    }
}

在这里插入图片描述


C3P0 数据库连接池 中获取 5000 次的连接所消耗的时间

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

public class C3P0Test {
    // 方式二: 通过读取配置文件中的信息,创建c3p0数据库连接池
    public static void main(String[] args) {
        // 创建c3p0数据库连接池
        DataSource dataSource = new ComboPooledDataSource("helloc3p0");

        long start = System.currentTimeMillis();  // 连接前的时间点:单位:毫秒
        try {

            for(int i = 0 ; i < 5000; i++) {
                // 获取到数据库连接池中的连接
                Connection connection = dataSource.getConnection();

                if(connection != null) {
                    try{
                        connection.close();  // 使用使用数据库连接池,归还连接,不是关闭连接
                    } catch(SQLException e) {
                        throw new RuntimeException(e); // 将编译异常转换为运行异常抛出
                    }
                }
            }

            long end = System.currentTimeMillis();   // 连接结束后的时间点: 单位:毫秒

            System.out.println("c3p0 数据库连接池 5000 次连接所消耗的时间:"+ (end - start));

        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }
    }
}

在这里插入图片描述

使用 c3p0 我们再将连接次数 增加到 5W, 50W 查看所消耗的时间:

在这里插入图片描述

在这里插入图片描述

我们可以看到非常明显的性能差,c3p0 比传统的 jdbc 连接快了 100 多倍,这就是我们使用数据库连接池的原因之一。

5. DBCP数据库连接池

  • DBCP 是 Apache 软件基金组织下的开源连接池实现,该连接池依赖该组织下的另一个开源系统:Common-pool 。如需要使用 DBCP数据库连接池 ,则需要导入如下两个 jar 文件:

    1. Commons-dbcp.jar 连接池的实现架包

在这里插入图片描述

  1. Commons-pool.jar 连接池实现的依赖库。

在这里插入图片描述

  1. 同样我们也将相应的jar 包托放到 Github ,Gitee 当中了
    1. Mysql数据库驱动/数据库连接池驱动 · 彩虹海/软件和配置 - 码云 - 开源中国 (gitee.com)
    2. software-and-configuration/Mysql数据库驱动/数据库连接池驱动 at master · China-Rainbow-sea/software-and-configuration (github.com)
  • Tomcat 的连接池正是采用该连接池来实现的。 该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。

  • 数据源(数据库连接池)和数据库连接不同,数据库连接池无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据库连接池即可


方式一: 使用传参数的方式创建 DBCP 数据库连接池,在获取连接,不推荐

关于如何创建 DBCP 数据库连接池,同样我们可以阅读其中的index.html帮助文档:在我们所下 jar包文件的路径下:Commons-dbcp\commons-dbcp-1.4\apidocs

在这里插入图片描述

在这里插入图片描述


导入 Commons-dbcp.jar,Commons-pool.jar 两个 jar

在这里插入图片描述

具体代码实现如下:

package Blogs.blogs04;

import org.apache.commons.dbcp.BasicDataSource;

import java.sql.Connection;
import java.sql.SQLException;

public class DBCPTest {
    public static void main(String[] args) {
        // 定义创建 dbcp 数据库连接池的对象
        BasicDataSource source = new BasicDataSource();

        source.setDriverClassName("com.mysql.cj.jdbc.Driver"); // 注册驱动这里是mysql8.0/ 5.0的没有 cj
        source.setUrl("jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true"); // 实际数据库在网络url的位置
        // ?rewriteBatchedStatements=true批量处理
        // 或者可以省略本地主机 localhost:3306 改为 jdbc:mysql:///test

        source.setUsername("root"); // 用户名
        source.setPassword("MySQL123"); // 密码

        // 获取到数据库中的连接
        try {
            Connection connection = source.getConnection();
            System.out.println(connection);  // 所获得的连接的地址
            System.out.println(connection.getClass());  // 类所在的包路径
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }

    }
}

在这里插入图片描述


方式二:将所需的参数编写到配置文件当中,配置文件是以.properties为后缀的文件

注意是该配置文件创建在 src 目录下,这里我们将我们的 dbcp 所编写的配置文件名为为 dbcp.properties

IDEA 中的 src 目录中创建 .properties 文件

在这里插入图片描述

在这里插入图片描述

该文件的编写如下:

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
# ?rewriteBatchedStatements=true 表示批量处理
username=root
password=MySQL123
# 不要加空格和分号,不然报错,空格也会被当作是参数变量,识别使用

其他的配置文件的参数如下:大家可以自行参考,斟酌添加上

属性默认值说明
initalSize0数据库连接池启动时创建的初始化连接数量
maxActive8数据库连接池中可 同时 连接的最大的连接数量
maxldle8连接池中最大的空闲的连接数,超过的空闲连接将被释放 ,如果设置为负数表示无限制
minldle0连接池中最小的空闲的连接数,低于这个数量会被创建新的连接。该参数越接近 maxldle,性能越好,因为连接的创建和销毁,都需要消耗资源,但是不能太大
maxWait无限制最大等待时间,当没有空闲的连接,连接池中所有的连接都被占用时,再请求连接,则会加入到等待队列中,等待空闲的连接出现,如果超过了该设定的等待时间还没有出现空闲连接,就会自动放弃该连接请求。如果设置为 -1 表示无限等待
poolPreparedStatementsfalse开启连接池中的 Statement 是否为 prepared
maxOpenPreparedStatements无限制开启连接池的 prepared 后的同时最大连接数
minEvictableldleTimeMillis连接池中连接,在时间段内一直空闲,被逐出连接池的时间
removerAbandonedTimeout300超过时间限制,自动回收没有用(废弃)的连接

具体代码实现如下:


import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class DBCPTest {
    // 方式二:通过读取配置文件中的信息,创建dbcp数据库连接池
    public static void main(String[] args) {

        try {
            // 读取配置文件中的信息,方式一:
            FileInputStream is = new FileInputStream(new File("src/dbcp.properties"));

            // 读取配置文件中信息,方式二:
            InputStream io = ClassLoader.getSystemClassLoader().getResourceAsStream("dbcp.properties"); // 默认是读取src目录下的文件

            // 创建对象获取读取到的配置文件的参数信息
            Properties properties = new Properties();
            properties.load(is);  // 以简单的线性格式输入字符读取到属性列表(关键字/元素对)

            // 通过传入获取配置文件的对象,创建dbcp 数据库连接池
            DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
            // 从dbcp 数据库连接池中获取到连接
            Connection connection = dataSource.getConnection();
            System.out.println(connection);  // 显示连接地址
            System.out.println(connection.getClass());  // 显示类所在的包下的路径
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }


    }
}

在这里插入图片描述


下面我们对 dbcp 数据库连接池进行一个封装,如下:同样注意,一个应用一个数据库连接池就足够了。

错误演示:

我们需要调用方法读取配置文件中的信息,定义对象在类当中:作为类属性存在没有问题,但是在类当中我们是无法调用方法的。

方法的调用需要是在:代码块当中:方法中的代码块,以及 类当中的 static 静态代码块,而静态代码块的特点十分符合我们一个应用一个 数据库连接池,因为 static 静态代码块(和类一起加载到内存当中,仅仅执行一次,所有对象共用它)。

在这里插入图片描述

改正:

具体代码如下:

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class JDBCUtils {

    private static DataSource dataSource = null;
    static {
        try {
            // 读取配置文件中的信息,方式一:
            FileInputStream is = new FileInputStream(new File("src/dbcp.properties"));
            // 读取配置文件中信息,方式二:
            InputStream io = ClassLoader.getSystemClassLoader().getResourceAsStream("dbcp.properties"); // 默认是读取src目录下的文件
            // 创建对象获取读取到的配置文件的参数信息
            Properties properties = new Properties();
            properties.load(is);  // 以简单的线性格式输入字符读取到属性列表(关键字/元素对)
            // 通过传入获取配置文件的对象,创建dbcp 数据库连接池
            dataSource = BasicDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(e); // 将编译异常转换为运行异常抛出
        }
    }


    public static Connection getDbcpConnection() {

        try {
            Connection connection = dataSource.getConnection();
            return connection;
        } catch (SQLException e) {
            throw new RuntimeException(e); // 将编译异常转换为运行异常抛出
        }
    }
}

测试 DBCP 数据库连接池处理 5000次/5w次50w次 连接所消耗的时间:

具体代码如下:

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class DBCPTest {
    // 方式二:通过读取配置文件中的信息,创建dbcp数据库连接池
    public static void main(String[] args) {

        try {
            // 读取配置文件中的信息,方式一:
            FileInputStream is = new FileInputStream(new File("src/dbcp.properties"));

            // 读取配置文件中信息,方式二:
            InputStream io = ClassLoader.getSystemClassLoader().getResourceAsStream("dbcp.properties"); // 默认是读取src目录下的文件

            // 创建对象获取读取到的配置文件的参数信息
            Properties properties = new Properties();
            properties.load(is);  // 以简单的线性格式输入字符读取到属性列表(关键字/元素对)

            // 通过传入获取配置文件的对象,创建dbcp 数据库连接池
            DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);

            long start = System.currentTimeMillis();  // 获取到连接前的时间点: 单位毫秒

            for(int i = 0; i < 5000; i++) {
                // 从dbcp数据库连接池中获取到连接
                Connection connection = dataSource.getConnection();

                if(connection != null) {
                    try{
                        // 归还连接,不是关闭连接
                        connection.close();
                    } catch(SQLException e) {
                        throw new RuntimeException(e); // 将编译异常转换为运行异常抛出
                    }
                }
            }

            long end = System.currentTimeMillis();  // 获取到所有连接完毕后的时间点:

            System.out.println("5000次连接所消耗的时间: " + (end - start));
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }


    }
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


6. Druid(德鲁伊)数据库连接池

Druild 是阿里巴巴开源平台上一个数据库连接池实现,它结合了 C3P0,DBCP,ProxoolDB 池的优点,同时加入了 日志监控 ,可以很好的监控 数据库连接池SQL的执行情况 ,可以说针对监控而生的 数据库连接池,同时也可以说是 目前最好的连接池之一 。是目前市场上大部分厂家使用的数据库连接池(数据源)。 同样的 Druid 也有相关的index.html帮助文档:在如下路径中 commons-dbutils-1.3\apidocs

在这里插入图片描述

在这里插入图片描述


和上面的两个数据库连接池是一样的,同样需要导入 有关 Druild 的 jar 包commons-dbutils-1.3.jar 如下

IDEA 导入 commons-dbutils-1.3.jar 包
在这里插入图片描述

同样我们也将相应的jar 包托放到 Github ,Gitee 当中了

  1. Mysql数据库驱动/数据库连接池驱动 · 彩虹海/软件和配置 - 码云 - 开源中国 (gitee.com)
  2. software-and-configuration/Mysql数据库驱动/数据库连接池驱动 at master · China-Rainbow-sea/software-and-configuration (github.com)

在这里插入图片描述


这里我们直接使用编写配置文件,然后读取配置文件的方式 创建 Druid 数据库连接池的方式

注意编写配置文件是以 .properties后缀的,而且是创建在 src 目录下的配置文件的信息。

这里我们创建的 Druid 配置文件的名为 druid.properties

如下使用 IDEA 创建 .properties 的文件

在这里插入图片描述

在这里插入图片描述


下面是 druid.properties 配置文件的编写:

driverClassName=com.mysql.cj.jdbc.Driver
#?rewriteBatchedStatements=true 批量处理打开
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
username=root
password=MySQL123
#初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
initialSize=10
#最小连接池数量
minIdle=5
#最大连接池数量
maxActive=20
#获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
maxWait=5000
#属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:   监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
filters=wall

#不要加空格以及;分号,因为无论是空格还是分号都会被识别成对象匹配。防止匹配失败

下面是其他的有关 Druid 配置参数信息,大家可以自行参考,斟酌添加上

配置缺省说明
name配置这个属性的意义在于,如果存在多个数据源,监控的时候可以通过名字来区分开来。 如果没有配置,将会生成一个名字,格式是:”DataSource-” + System.identityHashCode(this)
url连接数据库的url,不同数据库不一样。例如:mysql : jdbc:mysql://10.20.153.104:3306/druid2 oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto
username连接数据库的用户名
password连接数据库的密码。如果你不希望密码直接写在配置文件中,可以使用ConfigFilter。详细看这里:https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter
driverClassName根据url自动识别 这一项可配可不配,如果不配置druid会根据url自动识别dbType,然后选择相应的driverClassName(建议配置下)
initialSize0初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时
maxActive8最大连接池数量
maxIdle8已经不再使用,配置了也没效果
minIdle最小连接池数量
maxWait获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
poolPreparedStatementsfalse是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
maxOpenPreparedStatements-1要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
validationQuery用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
testOnBorrowtrue申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testOnReturnfalse归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testWhileIdlefalse建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
timeBetweenEvictionRunsMillis有两个含义: 1)Destroy线程会检测连接的间隔时间2)testWhileIdle的判断依据,详细看testWhileIdle属性的说明
numTestsPerEvictionRun不再使用,一个DruidDataSource只支持一个EvictionRun
minEvictableIdleTimeMillis
connectionInitSqls物理连接初始化的时候执行的sql
exceptionSorter根据dbType自动识别 当数据库抛出一些不可恢复的异常时,抛弃连接
filters属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 监控统计用的filter:stat日志用的filter:log4j防御sql注入的filter:wall
proxyFilters类型是List,如果同时配置了filters和proxyFilters,是组合关系,并非替换关系

通过读取配置文件信息,创建 Druid 数据库连接池,再获取其中的连接

package Blogs.blogs04;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;

public class DruidTest {
    public static void main(String[] args) {
        // 读取配置文件的方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");

        try {
            // 读取配置文件的方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建对象获取到读取的配置文件中的关键字/属性值
            Properties properties = new Properties();
            properties.load(io);

            // 通过传入读取配置文件信息对象,创建 druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

            // 从创建的 druid数据库连接池中获取到连接
            Connection connection = dataSource.getConnection();

            System.out.println(connection);  // 连接的地址
            System.out.println(connection.getClass());  // 类所在的包路径位置
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出。
        }

    }
}

在这里插入图片描述


同理将 创建 Druid 数据库连接池封装起来。注意:一个应用一个数据库连接池就足够了,方法的调用,写在static静态代码块中(和类一起加载到内存当中,仅仅执行一次,所有对象共用)。

具体实现如下:

public class JDBCUtils {
    private static DataSource dataSource = null;
    static {
        try {
            // 读取配置文件的方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建对象获取到读取的配置文件中的关键字/属性值
            Properties properties = new Properties();
            properties.load(io);

            // 通过传入读取配置文件信息对象,创建 druid数据库连接池
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }
    }

    public static Connection getDruidConnection() {
        try {
            Connection connection = dataSource.getConnection();
            return connection;
        } catch (SQLException e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出
        }
    }
}

测试 Druid 数据库连接池处理 5000次/5w次50w次 连接所消耗的时间:

具体代码如下:

package Blogs.blogs04;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class DruidTest {
    public static void main(String[] args) {
        // 读取配置文件的方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");

        try {
            // 读取配置文件的方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建对象获取到读取的配置文件中的关键字/属性值
            Properties properties = new Properties();
            properties.load(io);

            // 通过传入读取配置文件信息对象,创建 druid数据库连接池
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

            long start = System.currentTimeMillis();   // 获取到连接前的时间点:单位毫秒

            for(int i = 0; i < 5000; i++) {
                // 从创建的 druid数据库连接池中获取到连接
                Connection connection = dataSource.getConnection();

                if(connection != null) {
                    try {
                        connection.close();   // “归还连接”,不是关闭连接
                    } catch (SQLException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

            long end = System.currentTimeMillis();   // 获取到连接完毕后的时间点:单位毫秒

            System.out.println("5000次连接所消耗的时间:" +(end - start));

        } catch (Exception e) {
            throw new RuntimeException(e);  // 将编译异常转换为运行异常抛出。
        }

    }
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


7. 总结:

  1. 我们上述的这三种 C3P0,DBCP,Druid 数据库连接池(数据源) 都是第三方基于 DataSource 接口编写封装的,同时注意使用这三种数据库连接池,需要导入相关的 jar 包:
    • C3P0:c3p0-0.9.1.2-jdk1.3.jar
    • DBCP:Commons-dbcp.jar ( 连接池的实现架包 ),Commons-pool.jar( 连接池实现的依赖库 )
    • Druid(德鲁伊)commons-dbutils-1.3.jar
    • Mysql数据库驱动/数据库连接池驱动 · 彩虹海/软件和配置 - 码云 - 开源中国 (gitee.com)
    • software-and-configuration/Mysql数据库驱动/数据库连接池驱动 at master · China-Rainbow-sea/software-and-configuration (github.com)
  2. 这三种 C3P0,DBCP,Druid 都有帮助文档,index.html大家不要忘记了它的存在。
  3. static 静态的是和类一起同时加载到内存到中的,就不要使用 “this.” 的引用了
  4. 需要注意这三种数据库连接池的 配置文件的编写 ,其中C3p0 默认配置文件名是 :c3p0-config.xml ,而 DBCP以及 Druid(德鲁伊) 它们俩的 配置文件 是以 .properties后缀的,都将它们三者的配置文件信息都存放在项目 src 目录下。
  5. 读取配置文件的两种方式:
 // 读取配置文件的方式一:
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");

// 读取配置文件的方式二:
            FileInputStream io = new FileInputStream(new File("src/druid.properties"));

            // 创建对象获取到读取的配置文件中的关键字/属性值
            Properties properties = new Properties();
            properties.load(io);

  1. 一个应用一个数据库连接池,而不是创建一个连接,就创建一个数据库连接池,这样还不如不使用数据库连接池技术。当连接不够了,可以通过增加数据库连接池中的连接数量,我们可以把数据库连接池(数据源)比作是一个生产连接的工厂 ,工厂只需要一个,所以一个应用只需要一个数据库连接池就足够了。
  2. 注意:方法的调用是不能在类当中的,需要在代码块当中,方法代码块,static静态代码块(和类一起加载到内存当中,仅仅只执行一次,所有对象共用),该特点十分符合 一个应用一个数据库连接池的特征 ,所有我们将创建数据库连接池放在类的 static 静态/静态代码块中执行。

在这里插入图片描述

  1. 数据库连接池技术的优点:资源重用更快的系统反应速度更快的系统反应速度统一的连接管理,避免数据库连接泄漏

8. 最后:

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见 !!!。最后,朋友,请留下你来过的证明 。

在这里插入图片描述

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

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

相关文章

C#压缩图片

SqlSer数据库设置保存图片字段类型为Image类型 对应保存 方法参数为图片路径&#xff0c;压缩后路径&#xff0c;压缩最大宽度&#xff0c;压缩最大高度 引用类型using System.Data; using System.Drawing; using System.IO; \完整类 /// <summary> /// 按比例缩放&…

七牛qshell 批量上传 mac 本地目录

七牛qshell 批量上传 mac 本地目录下载路径及使用方法(官方)下载到自己指定的文件夹添加环境变量,使qshell在任意地方可以执行添加密钥 生成账户文件下载路径及使用方法(官方) https://developer.qiniu.com/kodo/1302/qshell记录自己部署遇到的问题及操作步骤 下载到自己指定…

音视频开发核心知识点及源码解析,还不赶紧收藏起来

随着基础设施的完善&#xff08;光纤入户、wifi覆盖、5G普及&#xff09;的影响&#xff0c;将短视频、直播、视频会议、在线教育、在线医疗瞬间推到了顶峰&#xff0c;人们对音视频的需求和要求也越来越强烈 音视频开发还具有许多方向&#xff0c;比如&#xff1a; 如果对音视…

C语言:while后加分号与for后加分号的区别

while 后面不能加分号&#xff0c;否则虽然编译可以通过&#xff0c;但是执行程序时会发生死循环#include <stdio.h> int main() { int i1,total0; while(i<100)//不能在 while 后面加分号 { totali; i;//循环…

个人付费专栏上线预热

个人付费专栏上线预热 专栏地址&#xff1a;请点击访问 文章目录一、订阅这个专栏有什么好处&#xff1f;二、实战项目预告1. 活动类站点 &#xff08;已完成前端后端&#xff09;2. 电商项目 &#xff08;筹备中&#xff0c;一比一还原设计图&#xff09;3. 论坛问答系统 &…

每日三题-爬楼梯、买卖股票的最佳时机、正则表达式匹配

&#x1f468;‍&#x1f4bb;个人主页&#xff1a; 才疏学浅的木子 &#x1f647;‍♂️ 本人也在学习阶段如若发现问题&#xff0c;请告知非常感谢 &#x1f647;‍♂️ &#x1f4d2; 本文来自专栏&#xff1a; 算法 &#x1f308; 算法类型&#xff1a;Hot100题 &#x1f3…

IP 摄像机移动应用 SDK 开发入门教程(安卓版)

涂鸦智能安卓版摄像机&#xff08;IP Camera&#xff0c;简称 IPC&#xff09;SDK 是基于智能生活 App SDK 开发而成。 通过移动应用控制物理网设备是常见的使用场景&#xff0c;但由于设备的品类丰富&#xff0c;增大了应用开发难度。因此 智能生活 App SDK 提供了常见的垂直…

支付宝支付内网穿透

支付宝支付&内网穿透一 沙箱环境二 python第三方模块python-alipay-sdk三 python-alipay-sdk二次封装四 支付接口五 内网穿透5.1 cpolar软件5.2 测试支付宝post回调一 沙箱环境 注册认证沙箱环境&#xff1a;https://openhome.alipay.com/platform/appDaily.htm?tabinfo …

【FileZila】实现windows与Linux系统文件互传

1、下载安装FileZila客户端 根据自己的PC系统版本&#xff0c;下载对应的FileZila客户端https://www.filezilla.cn/download/client 2、Linux服务端&#xff0c;安装配置vsftpd 2.1 安装ftp服务 sudo apt-get install vsftpd2.2 配置ftp服务 &#xff08;1&#xff09;打开ft…

Verilog 实现CDC中单bit 跨时钟域,从慢时钟域到快时钟域

单bit 跨时钟域&#xff0c;从慢时钟域到快时钟域1&#xff0c;首先&#xff0c;了解一些问题2&#xff0c;RTL代码设计3&#xff0c;testbench测试代码4&#xff0c;RTL代码和testbench综合的电路原理图5&#xff0c;前仿真&#xff0c;验证![在这里插入图片描述](https://img…

关于某些地区延期举办2022年11月27日 PMI认证考试等有关事项的通知

22年.11月22日通知&#xff1a; 关于成都等六个地区延期举办2022年11月27日 PMI认证考试等有关事项的通知 尊敬的考生&#xff1a; 受近日疫情影响&#xff0c;结合当地疫情防控规定和活动举办要求&#xff0c;成都、武汉、西安、昆明、银川、长春地区现不满足组织2022年11月…

A. The Enchanted Forest(思维)

Problem - 1687A - Codeforces 玛丽莎来到魔法森林采摘蘑菇。 魔法森林可以用X轴上编号为1到n的n个点来表示。在玛丽莎开始之前&#xff0c;她的朋友帕秋莉用魔法检测了每个点上的蘑菇的初始数量&#xff0c;用a1,a2,...,an表示。 玛丽莎可以在第0分钟时从森林的任何一点开始…

Allegro如何输出IDF文件操作指导

Allegro如何输出IDF文件操作指导 Allegro支持输出IDF文件,用于导入结构软件中检查和查看,具体操作如下 点击File-export-IDF 会弹出一个对话框,file name type选择IDF 然后点击export,输出IDF文件,文件已经输出 This section is describe what the function allegro h…

项目管理工具需要具备的五点功能

将新产品推向市场是有益的&#xff0c;但也具有挑战性。从一个概念到成功发布的过程涉及很多事情。在产品开发过程中&#xff0c;许多内部团队都参与了将概念推向市场的工作。例如&#xff0c;设计团队、工程团队和营销团队都在这个生命周期中发挥作用。协调时间表、阶段和可交…

【Vue】组件化和声明周期函数

1. 组件化 组件化就是指一个后台我们将它的各个部分拆分成各个组件&#xff0c;比如 csdn 的上边栏、右侧广告区等都可以是组件&#xff0c;组件可以复用。Vue 的一个好处就是组件化。 <!DOCTYPE html> <html lang"en"> <head><meta charset&…

【云原生】Docker的数据卷、数据卷容器,容器互联

内容预知 1.数据卷&#xff08;容器与宿主机之间数据共享&#xff09; 2. 数据卷容器&#xff08;容器与容器之间数据共享&#xff09; 3. 容器互联&#xff08;使用centos镜像&#xff09; 3.1 实现容器互联 3.2 只通过IP进行通信 总结 1.数据卷&#xff08;容器与宿主…

视频编解码 - 帧间预测

目录 帧间预测 块大小 参考帧和运动矢量 运动矢量 运动搜索 1、全搜索算法 2、钻石搜索算法&#xff08;菱形搜索算法&#xff09; 3、六边形搜索算法 搜索起始点的确定 快速搜索与全搜索的优缺点 非整像素的处理 亚像素差值 亚像素精度运动搜索 运动矢量预测 S…

双十二蓝牙耳机哪款好?双十二平价蓝牙耳机推荐

对于许多人来说&#xff0c;音乐即是生活良药&#xff0c;带给我们生活、工作和学习的动力&#xff0c;若想要随时随地都能来上一剂&#xff0c;那么买到一款划算平价的真无线蓝牙耳机便是优秀的选择。 一、南卡小音舱蓝牙耳机 蓝牙&#xff1a;5.3 延迟&#xff1a;45ms 发…

npm、yarn到pnpm的发展历程

npm、yarn到pnpm的发展历程背景价值点npm发展及存在的问题npm v1&#xff08;树状结构&#xff09;安装原则优点不足&#xff1a;npm v3&#xff08;扁平化结构&#xff09;安装原则优点&#xff1a;不足&#xff1a;目录结构不确定依赖A先安装依赖A后安装npm v5优点npm包分身定…

mysql全文索引

引用&#xff1a;https://www.cnblogs.com/miracle-luna/p/11147859.html MySQL 5.7.6之前只支持英文全文索引&#xff0c;不支持中文全文索引&#xff0c;&#xff0c;需要利用分词器把中文段落预处理 拆分成单词&#xff0c;&#xff0c;然后存入数据库 MySQL 5.7.6 开始&am…