概述:
當應用訪問量比較大時,每次請求都需要從數據庫中獲取鏈接,這樣極其消耗資源,創建的時間也比較長。例如一個網站的訪問量每天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<Connection> list = new LinkedList<Connection>();
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<Connection> 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>
<Resource name="jdbc/EmployeeDB"
auth="Container"
type="javax.sql.DataSource"
username="dbusername"
password="dbpassword"
driverClassName="org.hsql.jdbcDriver"
url="jdbc:HypersonicSQL:database"
maxActive="8"
maxIdle="4"/>
</Context
代碼: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();