近年来,随着Internet/Intranet建网技术的飞速发展和在世界范围内的迅速普及,计算机
应用程序已从传统的桌面应用转到Web应用。基于B/S(Browser/Server)架构的3层开发模式逐渐取代C/S(Client/Server)架构的开发模式,成为开发企业级应用和电子商务普遍采用的技术。
在Java语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁,
即Java语言通过JDBC技术访问数据库。JDBC是一种“开放”的方案,它为数据库应用开发人员﹑数据库前台工具开发人员提供了一种标准的应用程序设计接口,使开发人员可以用纯Java语言编写完整的数据库应用程序。JDBC提供两种API,分别是面向开发人员的API和面向底层的JDBC驱动程序API,底层主要通过直接的JDBC驱动和JDBC-ODBC桥驱动实现与数据库的连接。
一般来说,Java应用程序访问数据库的过程是:
①装载数据库驱动程序;
②通过JDBC建立数据库连接;
③访问数据库,执行SQL语句;
④断开数据库连接。
JDBC作为一种数据库访问技术,具有简单易用的优点。但使用这种模式进行Web应用
程序开发,存在很多问题:首先,每一次Web请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费0.05s~1s的时间,而且系统还要分配内存资源。这个时间对于一次或几次数据库操作,或许感觉不出系统有多大的开销。可是对于现在的Web应用,尤其是大型电子商务网站,同时有几百人甚至几千人在线是很正常的事。在这种情况下,频繁的进行数据库连接操作势必占用很多的系统资源,网站的响应速度必定下降,严重的甚至会造成服务器的崩溃。不是危言耸听,这就是制约某些电子商务网站发展的技术瓶颈问题。其次,对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将不得不重启数据库。还有,这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。
由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理。我们知道,
对于共享资源,有一个很著名的设计模式:资源池(Resource Pool)。该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。
dbcp数据库连接池代码使用如下:
package util; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import org.apache.commons.dbcp.BasicDataSource; import org.apache.log4j.Logger; /** * Description: 数据库连接池类 * @filename DataSourceFactory.java * @date 2013年8月21日 19:47:21 * @author Herman.Xiong * @version 1.0 * Copyright (c) 2013 Company,Inc. All Rights Reserved. */ public class DataSourceFactory { private static Logger log = Logger.getLogger(DataSourceFactory.class); private static BasicDataSource bs = null; public static String driver,url,userName,password; /** * 创建数据源 * @return */ public static BasicDataSource getDataSource() throws Exception{ if(bs==null){ log.info("数据库连接信息:[driver:"+driver+",url:"+url+",userName:"+userName+",password:"+password+"]"); bs = new BasicDataSource(); bs.setDriverClassName(driver); bs.setUrl(url); bs.setUsername(userName); bs.setPassword(password); bs.setMaxActive(200);//设置最大并发数 bs.setInitialSize(30);//数据库初始化时,创建的连接个数 bs.setMinIdle(50);//最小空闲连接数 bs.setMaxIdle(200);//数据库最大连接数 bs.setMaxWait(1000); bs.setMinEvictableIdleTimeMillis(60*1000);//空闲连接60秒中后释放 bs.setTimeBetweenEvictionRunsMillis(5*60*1000);//5分钟检测一次是否有死掉的线程 bs.setTestOnBorrow(true); } return bs; } /** * 释放数据源 */ public static void shutDownDataSource() throws Exception{ if(bs!=null){ bs.close(); } } /** * 获取数据库连接 * @return */ public static Connection getConnection(){ Connection con=null; try { if(bs!=null){ con=bs.getConnection(); }else{ con=getDataSource().getConnection(); } } catch (Exception e) { log.error(e.getMessage(), e); } return con; } /** * 关闭连接 */ public static void closeCon(ResultSet rs,PreparedStatement ps,Connection con){ if(rs!=null){ try { rs.close(); } catch (Exception e) { log.error("关闭结果集ResultSet异常!"+e.getMessage(), e); } } if(ps!=null){ try { ps.close(); } catch (Exception e) { log.error("预编译SQL语句对象PreparedStatement关闭异常!"+e.getMessage(), e); } } if(con!=null){ try { con.close(); } catch (Exception e) { log.error("关闭连接对象Connection异常!"+e.getMessage(), e); } } } }