Servlet的JDBC 資料庫連線池
阿新 • • 發佈:2019-02-03
國慶的最後的時候,花了些時間整理下筆記等東東:(一些亂亂的東西)
純servlet的demo中使用的;
JDBC 資料庫連線池:(程式碼測試不能用,不過思路應該是對的,後來改好的 程式碼不對 沒有返回 下面的程式碼是可用的)
首先,需要一個繼承DataSource介面的類,這個就是地址池了;
改寫裡面的Connection getConnection()方法(無參的),這個是用來分配地址的,程式碼可以這麼寫,大概這樣:
publicConnection getConnection()throwsSQLException{
//給執行緒方法連線
synchronized(pool){
if( pool.size()>0){//容器裡有東東
return pool.remove();//給一個出去
}elseif(pool.size()==0&&count<maxPoolSize){
pool.add(createConnection());
return pool.remove();
}else{
//容器沒有連線了,並且連線數已經超過最大值,讓執行緒等。
try{
pool.wait();//讓執行緒等待
}catch(InterruptedException e){
// TODO: handle exception
e.printStackTrace();
}
return pool.remove();
}
}
//return null;
}
這裡的pool就是一個容器,裡面就是連線池咯!
然後,在這個類裡要有建立連線資料庫的方法:Connection createConnection();
不過這裡面的地址(放到地址池裡的是代理過的連線):
//專門建立連線
privateConnection createConnection(){
Connection conn =null;
try{
Class.forName(driverClassName);
conn=DriverManager.getConnection(url, user, password);
//上面是正常的連線!!
//下面是對連線進行代理,為了就是在呼叫close方法時 不呼叫真正的close方法
//而是我們自己寫 的 連線 回收的 方法 程式碼
CloseMethodHandler handler =newCloseMethodHandler(pool);
Connection proxyconnConnection = handler.createProxy(conn);
count=count+1;
//return conn;
return proxyconnConnection;
}catch(Exception e){
e.printStackTrace();
}
returnnull;
}
當然 ,這裡對這個地址池 類的構造方法 還是要寫一下 ,要在構造的時候 先獲得基本的資料 並建立 幾個連線到地址池
privateLinkedList<Connection> pool=newLinkedList<Connection>();
privateString driverClassName;
privateString url;
privateString user;
privateString password;
privateint count=0;//連線計數
publicMyDataSource(int maxPoolSize,int initPoolSize,String driverClassName,String url,String user,String password){
this.initPoolSize=initPoolSize;
this.maxPoolSize=maxPoolSize;
this.driverClassName=driverClassName;
this.url=url;
this.user=user;
this.password=password;
//建立三個連線
for(int i =0; i < initPoolSize; i++){
Connection conn =createConnection();
pool.add(conn);
}
}
這構造方法就沒什麼好說明的 了:
接下來:要建立上面的CloseMethodHandler這個類了,這個類是用來建立
代理的;
也就是,代理原本正真的資料庫連線,以便在其呼叫close方法時,呼叫回收 和 執行緒 喚醒;
這個類必須繼承InvocationHandler這個介面,並重寫invoke(Object proxy, Method method, Object[] args)方法;
這個方法就是用來處理(攔截)代理物件方法使用的;
publicclassCloseMethodHandlerimplementsInvocationHandler{
privateConnection target;
privateLinkedList<Connection> pool;
//構造方法 是因為需要pool物件而建立的
publicCloseMethodHandler(LinkedList<Connection> pool){
this.pool=pool;
}
//target是被代理物件,建立一個代理物件//用來建立一個代理的物件 ,並將引數的真的物件 儲存起來先
/*不過我感覺這裡有問題,對引數的處理不太對的趕腳*/
publicConnection createProxy(Connection target){
System.out.println(target.getClass().getName());
this.target=target;
//這個就是一個建立 代理 的方法 引數 我也弄的不明白 好像是 源物件的例項化的方式 ,代理物件的型別(介面),實現代理的類(就是自己)/*感覺這個也有問題 對引數就是搞不明白*/return(Connection)Proxy.newProxyInstance(target.getClass().getClassLoader(),newClass[]{Connection.class},this);
}
//攔截被代理物件的方法的方法==》攔截Connection物件中close的方法。
publicObject invoke(Object proxy,Method method,Object[] args)
throwsThrowable{
if(method.getName().equals("close")){
//攔截
synchronized(pool){
pool.add((Connection) proxy);
pool.notify();//喚醒等待的執行緒
}
}else{
return method.invoke(target, args);//不攔截 //如果這個不返回 則所有的方法 都返回空
}//問題就是在這裡了,這個原先沒有返回 所以所有的方法都被攔截了
returnnull; //這裡是不能返回空 close方法是返回空 而其他的方法 是有 返回的
}
}
至於,這個地址池的使用,就很方便了,只要建立一個這個地址池的單例,調動裡面的方法來獲得資料庫的連線就可以了;;
資料庫連線池:(小結)
管理多個數據庫連線的容器-連線池。
特點:
裡面有多個連線。
這些連線一般不關閉。
負責分發和回收。
把Connection 的 close 改造成釋放連線,並且喚醒等待的執行緒。
使用代理:完成方法的改造
替代Connection的 close方法。
第三方成熟的資料庫連線池:C3P0,DBCP。
自定義資料庫連線:
1、實現javax.sql.DataSource介面。
2、重寫裡面一個getConnection()方法
3、設定一個連線數的最大值。(保護資料庫)
4、設定一個初始化的連線數。
5、負責回收。(連線不關閉,而是回到資料庫連線池,並變為空閒狀態。)。
6、設定執行緒等待和解鎖的機制。
當然這裡使用第三方的開源外掛是最好的,有:c3p0- 和 commons-pool -dbcp 這兩個常用的;這裡就試了下c3p0 是可以用的,另外一個似乎有版本問題!!!!我寫的demo有問題應該,,,