0 前提:
数据库连接是很宝贵的资源,每一次初始化一个连接时都耗时较长,如果网站访问量较大,并不做优化前提下,很容易造成数据库服务器内存溢出,导致宕机。
1 数据库连接池:
结构如下图:
2 java提供类来让开发人员自定义实现数据库连接池: (一般都是用开源的数据库连接池)
2.0 自己编写连接池大概流程:
编写连接池需实现java.sql.DataSource接口。DataSource接口中定义了两个重载的getConnection方法:
Connection getConnection()
Connection getConnection(String username, String password)
开发的流程: 一次性从数据库中获取X个conn,然后将原始的conn(Connection)动态代理,然后将这些个conn放如到linkedlist保存,每次获取conn时去list获取,当在业务逻辑代码中执行释放资源时,将使用的动态代理的close将conn返回到list中。
其中对connection动态代理后代码如下:
public Connection getConnection() throws SQLException { // 这就是使用动态代理技术构建除了conn返回出去了
if(connections.size()>0){
final Connection conn = connections.removeFirst();
System.out.println(conn + "从连接池里面取出来了!!,池大小为:" + connections.size());
//第三个参数表示返回的代理对象干什么事情
/*
*Proxy --JDK提供的这个类 可以构建成某一接口的 代理对象
* 调用方法 newProxyInstance(当前类的类加载器, 给的是那个类的接口那么返回的就是这个类的代理对象, 返回的是代理对象要干的事情,事情是通过对象来指定的);
*/
return (Connection)Proxy.newProxyInstance(JdbcPool.class.getClassLoader(),conn.getClass().getInterfaces(), new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equals("close")){
connections.addLast(conn);
System.out.println(conn + "被还到池里了!!,池大小为:" + connections.size());
}else{// 如果不是调用conn的close方法而是调用conn的其他方法那么我就调用mysql的conn把其他事情给干了
return method.invoke(conn, args);
}
return null;
}
});
}else{
throw new RuntimeException("服务器繁忙,请过会再来!!");
}
}
2.1 市场上开源的连接池介绍(原理都是 1 维护X个数据库连接资源conn 2对原始conn实现动态代理,主要涉及两块 执行close时将conn返回到list 执行别的方法时交由原始conn执行):
一些开源组织提供了数据源(数据库连接池+技术实现)的独立实现,实际应用时不需要编写连接数据库代码
a) DBCP 数据库连接池,
需要jarCommons-dbcp.jar:连接池的实现 Commons-pool.jar:连接池实现的依赖库
配置文件:
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc3
username=root
password=root
#<!-- 初始化连接 -->
initialSize=5
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
b) C3P0 数据库连接池
需要的jar : c3p0-0.9.1.2.jar
关于这两个数据源的读取写法,需要的JAR,配置文件 见附件: db_super.rar