我们通常用jdbc连接数据库,频繁的建立建立连接,关闭资源是非常耗费资源,因此我们就想到了建立一个连接池,先在池中预存一些连接,我们需要时就从连接池中取用,用完之后不是关闭资源连接,而是放回去。
首先是大体项目结构,这里我没有在dao包中写SQL操作,为了方便我写在了测试类中,实际开发是需要提取出来的。
自定义连接池:
创建ConfigManager类,这个类是专门用来读取配置文件信息的。因为配置文件读取一次就行了,因此就将该类设计为单例模式,里面定义了两个方法,整个类是这样写的:
public class ConfigManager {
//这个类就是读取配置文件的
Properties prop=new Properties();
private static ConfigManager configManager;
private ConfigManager(){
//读配置文件,用流的方式
InputStream is = ConfigManager.class.getClassLoader().getResourceAsStream("database.properties");
try {
prop.load(is);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static ConfigManager getInstance(){
if (configManager==null) {
configManager=new ConfigManager();
}
return configManager;
}
public String getValue(String key){
return prop.getProperty(key);
}
}
创建JDBCUtil类,该类可以获得连接
public class JDBCUtil {
//获取连接
public static Connection getConnection() throws ClassNotFoundException, SQLException{
ConfigManager it = ConfigManager.getInstance();
String driver = it.getValue("driver");
String url=it.getValue("url");
String username = it.getValue("username");
String password = it.getValue("password");
Class.forName(driver);
Connection conn=DriverManager.getConnection(url,username,password);
return conn;
}
}
创建连接池类MyconnectionPool,将池子的初始容量设为5,每次三个三个的扩容。
public class MyConnectionPool {
//模拟连接池
public static LinkedList<Connection>list=new LinkedList<Connection>();
//初始化连接池,往连接池里放五个连接
static {
for (int i = 0; i < 5; i++) {
Connection conn;
try {
conn = JDBCUtil.getConnection();
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 Connection getConnection() throws ClassNotFoundException, SQLException{
if (list.isEmpty()) {
for (int i = 0; i < 3; i++) {
Connection conn = JDBCUtil.getConnection();
list.add(conn);
}
}
return list.removeFirst();
}
//关闭,以前我们是关闭资源,现在我们需要把资源(连接)放回连接池中
public void addback(Connection conn){
list.addFirst(conn);
}
}
准备工作已经完成,编写测试类测试,
public class Test {
@org.junit.Test
public void test() {
//测试自定义连接池
Connection conn=null;
try {
conn = MyConnectionPool.getConnection();
String sql="select * from news_user where id=?";
PreparedStatement prpt = conn.prepareStatement(sql);
prpt.setInt(1, 2);
ResultSet rs = prpt.executeQuery();
if (rs.next()) {
String str=rs.getString("username");
System.out.println(str);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("前"+MyConnectionPool.list.size());
MyConnectionPool.addback(conn);
System.out.println("后"+MyConnectionPool.list.size());
}
}
运行结果如下,通过输出连接池长度我们可以看出,我们确实可以从自定义的连接池中取出连接,并且可以将连接归还到池中。
最后,这里还有一个问题,就是我们自定义了一个addback方法用于归还连接,我们习惯用Connection接口的close方法关闭资源,自定义方法会增加程序员的记忆量,因此我们想到能不能调用close方法就能实现归还连接而不是原本的关闭资源呢?
这里使用装饰者模式实现,笔者就不再赘述了。