MySQL數據庫默認的連接超時時間爲8h(即wait_timeout=28800s),如果一個連接閒置時間超過8h,MySQL會主動斷開這個連接。用proxool連接池可以解決Mysql自動斷開重連的問題,它具有移植性好,快速、成熟、健壯等特性,同時還提供了可視化的連接池實時監控工具。proxool連接池配置如下:
1、下載相關JAR包;
從Maven Repository倉庫中下載proxool相關jar包,並將proxool-0.9.1.jar和proxool-cglib.jar拷貝至項目中。
2、在WEB-INF目錄下新建一個proxool.xml文件,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<something-else-entirely>
<proxool>
<alias>dbname</alias> <!--數據源的別名-->
<driver-url> jdbc:mysql://localhost:3306/testdb</driver-url><!--url連接串-->
<driver-class>com.mysql.jdbc.Driver </driver-class> <!--驅動類-->
<driver-properties>
<property name="user" value="root" /> <!--用戶名-->
<property name="password" value="root" /><!--密碼-->
</driver-properties>
<!--最大連接數(默認5個),超過了這個連接數,再有請求時,就排在隊列中等候,最大的等待請求數由maximum-new-connections決定 -->
<maximum-connection-count>100</maximum-connection-count>
<!--最小連接數(默認2個)-->
<minimum-connection-count>10</minimum-connection-count>
<!--proxool自動偵察各個連接狀態的時間間隔(毫秒),偵察到空閒的連接就馬上回收,超時的銷燬 默認30秒-->
<house-keeping-sleep-time>90000</house-keeping-sleep-time>
<!--沒有空閒連接可以分配而在隊列中等候的最大請求數,超過這個請求數的用戶連接就不會被接受-->
<maximum-new-connections>10</maximum-new-connections>
<!--如果housekeeper檢測到某個線程的活動時間大於這個數值.它將會殺掉這個線程.所以確認一下你的服務器的帶寬.然後定一個合適的值.默認是5分鐘.-->
<maximum-active-time>300000</maximum-active-time>
<!--最少保持的空閒連接數(默認2個)-->
<prototype-count>5</prototype-count>
<!--在使用之前測試-->
<test-before-use>true</test-before-use>
<!--用於保持連接的測試語句 -->
<house-keeping-test-sql>select sysdate from dual</house-keeping-test-sql>
</proxool>
<proxool>
<alias> dbname2</alias>
<driver-url>jdbc:oracle:thin:@localhost:1521:testdb2</driver-url>
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
<driver-properties>
<property name="user" value="dba" />
<property name="password" value="dba" />
</driver-properties>
<maximum-connection-count>100</maximum-connection-count>
<minimum-connection-count>10</minimum-connection-count>
<house-keeping-sleep-time>90000</house-keeping-sleep-time>
<maximum-new-connections>10</maximum-new-connections>
<maximum-active-time>300000</maximum-active-time>
<prototype-count>5</prototype-count>
<test-before-use>true</test-before-use>
<house-keeping-test-sql>select sysdate from dual</house-keeping-test-sql>
</proxool>
</something-else-entirely>
這裏面你可以根據需要配置多個不同數據庫的數據源。
3、配置web.xml文件;
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>ServletConfigurator</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
<init-param>
<param-name>xmlFile</param-name>
<param-value>WEB-INF/proxool.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 1、配置proxool連接池監控 -->
<servlet>
<servlet-name>Admin</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Admin</servlet-name>
<url-pattern>/admin</url-pattern>
</servlet-mapping>
<!-- 2、配置受保護域,只有Tomcat管理員才能察看連接池的信息 -->
<security-constraint>
<web-resource-collection>
<web-resource-name>proxool</web-resource-name>
<url-pattern>/admin</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description>The role that is required to log in to the Manager Application</description>
<role-name>manager</role-name>
</security-role>
<error-page>
<error-code>401</error-code>
<location>/401.jsp</location>
</error-page>
在應用啓動後訪問:http://localhost:8080/<web-name>/admin這個url即可監控。
注意:
1、配置proxool連接池監控,僅需<!-- 1、配置proxool連接池監控 -->配置;
2、配置tomcat manager查看連接池信息時,需要在401.jsp頁面中添加如下配置:
<%response.setHeader("WWW-Authenticate", "Basic realm=\"Tomcat Manager Application\"");%>這句話,
否則在訪問/admin察看連接池信息時,會直接跳轉到401.jsp頁面。
4、通過Java API配置連接池,獲取連接池信息;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.logicalcobwebs.proxool.ProxoolException;
import org.logicalcobwebs.proxool.ProxoolFacade;
import org.logicalcobwebs.proxool.admin.SnapshotIF;
public class PoolManager {
private static int activeCount = 0;
public PoolManager(){ }
/**
* 獲取連接
* getConnection
* @param name
* @return
*/
public Connection getConnection() {
Connection conn = null;
try{
//proxool驅動類
Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
//此處的dbname是在proxool.xml中配置的連接池別名,當然根據需要可以用dbname2
conn = DriverManager.getConnection("proxool.dbname");
showSnapshotInfo();
}catch(Exception ex){
ex.printStackTrace();
}
return conn;
}
/**
* 此方法可以得到連接池的信息
* showSnapshotInfo
*/
private void showSnapshotInfo(){
try{
SnapshotIF snapshot = ProxoolFacade.getSnapshot("dbname", true);
//獲得活動連接數
int curActiveCount=snapshot.getActiveConnectionCount();
//獲得可得到的連接數
int availableCount=snapshot.getAvailableConnectionCount();
//獲得總連接數
int maxCount=snapshot.getMaximumConnectionCount() ;
//當活動連接數變化時輸出的信息
if(curActiveCount!=activeCount) {
System.out.println("活動連接數:"+curActiveCount+",(active)可得到的連接數:"+availableCount+",(available)總連接數:"+maxCount+"(max)");
activeCount=curActiveCount;
}
}catch(ProxoolException e){
e.printStackTrace();
}
}
/**
* 獲取連接
* getConnection
* @param name
* @return
*/
public Connection getConnection(String name){
return getConnection();
}
/**
* 釋放連接
* freeConnection
* @param conn
*/
public void freeConnection(Connection conn){
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 釋放連接
* freeConnection
* @param name
* @param con
*/
public void freeConnection (String name,Connection con){
freeConnection(con);
}
public void getQuery() {
try {
Connection conn = getConnection();
if(conn != null){
Statement statement = conn.createStatement();
ResultSet rs = statement.executeQuery("select * from Users");
int c = rs.getMetaData().getColumnCount();
while(rs.next()){
System.out.println();
for(int i=1;i<=c;i++){
System.out.print(rs.getObject(i));
}
}
rs.close();
}
freeConnection(conn);
} catch (SQLException e) {
e.printStackTrace();
}
}
}