JavaWeb基础—数据库连接池DBCP、C3P0

一、基本概念

  数据库连接池负责分配、管理和释放数据库连接

  数据库连接池:(池用 map 来实现居多)
  用处:为了可重用(销毁创建麻烦,开销大)(招培训老师的例子)

二、编写实现数据库连接池

  池参数:
    初识大小(招 10 个老师)
    最小空闲连接数(小于 3 个时招人)
    增量(一次创建的最小单位)(一次招 5 个)
    最大空闲连接数(老师数多于 12 时销毁)
    最大连接数(最大就招 20 人,超过也不招人了,等)
    最大等待时间(等的时间太长没人归还就抛异常)

  连接池也是通过四大参数以及相关 jar 包等

  连接池一般不自己实现(那要崩溃,又不稳定)
  使用 commons-dbcp.jar(数据库连接池) 它依赖 commons-pool.jar
  (之前的 io 包,beanutils(依赖 logging.jar 包) 等)commons 被称为第二 API

  连接池必须实现 javax.sql.DataSource 接口(1.4 开始的规范)通常使用无参的构造器
  第三方的包都已经被实现,池参数都有默认值
  但是!四大参数必须自己提供!

  一般地,有两大开源的数据源实现:dbcp c3p0

  步骤:
    获得连接池对象(BasicDataSource)
    设置四大参数
    设置池参数
    得到连接对象(close() 方法是归还,不是销毁)

  1.dbcp 的小 Demo(了解)

package com.commons.dbcptest;

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

import org.apache.commons.dbcp2.BasicDataSource;
import org.junit.Test;

/**

  • 用于测试 commons 的 dbcp 的类
  • @author jiangbei01

/
public class Demo02 {
@Test
public void fun1() throws SQLException{
/

* 得到连接池对象
* 设置四大参数
* 设置池参数
* 得到连接对象
*/
BasicDataSource dataSource
= new BasicDataSource();
dataSource.setDriverClassName(
"com.mysql.jdbc.Driver");
dataSource.setUrl(
"jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername(
"root");
dataSource.setPassword(
"root");
//使用的为默认池参数
Connection con = dataSource.getConnection();
System.out.println(con.getClass().getName());
//把连接归还给池
con.close();
}
}

  2.c3p0 (大多开源项目的支持,JNDI 的实现)

 

  C3P0:
    免费开源的数据库连接池,功能强大,性能优越,【推荐】
    连接需要两个 jar 包(不需要 oracal 那个 jar 包)
  ComboPooledDataSource 为连接池对象,方法步骤与上大同小异!

 

  C3P0 可以有一个配置文件,但配置文件必须满足要求。可以使用使用命名配置
  <named-config name="">
  必须叫 c3p0-config.xml
  必须在 src 下

  具体的配置见下图

  

  配置文件模板
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<!-- 四大参数 -->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/mydb</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<!-- 池参数 -->
<property name="acquireIncrement">3</property>
<property name="initialPoolSize">2</property>
<property name="maxPoolSize">5</property>
<property name="minPoolSize">2</property>
</default-config>
</c3p0-config>
  使用连接池,重写 JdbcUtils(day18)

 这里做出一个简单的重写

  

package cn.itcast.jdbcutils;

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

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class JdbcUtils {
//使用的是默认的配置信息,注意给出 c3p0-config.xml 配置文件
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> Connection getConnection() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> SQLException{
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> dataSource.getConnection();
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
 * 大方一点,给出连接池对象给你
 </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> ComboPooledDataSource getDataSource(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> dataSource;
}

}

三、JNDI

  JNDI(Java Naming and Directory Interface),Java 命名和目录接口,它对应于 J2SE 中的 javax.naming 包,
  这 套 API 的主要作用在于:它可以把 Java 对象放在一个容器中(JNDI 容器),并为容器中的 java 对象取一个名称,以后程序想获得 Java 对象,只需 通过名称检索即可。其核心 API 为 Context,它代表 JNDI 容器,其 lookup 方法为检索容器中对应名称的对象

  

JNDI(Java Naming and Directory Interface,Java 命名和目录接口)
Tomcat 配置数据库连接池(JNDI 的手段来得资源)在 tomcat/conf/catalina/localhost 下创建与项目同名的 xml 配置文件
其它方法见百度

(百度的博客里的另外的方法)

  1、在 Web 项目的 WebRoot 目录下的 META-INF 目录创建一个 context.xml 文件

   2、在 context.xml 文件配置 tomcat 服务器的数据源

 

复制代码
 1 <Context>
 2    <Resource 
 3        name="jdbc/datasource" 
 4        auth="Container"
 5        type="javax.sql.DataSource" 
 6        username="root" 
 7        password="XDP"
 8        driverClassName="com.mysql.jdbc.Driver" 
 9        url="jdbc:mysql://localhost:3306/jdbcstudy"
10        maxActive="8" 
11        maxIdle="4"/>
12 </Context>

 

  3、将数据库的驱动 jar 文件需放置在 tomcat 的 lib 下

  4、在获取数据库连接的工具类 (如 jdbcUtils) 的静态代码块中获取 JNDI 容器中的数据源

  见孤傲苍狼大神的博客:http://www.cnblogs.com/xdp-gacl/p/4002804.html

采用之前的方式

, 小的配置文件示例:
<Context>
<Resource name="jdbc/dataSource" auth="Container"
factory="org.apache.naming.factory.BeanFactory"
type="com.mchange.v2.c3p0.ComboPooledDataSource"/>
</Context>
name: 资源名称,注意命名规范
auth: 可不要
factory: 固定,不要去变
type: 类型,也就是 c3p0 包名
其他的东西都是资源的参数

获取资源的方法
Context iniCtx = new InitialContext();
Context envCtx = (Context)iniCtx.lookup("java:comp/env");// 固定
// 二次查找
//MyBean bean = (MyBean)envCtx.lookup("bean/MyBeanFactory");

writer.println("foo ="+bean.getFoo()+",bar ="+bean.getBar());

例如(注意在项目点 lib 下导包):

package cn.itcast.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
/**

  • 测试 JNDI 获取资源的 Servlet,使用浏览器测试
  • @author jiangbei01

*/
public class AServlet extends HttpServlet {

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> doGet(HttpServletRequest request, HttpServletResponse response) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> ServletException, IOException {
    </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取上下文对象</span>
        Context iniCtx = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> InitialContext();
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">找出入口</span>
        Context envCtx = (Context)iniCtx.lookup("java:comp/env"<span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">二次查找,找到资源,里面的就是资源名</span>
        DataSource dataSource = (DataSource)envCtx.lookup("jdbc/dataSource"<span style="color: rgba(0, 0, 0, 1)">);
        </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">于是就得到连接了,注意导包</span>
        <span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
            Connection con </span>=<span style="color: rgba(0, 0, 0, 1)"> dataSource.getConnection();
            System.out.println(con);
            con.close();
        } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (SQLException e) {
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO Auto-generated catch block</span>

e.printStackTrace();
}

    } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (NamingException e) {
        e.printStackTrace();
    }
}

}