本篇介紹幾種開源數據庫連接池,同時重點講述如何使用Tomcat服務器內置的數據庫連接池。
之前的博客已經重點講述了使用數據庫連接池的好處,即是將多次創建連接轉變為一次創建而使用長連接模式。這樣能減少數據庫創建連接的消耗。正是由於數據庫連接池的思想非常重要,所以市面上也有很多開源的數據庫連接池供我們使用。主要有以下三個:
DBCP數據庫連接池
C3P0 數據庫連接池
Tomcat內置的數據庫連接池(DBCP)
本篇主要講述C3P0數據庫連接池的使用,關於另外兩個數據庫連接池的用法請看《開源數據庫連接池之DBCP》 、《開源數據庫連接池之C3P0》 。如果我們使用這些開源的數據庫連接池,我們就可以省略像前一篇博客中自己創建數據庫連接池的步驟,這樣會省略我們很多事。
Tomcat服務器也內置了一個數據庫連接池,當然這個數據庫連接池其實也是一個DBCP數據庫連接池。為什么?因為Tomcat和DBCP都是Apache公司的產品。
JNDI技術簡單介紹
在學習Tomcat內置的連接池之前,我們先來認識下JNDI技術。
JNDI(Java Naming and Directory Interface),Java命名和目錄接口,其對應於J2SE中的javax.naming包。
這個JNDI的作用在於,可以將一個Java對象放在容器(JNDI容器)中,並為存儲的這個對象取一個名稱,如果某個程序的方法要想獲得這個對象,則使用JNDI並通過存儲的名稱檢索即可獲得。例如這個JNDI接口定義了Context接口,這是命名服務執行查詢的入口,其lookup方法則為檢索JNDI容器中的對象。對於Context來說,又代表了一個web應用,后面我們就會知道這兩者的羈絆了。
Tomcat內置的數據庫連接池
使用Tomcat服務器內置的數據庫連接池的局限在於,一是這個工程必須是web工程,而不能是一般的Java工程;二是我們必須在服務器啟用之前就要將數據庫連接池配置好,這就要看情況了,如果我們在啟用Tomcat之前沒配置數據庫連接池的話,那么后面的web應用一般也就不會使用內置的數據庫連接池了,畢竟一般服務器不會隨便停用。其實要想使用Tomcat內置的數據庫連接池,也很簡單,就將數據庫的驅動jar包(例如mysql-connector-java-5.1.37.jar)放置在Tomcat的【lib】目錄下。
有了數據庫驅動后,接下來就是如何配置連接池的參數了,因為是要使用Tomcat服務器,因此這個配置也會和服務器相關。我們先來看看一段簡單地配置參數代碼:
這是一段相當於是設置Tomcat內置連接池的配置文件內容(當然作為示例參數沒有設置太多),其中開頭以<context>標簽以及name和docBase屬性是否十分熟悉?是的,我們在《Tomcat詳細用法學習(二)》 和 《Tomcat詳細用法學習(四)》 中都已經介紹過了,這個<context>標簽在<Host>標簽下,<Host>標簽代表在服務器中設置的哪個虛擬主機,而<context>標簽代表在某個虛擬主機下的某個具體的web應用,name屬性指定這個web應用的名稱,docBase屬性指定該web應用的所在具體路徑。也就是說如果我們要配置Tomcat連接池可以在server.xml文件中配置相應的連接池參數。
當然我們們在《Tomcat詳細用法學習(二)》說過,盡量不要在Tomcat的【conf】目錄中的server.xml文件中配置上面的<context>標簽,因為每次配置都要重啟服務器。當然也可以在Tomcat目錄下【conf】-->【Catalina】-->【localhost】目錄中,自建一個xml文件,再在里面寫<context>標簽內容,將上面圖中的內容寫進去,這也是《Tomcat詳細用法學習(二)》提到過的。但這里我們任然不用這種要去服務器目錄下設置的方法,我們最好的選擇是在web應用中就能配置好自己的連接池參數。
那么最終我們使用在MyEclipse中創建web工程中的【WebRoot】下的【META-INF】目錄里創建各自web的Tomcat內置連接池配置文件,並且這個文件必須命名為“context.xml”。
其實在Tomcat服務器的文檔中就介紹了對於context的幾種配置方式,這點在《Tomcat詳細用法學習(二)》中介紹了,對於這次我們采用的方式Tomcat文檔是這么介紹的:
也就是說我們在自己的web工程下的【META-INF】目錄中創建一個“context.xml”文件,當web工程部署到Tomcat服務器時,服務器就會自動將這個“context.xml”配置文件復制到Tomcat目錄下【conf】-->【Catalina】-->【localhost】目錄下,同時將該文件重命名為以web工程名.xml的方式,就跟我們上面說的第二種方式一樣。但這次我們無需再到Tomcat服務器下去創建xml文件,而是通過在自己應用下創建服務器會自動將我們的xml文件復制過去。
好了,我們已經說完了使用Tomcat內置連接池應該如何創建配置文件,配置文件的內容和配置文件應該放置的位置,現在就是如何使用的問題,我們之前說過JNDI定義了Context接口,是命名服務執行查詢的入口,而這個接口的名字正好不就是我們要配置連接池參數的<context>元素嗎,所以這里就說明了Tomcat內置連接池是要通過JNDI容器來檢索的,而通過<Resource>元素的“name”屬性作為在JNDI容器里檢索的關鍵字。
Tomcat文檔中也詳細說明了如何使用內置的連接池:
注意是點擊User Guide的第8點“JNDI Resources”而不是第9點。在“JNDI Resources”中詳細介紹了JDBC Data sources:
例:根據上面的知識來簡單地創建和使用Tomcat內置數據庫連接池
首先在Tomcat目錄中的【lib】目錄下放入我們的數據庫驅動jar包,這里我們使用的是MySQL數據庫:
如果沒有這一步最后程序將會拋出未找到com.mysql.jdbc.Driver的異常。
接着創建一個WEB工程,這里我們命名為“JdbcTomcatPool”,我們使用MySQL數據庫中自定義的一個庫,這個庫我們命名為“jdbcdemo”。創建完web工程,那么在該工程的【META-INF】目錄下創建一個“context.xml”文件:
配置文件中的內容如下:
<Context>
<Resource name="tomcatpool" auth="Container" type="javax.sql.DataSource" username="root" password="root" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/jdbcdemo" initialSize="10" maxActive="20" maxIdle="4"/>
</Context>
這里<Resource>元素的name屬性即為我們使用JNDI去檢索的關鍵字,在本例中為“tomcatpool”。其他的參數都是配置連接池的設置,我們可以查看DBCP的參數(之前說過DBCP和Tomcat都是Apache的),也可以在Tomcat的文檔查看JNDI Resources這個點里的JDBC Data sources這個文檔都有詳細的說明。
接下來我們跟以前的工程一樣,創建一個數據庫工具類JdbcUtils來簡化對數據庫的操作,注意,這里我們使用到了處理JNDI檢索的對象:

1 public class JdbcUtils { 2
3 private static DataSource ds = null; 4
5 static{ 6 try{ 7
8 Context initCtx = new InitialContext(); 9 Context envCtx = (Context)initCtx.lookup("java:comp/env"); 10 ds = (DataSource) envCtx.lookup("tomcatpool"); 11 //根據<Resource>元素的name屬性值到JNDI容器中檢索連接池對象
12 }catch (Exception e) { 13 throw new ExceptionInInitializerError(e); 14 } 15 } 16
17 public static Connection getConnection() throws SQLException { 18 return ds.getConnection(); //利用數據源獲取連接
19 } 20
21 public static void release(Connection conn,Statement st,ResultSet rs) { 22 if(rs!=null) { 23 try{ 24 rs.close(); 25 }catch (Exception e) { 26 e.printStackTrace(); 27 } 28 } 29 if(st!=null) { 30 try{ 31 st.close(); 32 }catch (Exception e) { 33 e.printStackTrace(); 34 } 35 } 36 if(conn!=null) { 37 try{ 38 conn.close(); 39 }catch (Exception e) { 40 e.printStackTrace(); 41 } 42 } 43 } 44 }
這個工具類和之前的開源連接池差不多一樣,在獲取連接池和連接都是通過不同開源連接池的對象獲取,而釋放資源的代碼一點都沒有變,因此可以知道在Tomcat內置的連接池依然也是對數據庫直接提供的Connection對象做了close方法的覆寫,那么我們使用一個Servlet來看看Tomcat給我們提供的連接池是什么樣子的:

1 public class TestServlet extends HttpServlet { 2
3 public void doGet(HttpServletRequest request, HttpServletResponse response) 4 throws ServletException, IOException { 5
6 Connection conn = null; 7 Statement st = null; 8 ResultSet rs = null; 9 try{ 10 conn = JdbcUtils.getConnection(); 11 response.getWriter().write(conn.toString()); 12 response.getWriter().write("<br>"); 13 response.getWriter().write(conn.getClass().getName()); 14 }catch (Exception e) { 15 throw new RuntimeException(e); 16 } 17 finally{ 18 JdbcUtils.release(conn, st, rs); 19 } 20 } 21 }
在瀏覽器中查看:
從Tomcat內置的連接池返回給我們的Connection對象來看,確實證實了Tomcat內置的連接池就是DBCP連接池。因此我們是一個WEB工程同時不想用其他的開源連接池的話就可以使用Tomcat的內置數據庫連接池了。