為什么使用數據源
在帳套配置項中,我們使用數據源來表示對應的數據庫連接。使用數據源有兩個好處:對開發人員屏蔽數據庫細節,只要通過JNDI取得數據源就可以了,無需關心數據庫連接是如何建立的;數據源通常都提供了數據庫連接池的功能。
數據庫連接是一種關鍵的有限的昂貴的資源,而且數據庫連接的建立和關閉也是很耗費系統資源的。在傳統的兩層C/S架構中,一個客戶端對應一個數據庫連接,在用戶活動期間就獨占此連接;而在分布式系統中,數據庫連接的建立與關閉是異常頻繁的,因此數據庫連接的對系統的性能影響更是明顯。對數據庫連接的管理能顯著影響到整個應用程序的伸縮性和健壯性,影響到程序的性能指標。數據庫連接池正是針對這個問題提出來的。
數據庫連接池在初始化時將創建一定數量的數據庫連接放到連接池中,這些數據庫連接的數量是由最小數據庫連接數來設定的。數據庫連接池負責分配、管理和釋放數據庫連接,它允許應用程序重復使用一個現有的數據庫連接,而再不是重新建立一個;釋放空閑時間超過最大空閑時間的數據庫連接來避免因為沒有釋放數據庫連接而引起的數據庫連接遺漏。無論這些數據庫連接是否被使用,連接池都將一直保證至少擁有這么多的連接數量。連接池的最大數據庫連接數量限定了這個連接池能占有的最大連接數,當應用程序向連接池請求的連接數超過最大連接數量時,這些請求將被加入到等待隊列中。
JDBC3.0規范中規定了如下的接口和類來實現數據庫連接池:
javax.sql.ConnectionEvent:連接事件
javax.sql.ConnectionPoolDataSource:連接池數據源
javax.sql.PooledConnection:被池化的連接
javax.sql.ConnectionEventListener:連接事件監聽接口
上邊這些接口和類是對數據庫連接池內部實現的規定,對于使用者來說是透明的。數據庫連接池的使用者一般只和DataSource接口直接打交道,通過這個接口獲得數據庫連接,其主要方法為:
Connection getConnection():得到一個數據庫連接
Connection getConnection(String userName,String password):得到一個數據庫連接
java.io.PrintWriter getLogWriter():獲得Log Writer的對象
void setLogWriter(java.io.PrintWriter out):設置Log Writer
void setLoginTimeout(int seconds):設置數據源嘗試連接數據庫的最大時間
int getLoginTimeout():獲得數據源嘗試連接數據庫的最大時間
開源社區中有很多數據庫連接池的實現,比如PoolMan等,使用這些數據庫連接池包可以保證跨應用服務器的移植。不過在本案例系統中,我們使用應用服務器的數據源功能提供的數據庫連接池。數據源在不同的服務器中有不同的配置方式,下面介紹Tomcat中數據源的配置。
打開%TOMCAT_HOME%\conf\server.xml,在</Context>和</host>前添加如下配置文件項:
<Context docBase="CowNewPIS" path="/CowNewPIS"??????reloadable="true">
<Resource type="javax.sql.DataSource"
??????auth="Container" name="jdbc/PISMSSQL_Dev" />
<ResourceParams name="jdbc/PISMSSQL_Dev">
<parameter>
<name>maxWait</name>
<value>5000</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>4</value>
</parameter>
<parameter>
<name>password</name>
<value></value>
</parameter>
<parameter>
<name>url</name>
<value>
jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=PISDev1106
</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>
com.microsoft.jdbc.sqlserver.SQLServerDriver
????</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>2</value>
</parameter>
<parameter>
<name>username</name>
<value>sa</value>
</parameter>
</ResourceParams>
</Context>
?
在配置的時候,要指定數據庫的JDBC驅動、數據庫連接URL等。數據源配置完畢,重啟服務器。編寫一個測試客戶端:
Context ctx=null;
Connection conn=null;
try
{
ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup("java:comp/env/jdbc/PISMSSQL_Dev");
conn=ds.getConnection();
}
finally
{
if(conn!=null)
conn.close();
if(ctx!=null)
ctx.close();
}
Tomcat啟動的時候會將Server.xml中的數據源配置綁定到JNDI中,我們可以在應用服務器啟動的時候用代碼來代替Tomcat完成綁定:
BasicDataSource bdds = new BasicDataSource();
//設置數據庫驅動
bdds.setDriverClassName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
//設置JDBC的URL
bdds.setUrl("jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=PISDev1106");
bdds.setUsername("sa");
//設置連接池初始大小
bdds.setInitialSize(2);?????
//JNDI配置
Map env = new Hashtable();
env.put("java.naming.factory.initial",
"org.apache.naming.java.javaURLContextFactory");
InitialContext ctx=new InitialContext(env);?????
//數據源綁定到JNDI
ctx.bind("jdbc/PISMSSQL_Dev",bdds);
這樣我們可以把數據源的配置文件移到ServerConfig.xml中,增加類似如下的配置:
<DataSources>
<DataSource
name=”jdbc/PISMSSQL_Dev” driverClassName=”com.microsoft.jdbc.sqlserver.SQLServerDriver”
url=”jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=PISDev1106”
userName=”sa”
>
</DataSource>
</DataSources>
在應用服務器啟動的時候,到ServerConfig.xml中讀取數據源配置完成綁定。這種方式一是減少了實施人員配置文件的工作量,服務端的任何配置都可以在這個配置文件中完成;二是使得系統在不同服務器之間移植變得更加容易。