概述:
当应用访问量比较大时,每次请求都需要从数据库中获取链接,这样极其消耗资源,创建的时间也比较长。例如一个网站的访问量每天10W,就得创建10W次连接。
这时就可以用连接池。
连接池需要实现javax.sql.DataSource接口,实现她的两个方法:
getConnection();
getConnection(String user,String password);
1. 实现DataSource接口
2. 定义一个List类型的成员变量,用来存放Connection。因为存取的操作频繁,所以这里用LinkedList集合。
3. 定义一个成员变量:初始连接数。
4. 在静态代码块中,循环生成 多个连接。
5. 实现getConnection方法,作一个判断:list>0代表里面还有连接,否则抛异常“连接不够”。
6. 在作连接池中,最麻烦的一步就是close关闭。因为我们并不是要把连接关闭,而是把连接又放回list中。
(当要对一个对象的功能进行增强时,有三种方法:1.写一个子类继承被增强的类。2. 用包装设计模式。3.用动态代理的方式)
private static LinkedList list = new LinkedList();
static {
ResourceBundle rb = ResourceBundle.getBundle("db");
String url = rb.getString("url");
String drive = rb.getString("drive");
String username = rb.getString("username");
String password = rb.getString("password");
try {
Class.forName(drive);
for (int x = 0; x < 10; x++) {
Connection conn = DriverManager.getConnection(url, username,
password);
list.add(conn);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static LinkedList getList() {
return list;
}
@Override
public Connection getConnection() throws SQLException {
if (list.size() > 0) {
final Connection conn = list.removeFirst();
//用装饰设计模式实现:重写他的close方法。其它的方法都调用其自身的方法。
// MyConnection myconn = new MyConnection(conn, list);
// return myconn;
//用动态代理的方式实现
return (Connection) Proxy.newProxyInstance(conn.getClass()
.getClassLoader(), conn.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
String methodName = method.getName();
if (!methodName.equals("close")) {
return method.invoke(conn, args);
} else {
list.add(conn);
return null;
}
}
});
} else {
throw new RuntimeException("对不起!服务器正忙");
}
1. 写一个类实现与被增强类的接口。
2. 在类中定义一个变量,记住被增强的对象。
3. 定义一个构造方法,接收被增强对象。
4. 覆盖被增强的方法。
5. 对不想被增强的方法,可以直接调用被增强的对象(目标对象)的方法。
适配器设计模式:
理解:当我们自己的多个类或别人写的类实现一个接口时,而这个接口中定义了N个方法。我们不需要每个实现他的类都去覆盖他的方法。只需要做一个类去实现他的所有方法。而其它类继承这个类,覆盖所需的方法即可。而这个类就是适配器类。这种方法叫适配器设计模式。
开源连接池:DBCP
1. 导入commons-dbcp-*.jar commons-pool.jar包
2. 修改配置文件
代码如下:
public class JdbcUtils {
private static DataSource ds;
static {
try {
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dbcp.properties");
Properties props = new Properties();
props.load(in);
ds = BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
throw new ExceptionInInitializerError("初始化异常");
}
}
public static Connection getConnection() {
try {
return ds.getConnection();
} catch (SQLException e) {
throw new ExceptionInInitializerError(e);
}
}
}
开源连接池:P3C0
1. 导入c3p0-0.9.1.2.jar,c3p0-0.9.1.2-jdk1.3.jar,c3p0-oracle-thin-extras-0.9.1.2.jar(可选,如果是oracle)
2. 复制配置文件至classPath环境下,或者classes目录下。
代码:
public class JdbcUtils {
private static ComboPooledDataSource cpds;
static {
try {
cpds = new ComboPooledDataSource("mysql");
} catch (Exception e) {
throw new ExceptionInInitializerError("初始化异常");
}
}
public static Connection getConnection() {
try {
return cpds.getConnection();
} catch (SQLException e) {
throw new ExceptionInInitializerError(e);
}
}
}
JNDI容器:J2EE开发13种技术之一。用于存放资源,例如:当多个程序之间的数据传递时,可以先把数据写到JNDI容器中,然后哪个程序需要就去JNDI容器里取出。
Tomcat数据源配置
在Tomcat启动时建立,将配置信息写到context.xml文件中,放在META-INF目录下。
代码:
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource)
envCtx.lookup("jdbc/EmployeeDB");
Connection conn = ds.getConnection();
... use this connection to access the database ...
conn.close();