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();
}
}
}