数据库连接池(JSP)

一、为什么使用数据库连接池

       用户每次请求都需要向数据库获得连接,而数据库创建连接通常要消耗相对较大的资源,创建时间也长。假设网站一天10万的访问量,数据库服务器就需要创建10万次连接,极大浪费数据库的资源,并且极易造成数据库服务器内存溢出、宕机。连接池工作原理图:

 

             应用程序一开始就向数据库要了一批连接构成连接池,用户访问 Servlet,Servlet 向 Dao 要数据,此时 Dao 层不是直接向数据库要连接,而是向连接池中拿一个空闲的连接。当 Dao 用完连接以后,将连接还给连接池。

 

二、编写数据库连接池

       1、编写连接池需要实现 java.sql.DataSource 接口。DataSource 接口中定义了两个重载的 getConnection 方法:

              Connection.getConnection();

              Connection.getConnection(String username, String password);

         2、实现 DataSource 接口并实现连接池功能的步骤:

              在 DataSource 构造函数中批量创建与数据库的连接,并把创建连接加入到 LinkedList 对象中。实现 getConnection 方法,让 getConnection 方法每次调用时,从 LinkedList 中取一个 Connection 返回给用户。当用户使用完 Connection 对象应保证将连接返回到 LinkedList 中,而不是还给数据库。

 

              在自己编写数据库连接池时,我们要考虑到,从数据库获取连接的时候容易,但是当用户用完连接,调用 connection.close() 方法的时候,会直接将连接交还给数据库而不是再放回连接池中。所以我们要动态的改变 connection 方法。有三种方式可以实现 (1)写一个 connection 的子类,复写所有方法。但是这种方法有一个问题,因为 connection 对象中封装了太多数据,我们如何将 connection 的数据拷贝到我们当前的子类中呢?这是一个复杂的过程。(2)用装饰模式,装饰模式可以动态的为一个类增加新功能。装饰模式有几个步骤,首先装饰类和被装饰类要有一个共同的父接口,其次装饰类中维护着一个被装饰类的对象,同时在装饰类的构造函数中要将被装饰的对象传进来,目的是赋值。然后我们可以为根据需求增加修改原来的功能。当我们要使用被装饰类的时候,我们给用户返回的是我们装饰后的对象,  从而达到目的。但是装饰模式比较适用于简单类,不适合用于方法多的对象,因为我们有时仅仅需要修改一部分功能,而其它功能还是希望调用被装饰类本身的方法,那么这样我们就必须一个一个方法进行修改,来调用被装饰类的方法,这个工程非常庞大。(3)使用动态代理,动态代理可以实现拦截对对象的直接访问。如果我们想修改某一个方法,只需要在调用对象之前进行判断即可,如果是我们想修改的,我们直接拦截,如果不是我们想要的,我们可以直接交给被代理对象处理。由于动态代理是基于代理对象和被代理对象要有相同接口,所以我们可以基于接口统一调用,运行时以多态的形式表现出来。

 

  1. public class DataSourcePool {  
  2.   
  3.     private static LinkedList<Connection> list = new LinkedList<Connection>();  
  4.   
  5.     static {  
  6.         for (int i = 0; i < 5; i++) {  
  7.             Connection con = DBHelper.getConnection();  
  8.             list.add(con);  
  9.         }  
  10.     }  
  11.   
  12.     public Connection getConnection() throws SQLException {  
  13.         if (list.size() > 0) {  
  14.             System.out.println("当前连接池有:" + list.size() + "个连接");  
  15.             final Connection con = list.removeFirst();  
  16.             System.out.println("当前连接池有:" + list.size() + "个连接");  
  17.             return (Connection) Proxy.newProxyInstance(DataSourcePool.class.getClassLoader(), con.getClass().getInterfaces(), new InvocationHandler() {  
  18.   
  19.                 public Object invoke(Object proxy, Method method, Object[] args)  
  20.                         throws Throwable {  
  21.                     String methodName = method.getName();  
  22.                     if(methodName.equals("close")){  
  23.                         list.add(con);  
  24.                         System.out.println("当前连接池有:" + list.size() + "个连接");  
  25.                         return null;  
  26.                     }else{  
  27.                         return method.invoke(con, args);  
  28.                     }  
  29.                 }  
  30.   
  31.             });  
  32.         }  
  33.         return null;  
  34.     }  
  35. }  

 

三、开源数据库连接池

       现在很多 Web 服务器都提供了 DataSource 的实现,即连接池的实现,通常我们把 DataSource 的实现按英文含义称之为数据源。也有一些开源组织提供了数据源的独立实现:DBCP、C3P0、apache dbcp,Tomcat 内置的 dbcp 也就是 DBCP。

 

          1、DBCP

               DBCP 是 Apache 软件组织下的开源连接池,使用 DBCP 数据源,应用程序应在系统中增加两个 jar 包:Commons-dbcp.jar(连接池的实现)、Commons-pool.jar(连接池实现的依赖库),DBCP 连接池既可以与应用服务器整合使用,也可以由应用程序独立使用。

               BasicDataSourceFactory factory = new BasicDataSourceFactory();

               factory.createDateSource(P);

               在创建数据源的时候,DBCP 采用的是读取配置文件的形式,返回一个 DataSrouce。DBCP 是采用装饰模式来创建连接池的。

  1. #连接设置  
  2. driverClassName=com.mysql.jdbc.Driver  
  3. url=jdbc:mysql://localhost:3306/day15  
  4. username=root  
  5. password=root  
  6.   
  7. #<!-- 初始化连接 -->  
  8. initialSize=10  
  9.   
  10. #最大连接数量  
  11. maxActive=50  
  12.   
  13. #<!-- 最大空闲连接 -->  
  14. maxIdle=20  
  15.   
  16. #<!-- 最小空闲连接 -->  
  17. minIdle=5  
  18.   
  19. #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->  
  20. maxWait=60000  


 

        2、c3p0

              c3p0 在创建连接池的时候,可以手动指定连接的方式,也可以通过 xml 和配置文件的形式创建连接池。

              ComboPooledDataSource source = new ComboPooledDataSource("配置名");

 

        3、配置 Tomcat 内置 dbcp 连接池

             Tomcat 采用的是 JNDI 容器存放连接的,在服务器启动的时候,会在 JNDI 容器中创建一批连接,应用程序需要连接的时候直接在 JNDI 容器中查找。我们在使用时首先应该初始化 JNDI ,然后获取 Tomcat 中 JNDI 容器,最后在 JNDI 容器中检索连接池。

  1.                        Context initCtx = new InitialContext();  
  2. Context envCtx = (Context) initCtx.lookup("java:comp/env");  
  3. DataSource source = (DataSource) envCtx.lookup("jdbc/EmployeeDB");  


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值