定义

数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。
        数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。

参考资料

DBCP
下载地址:http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi
相关属性说明: http://commons.apache.org/proper/commons-dbcp/configuration.html
c3p0
下载地址:http://sourceforge.net/projects/c3p0/
相关属性说明: http://www.mchange.com/projects/c3p0/
Druid
下载地址:http://repo1.maven.org/maven2/com/alibaba/druid/
相关属性说明: https://github.com/alibaba/druid/wiki
Proxool
下载地址:http://proxool.sourceforge.net/
相关属性说明:https://github.com/proxool/proxool

数据库连接池

原理

连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。

使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。

同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等,也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

常见数据库连接池及其特点

在 Java 中开源的常用的数据库连接池有以下几种 :
1)DBCP
        DBCP 是一个依赖 Jakarta commons-pool 对象池机制的数据库连接池.DBCP 可以直接的在应用程序中使用,Tomcat 的数据源使用的就是 DBCP。
2)c3p0
        c3p0 是一个开放源代码的 JDBC 连接池,它在 lib 目录中与 Hibernate 一起发布,包括了实现 jdbc3 和 jdbc2 扩展规范说明的 Connection 和 Statement 池的 DataSources 对象。
3)Druid
        阿里出品,淘宝和支付宝专用数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个 ProxyDriver,一系列内置的JDBC 组件库,一个 SQL Parser。支持所有 JDBC 兼容的数据库,包括 Oracle、MySql、Derby、Postgresql、SQL Server、H2 等等。
        Druid 针对 Oracle 和 MySql 做了特别优化,比如 Oracle 的 PS Cache 内存占用优化,MySql 的 ping 检测优化。
        Druid 提供了 MySql、 Oracle、 Postgresql、 SQL-92 的 SQL 的完整支持,这是一个手写的高性能 SQL Parser,支持 Visitor模式,使得分析 SQL 的抽象语法树很方便。简单 SQL 语句用时 10 微秒以内,复杂 SQL 用时 30 微秒。
        通过 Druid 提供的 SQL Parser 可以在 JDBC 层拦截 SQL 做相应处理,比如说分库分表、审计等。Druid 防御 SQL 注入攻击的 WallFilter 就是通过 Druid 的 SQL Parser 分析语义实现的。
4) proxool
        Proxool 是一种 Java 数据库连接池技术。sourceforge 下的一个开源项目,这个项目提供一个健壮、易用的连接池,最为关键的是这个连接池提供监控的功能,方便易用,便于发现连接泄漏的情况。目前是和 DBCP 以及 C3P0 一起,最为常见的三种 JDBC 连接池技术。目前,Hibernate 官方宣布由于 Bug 太多不再支持 DBCP,而推荐使用 Proxool 或 C3P0。

主要配置说明

连接池配置大体可以分为基本配置、关键配置、性能配置等主要配置,缺少 proxool 相关配置。

基本配置

基本配置是指连接池进行数据库连接的四个基本必需配置:
传递给 JDBC 驱动的用于连接数据库的用户名、密码、URL 以及驱动类名。

  DBCP c3p0 Druid
用户名 username   user   username
密码 password   password   password
URL url   jdbcUrl   jdbcUrl
驱动类名 driverClassName   driverClass   driverClassName

注:在 Druid 连接池的配置中,driverClassName 可配可不配,如果不配置会根据 url 自动识别 dbType(数据库类型),然后选择相应的 driverClassName。

关键配置

为了发挥数据库连接池的作用,在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。
最小连接数:
        是数据库一直保持的数据库连接数,所以如果应用程序对数据库连接的使用量不大,将有大量的数据库资源被浪费。
初始化连接数:
        连接池启动时创建的初始化数据库连接数量。
最大连接数:
        是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求被加入到等待队列中。
最大等待时间:
        当没有可用连接时,连接池等待连接被归还的最大时间,超过时间则抛出异常,可设置参数为 0 或者负数使得无限等待(根据不同连接池配置)。

  DBCP c3p0 Druid
最小连接数 minIdle(0) minPoolSize(3) minIdle(0)
初始化连接数 initialSize(0) initialPoolSize(3) initialSize(0)
最大连接数 maxTotal(8) maxPoolSize(15) maxActive(8)
最大等待时间 maxWaitMillis(毫秒) maxIdleTime(0秒) maxWait(毫秒)

注 1:在 DBCP 连接池的配置中,还有一个 maxIdle 的属性,表示最大空闲连接数,超过的空闲连接将被释放,默认值为 8。对应的该属性在 Druid 连接池已不再使用,配置了也没有效果,c3p0 连接池则没有对应的属性。
注 2:数据库连接池在初始化的时候会创建 initialSize 个连接,当有数据库操作时,会从池中取出一个连接。如果当前池中正在使用的连接数等于 maxActive,则会等待一段时间,等待其他操作释放掉某一个连接,如果这个等待时间超过了maxWait,则会报错;如果当前正在使用的连接数没有达到 maxActive,则判断当前是否空闲连接,如果有则直接使用空闲连接,如果没有则新建立一个连接。在连接使用完毕后,不是将其物理连接关闭,而是将其放入池中等待其他操作复用。

性能配置

预缓存设置:
        即是 PSCache,PSCache 对支持游标的数据库性能提升巨大,比如说 oracle。JDBC 的标准参数,用以控制数据源内加载的 PreparedStatements 数量。但由于预缓存的 statements 属于单个 connection 而不是整个连接池,所以设置这个参数需要考虑到多方面的因素。

单个连接拥有的最大缓存数:

要启用 PSCache,必须配置大于 0,当大于 0 时,poolPreparedStatements 自动触发修改为true。在 Druid 中,不会存在 Oracle 下 PSCache 占用内存过多的问题,可以把这个数值配置大一些,比如说 100。

  DBCP c3p0 Druid
开启缓存功能 poolPreparedStatements  maxStatements  poolPreparedStatements
单个连接拥有的最大缓存数 maxOpenPrepared-Statements maxStatementsPer-Connection maxOpenPrepared-Statements

连接有效性检测设置:

连接池内部有机制判断,如果当前的总的连接数少于 miniIdle,则会建立新的空闲连接,以保证连接数得到 miniIdle。如果当前连接池中某个连接在空闲了 timeBetweenEvictionRunsMillis 时间后仍然没有使用,则被物理性的关闭掉。有些数据库连接的时候有超时限制(mysql 连接在 8 小时后断开),或者由于网络中断等原因,连接池的连接会出现失效的情况,这时候设置一个 testWhileIdle 参数为 true,可以保证连接池内部定时检测连接的可用性,不可用的连接会被抛弃或者重建,最大情况的保证从连接池中得到的 Connection 对象是可用的。当然,为了保证绝对的可用性,你也可以使用 testOnBorrow为 true(即在获取 Connection 对象时检测其可用性),不过这样会影响性能。

  DBCP c3p0 Druid
申请连接检测 testOnBorrow testConnectionOnCheckin testOnBorrow
是否超时检测 testWhileIdle   testWhileIdle
空闲时间 timeBetweenEvictionRunsMillis idleConnectionTestPeriod timeBetweenEvictionRunsMillis
校验用 sql 语句 validationQuery preferredTestQuery validationQuery
归还连接检测 testOnReturn testConnectionOnCheckout testOnReturn

超时连接关闭设置:
        removeAbandoned 参数,用来检测到当前使用的连接是否发生了连接泄露,所以在代码内部就假定如果一个连接建立连接的时间很长,则将其认定为泄露,继而强制将其关闭掉。

  DBCP c3p0 Druid
是否超时关闭连接 removeAbandoned breakAfterAcquireFailure removeAbandoned
超时时间 removeAbandonedTimeout checkoutTimeout removeAbandonedTimeout
是否记录日志 logAbandoned   logAbandoned

c3p0 重连设置:
设置获取连接失败后,是否重新连接以及间隔时间。

  DBCP c3p0 Druid
重连次数   acquireRetryAttempts  
间隔时间   acquireRetryDelay  

配置详解

DBCP 属性说明表

属性(Parameter) 默认值(Default) 描述(Description)
username   传递给 JDBC 驱动的用于建立连接的用户名
password   传递给 JDBC 驱动的用于建立连接的密码
url   传递给 JDBC 驱动的用于建立连接的 URL
driverClassName   使用的 JDBC 驱动的完整有效的java 类名
defaultAutoCommit driver 连接池创建的连接的默认的default  auto-commit 状态,没有设置则不会自动提交
initialSize 0 初始化连接:连接池启动时创建的初始化连接数量
maxTotal 8 最大活动连接:连接池在同一时间能够分配的最大活动连接的数量, 如
果设置为非正数则表示不限制
maxIdle 8 最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示
不限制
minIdle 0 最小空闲连接:连接池中容许保持空闲状态的最小连接数量,负数表示没
有限制。
maxWaitMillis indefinitely 最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常,如果设置为-1 表示无限等待。
validationQuery   SQL 查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.如果指定,则查询必须是一个 SQL SELECT 并且必须返回至少一行记录。
testOnCreate false 指明是否在建立连接之后进行验证,如果验证失败,则尝试重新建立连接
testOnBorrow true 指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个. 注意:设置为 true 后如果要生效,validationQuery 参数必须设置为非空字符串。
testOnReturn false 指明是否在归还到池中前进行检验
testWhileIdle false 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除. 注意:设置为true 后如果要生效,validationQuery 参数必须设置为非空字符串
timeBetweenEviction-RunsMillis -1 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位.如果设置为非正数,则不运行空闲连接回收器线程
numTestsPerEvictionRun 3 在每次空闲连接回收器线程(如果有)运行时检查的连接数量
minEvictableIdleTime-Millis 1000*60*30 连接在池中保持空闲而不被空闲连接回收器线程(如果有)回收的最小时间值,单位毫秒
softMiniEvictableIdle- TimeMillis -1 在空闲连接回收器有资格被回收之前,连接在池中可能闲置的最小时间量,以及在池中至少有“minIdle”连接保留的额外条件。当miniEvictableIdleTimeMillis设置为正值时,miniEvictableIdleTimeMillis首先由空闲连接回收器检查 - 即当回收器访问空闲连接时,首先将空闲时间与miniEvictableIdleTimeMillis(不考虑池中空闲连接数)进行比较,然后针对softMinEvictableIdleTimeMillis,包括minIdle约束。
maxConnLifetimeMillis -1 The maximum lifetime in milliseconds of a connection. After this time is exceeded the connection will fail the next activation, passivation or validation test. A value of zero or less means the connection has an infinite lifetime.
logExpiredConnections   true   Flag to log a message indicating that a connection is being closed by the pool due to maxConnLifetimeMillis exceeded. Set this property to false to suppress expired connection logging that is turned on by default.
connectionInitSqls null A Collection of SQL statements that will be used to initialize physical connections when they are first created. These statements are executed only once - when the configured connection factory creates the connection.
info true True means that borrowObject returns the most recently used ("last in") connection in the pool (if there are idle connections available). False means that the pool behaves as a FIFO queue - connections are taken from the idle instance pool in the order that they are returned to the pool.
poolPreparedState-ments false 开启池的 prepared statement 池功能
maxOpenPreparedState-ments unlimited statement 池能够同时分配的打开的statements的最大数量, 如果设置为 0 表示不限制
accessToUnderlyingConnectionAllowed false   控制 PoolGuard 是否容许获取底层连接. 默认 false 不开启,这是一个有潜在危险的功能, 不适当的编码会造成伤害.(关闭底层连接或者在守护连接已经关闭的情况下继续使用它).请谨慎使用,并且仅当需要直接访问驱动的特定功能时使用.注意: 不要关闭底层连接, 只能关闭前面的那个. 
removeAbandoned   false   标记是否删除泄露的连接,如果他们超过了removeAbandonedTimout的限制.如果设置为 true, 连接被认为是被泄露并且可以被删除,如果空闲时间超过removeAbandonedTimeout. 设置为 true 可以为写法糟糕的没有关闭连接的程序修复数据库连接.
removeAbandonedTimeout   300 泄露的连接可以被删除的超时值, 单位秒
logAbandoned   false   标记当 Statement 或连接被泄露时是否打印程序的 stack traces 日志。被泄露的 Statements 和连接的日志添加在每个连接打开或者生成新的 Statement,因为需要生成stack trace。
abandonedUsageTracking false   如果为 true, 那么连接池会记录每个方法调用时候的堆栈信息以及废弃连接的调试信息

1、注意:如果在某些负载比较大的系统中将 maxIdel 设置过小时,很可能会出现连接关闭的同时新连接马上打开的情况.这是由于关闭连接的线程比打开的快导致的.所以,对于这种系统中,maxIdle 的设定值是不同的但是通常首选默认值。

2、注:如果开启"removeAbandoned",那么连接在被认为泄露时可能被池回收. 这个机制在(getNumIdle() < 2)and (getNumActive() > getMaxActive() - 3)时被触发. 举例当maxActive=20, 活动连接为 18,空闲连接为 1 时可以触发"removeAbandoned".但是活动连接只有在没有被使用的时间超过"removeAbandonedTimeout"时才被删除,默认 300 秒.在resultset 中游历不被计算为被使用.

C3P0 属性说明表

属性(Parameter) 默认值(Default) 描述(Description)
user   同 DBCP 中的 username 属性
password   同 DBCP 中的 password 属性
jdbcUrl   同 DBCP 中的 jdbcUrl 属性
driverClass   同 DBCP 中的 driverClass 属性
autoCommitOnClose  false   默认值 false 表示回滚任何未提交的任务,设置为 true 则全部提交,而不是在关闭连接之前回滚.*参见 DBCP 中的 defaultAutoCommit 属性
initialPoolSize   3 初始化连接:连接池启动时创建的初始化连接数量*参见 DBCP 中的 initialSize 属性
maxPoolSize   15 连接池中保留的最大连接数 *参见DBCP 中的 maxIdle 属性
minPoolSize 3  连接池中保留的最小连接数*参见DBCP 中的 maxIdle 属性
maxIdleTime 0 最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以秒计数),超过时间则抛出异常,如果设置为 0 表示无限等待
preferredTestQuery   null 定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。注意:测试的表必须在初始数据源的时候就存在。
testConnectionOn-Checkin false   如果设为 true 那么在取得连接的同时将校验连接的有效性。
testConnectionOn-Checkout false   如果设为true那么在每个connection提交的时候都将校验其有效性,但是要确保配置的preferredTestQuery 的有效性
idleConnectionTest-Period 0 如果设置大于 0,表示过了多少秒检查一次空闲连接,结合 testConnectionOnCheckin 以及testConnectionOnCheckout 使用
acquireRetryAttempts  30 定义在从数据库获取新连接失败后重复尝试的次数, 如果小于 0 则表示无限制的连接。
acquireRetryDelay   1000 两次连接中的间隔时间,单位毫秒。
breakAfterAcquire-Failure false   获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。 但是数据源仍有效保留,并在下次调用 getConnection() 的时候继续尝试获取连接。如果为 true,那么在尝试获取连接失败后该数据源将声明已断开并永久关闭。
checkoutTimeout   0 当连接池用完时客户端调用 getConnection()后等待获取新连接的时间,潮湿后将抛出 SQLException,如设为 0,则为无限期等待。单位毫秒。
maxStatements   0 控制数据源内加载的 PreparedStatements数量
maxStatementsPer-Connection 0 定义了连接池内单个连接所拥有的最大缓存statements 数

DRUID 属性说明表

属性(Parameter) 默认值(Default) 描述(Description)
username     连接数据库的用户名
password   连接数据库的密码
jdbcUrl     同 DBCP 中的 jdbcUrl 属性
driverClassName    根据 url 自动识别,这一项可配可不配,如果不配置 druid 会根据 url 自动识别 dbType, 然后选择相应的 driverClassName.
initialSize   0 初始化时建立物理连接的个数。初始化发生在显示调用 init 方法,或者第一次getConnection 时 *参见DBCP 中的 initialSize 属性
maxActive 8 最大连接池数量
maxIdle   8 已经不再使用,配置了也没效果
minIdle     最小连接池数量
maxWait     获取连接时最大等待时间,单位毫秒。配置了 maxWait 之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置 useUnfairLock 属性为 true 使用非公平锁。
poolPreparedState-ments false   是否缓存 preparedStatement,也就是PSCache。 PSCache 对支持游标的数据库性能提升巨大,比如说 oracle。
maxOpenPrepared-Statements -1 要启用 PSCache,必须配置大于 0,当大于 0 时,poolPreparedStatements 自动触发修改为 true。 在 Druid 中,不会存在 Oracle 下 PSCache 占用内存过多的问题,可以把这个数值配置大一些,比如说 100
testOnBorrow   true   申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
testOnReturn   false   归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
testWhileIdle   false   建议配置为 true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis, 执行validationQuery 检测连接是否有效。
validationQuery     用来检测连接是否有效的 sql, 要求是一个查询语句。 如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle 都不会其作用。在 mysql中通常为 select 'x',在 oracle 中通常为 select 1 from dual
timeBetweenEviction-RunsMillis   1) Destroy 线程会检测连接的间隔时间 2) testWhileIdle 的判断依据
minEvictableIdle- TimeMillis  

Destory 线程中如果检测到当前连接的最后活跃时间和当前时间的差值大于minEvictableIdleTimeMillis,则关闭当前连接。

removeAbandoned    对于建立时间超过removeAbandonedTimeout 的连接强制关闭
removeAbandoned-Timeout   指定连接建立多长时间就需要被强制关闭
logAbandoned false   指定发生 removeabandoned 的时候,是否记录当前线程的堆栈信息到日志中
filters     属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有: 1)监控统计用的 filter:stat 2)日志用的filter:log4j 3)防御 sql 注入的filter:wall

转载于:https://my.oschina.net/wuminghai/blog/833977

【张小平工作日志】DBCP、c3p0、Druid、Proxool数据库连接池比较相关推荐

  1. c3p0、dbcp、druid三大连接池对比

    转: c3p0.dbcp.druid三大连接池对比 转载于:https://www.cnblogs.com/littlelazy/p/10480552.html

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

    连接池及Druid(德鲁伊) 数据库连接池 一.数据库连接池 数据库连接池负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个:释放空闲时间超过最大空闲时间 ...

  3. proxool数据库连接池用法

    今天给大家介绍一种新的数据连接池实现方式--proxool数据库连接池,这是一个健壮.易用的连接池.以下通过一个Demo说明一下怎样使用: 项目结构例如以下: DBLink.java文件里的代码: p ...

  4. Druid:数据库连接池实现技术

    Druid:数据库连接池实现技术,由阿里巴巴提供的 1. 步骤:         1. 导入jar包 druid-1.0.9.jar         2. 定义配置文件:             * ...

  5. Druid:数据库连接池实现技术,由阿里巴巴提供的

    Druid:数据库连接池实现技术,由阿里巴巴提供的         1. 步骤:             1. 导入jar包 druid-1.0.9.jar             2. 定义配置文件 ...

  6. Druid:数据库连接池实现技术 1

    5 Druid:数据库连接池实现技术,由阿里巴巴提供* 步骤:1.导入jar包 druid-1.0.9.jar mysql-connector-java-8.0.22.jar2.定义配置文件:* 是p ...

  7. java连接池 dbcp 样例_DBCP数据库连接池的简单使用

    0.DBCP简介 DBCP(DataBase connection pool)数据库连接池是 apache 上的一个Java连接池项目.DBCP通过连接池预先同数据库建立一些连接放在内存中(即连接池中 ...

  8. javaweb mysql 连接池 c3p0 配置_javaWeb_JDBC_c3p0数据库连接池

    JDBC_c3p0数据库连接池 1.一个基本的c3p0数据库连接池 /** * 一个基本的从池c3p0数据库连接池 */ public static void testC3P0() throws Ex ...

  9. 【张小平工作日志】同一目录下,Maven resource使用include与exclude实现过滤

    <include>与<exclude>是用来圈定和排除某一文件目录下的文件是否是工程资源的. 如果<include>与<exclude>划定的范围存在冲 ...

最新文章

  1. Mirosoft Office自动化问题
  2. spring 的jar包解释
  3. 本地搭建Dubbo监控中心的安装步骤
  4. 项目架构开发:数据访问层之Cache
  5. 立足于飞秋和即时通讯软件市场
  6. 【Java】深入理解Java虚拟机的读书笔记
  7. 《设计模式详解》结构型模式 - 适配器模式
  8. Base64、Blob、File 三种类型的相互转换 最详细
  9. 精准测试系列产品白皮书2020版
  10. mysql统计字数_使用SQL确定文本字段的字数统计
  11. 计算机专业自考本需要学哪几门,自考本科都考哪些科目?一次考几门?
  12. 韩语零基础快速掌握韩语学习的小技…
  13. Longhorn 云原生容器分布式存储 - Air Gap 安装
  14. magic3是鸿蒙系统吗,如果荣耀Magic3搭载屏下镜头和鸿蒙系统,你会做第一批吗?...
  15. 梅科尔工作室-华为云ModelArts的简单使用(附详细图解)
  16. Tekton 的供应链安全工具 Chains
  17. 金山办公和金山软件是同一家公司?复盘金山办公成长史 | 云计算
  18. 新西兰访问学者的签证材料
  19. 连续分配管理方式的动态分区分配算法(首次适应、最佳适应、最坏适应、邻接适应算法)
  20. [医疗信息化][DICOM教程]开篇介绍,新冠肺炎为医疗保健信息产业带来新的的紧迫性...

热门文章

  1. PhpExcel读取Excel表格中的数据
  2. 一文读懂供应链金融及其衍生产品
  3. 安卓数据转移到iphone老是中断_如何把安卓手机上的数据转移到 iPhone、iPad?
  4. 数据库实验第五周【数据查询】
  5. springboot汽车配件销售系统-预约洗车系统java
  6. Python应用开发
  7. 推荐一款手机Python编程软件
  8. Facebook数据中心实践分析,OCP主要工作成果介绍
  9. 利用Webbrowser类实现超长网页的截屏的实现(解决报错不能截取的难题)
  10. 哈夫曼编码--英语文章的编码译码(c/c++)