Struts2+spring+hibernate中的proxool连接池配备

Struts2+spring+hibernate中的proxool连接池配置

      最近做的一个项目中运用到了连接池技术,可能我们大家比较熟悉的开源连接池有dbcp,c3p0,proxool。对这三种连接池来说,从性能和出错率来说,proxool稍微比前两种好些。今天主要讲述一下,我在项目中成功的配置和源码。

 

第一步:首先去http://proxool.sourceforge.net/下载两个jar文件,一个是proxool-0.9.1.jar,另一个是proxool-cglib.jar,然后将这两个jar文件放到WEB-INF/lib下。

 

第二步:就是写一个单独的proxool.xml文件放到WEB-INF文件夹下。我用的数据库是Oracle10g。

<?xml version="1.0" encoding="UTF-8"?>
<something-else-entirely>
 <proxool>
     <!-- 连接池的名字 -->
  <alias>dbPool</alias>
  <!--proxool只能管理由自己产生的连接-->
  <driver-url>
   jdbc:oracle:thin:@192.168.0.244:1521:qdhw
  </driver-url>
  <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
  <driver-properties>
   <property name="user" value="qdhw" />
   <property name="password" value="qdhw" />
  </driver-properties>
  <!-- proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁-->
  <house-keeping-sleep-time>90000</house-keeping-sleep-time>
  <!-- 指因未有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受-->
  <maximum-new-connections>30</maximum-new-connections>
  <!-- 最少保持的空闲连接数-->
  <prototype-count>5</prototype-count>
  <!-- 允许最大连接数,超过了这个连接,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定-->
  <maximum-connection-count>200</maximum-connection-count>
  <!-- 最小连接数-->
  <minimum-connection-count>10</minimum-connection-count>
 </proxool>

</something-else-entirely>

 

第三步:加载并初始化proxool.xml文件。因为它是连接数据库的,其他很多模块都用到数据,所以你必须首先加载它,在web.xml中进行如下配置:如果你以前加载applicationContext.xml用的是:
<listener>
    <listener-class>
  org.springframework.web.context.ContextLoaderListener
    </listener-class>
 </listener>
  这时你必须换成如下配置:
 <servlet>
  <servlet-name>contextConfigLocation</servlet-name>
  <servlet-class>
   org.springframework.web.context.ContextLoaderServlet
  </servlet-class>
  <load-on-startup>2</load-on-startup>
 </servlet>
 要不然你就会遇见这样的错误:
Problem   
org.logicalcobwebs.proxool.ProxoolException: Attempt to refer to a unregistered pool by its
alias 'dbPool'
      如果用过proxool与spring整合时,不少就遇到过这样的问题,其实这个问题很明显就是你的proxool.xml没有被先加载初始化,我们应该让它先加载,应该这样配置:
<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>
  把<load-on-startup>的值设为1,值越小级别就越高,就先被加载初始化。一定要先于applicationContext.xml的加载。

第三步是参照网上的一些文章,试了许久,还是有错误,还是不行。几经折腾,在网上找到了解决的办法,就是自己写个监听器,用它来起动proxool连接池,然后在web.xml中配置一下,我的配置如下:

 

<!-- 配置proxool.xml连接池监听类 -->
   <context-param>
    <param-name>xmlFile</param-name>
    <param-value>/WEB-INF/proxool.xml</param-value> 
   </context-param>
  <listener>
    <listener-class>com.xtlh.qdbridge.util.ProxoolListener</listener-class>
  </listener>

 

监听器类如下:

import java.io.File;  
import java.util.Enumeration;  
import java.util.Properties;  
 
import javax.servlet.ServletContext;  
import javax.servlet.ServletContextEvent;  
import javax.servlet.ServletContextListener;  
 
import org.apache.commons.logging.Log;  
import org.apache.commons.logging.LogFactory;  
import org.logicalcobwebs.proxool.ProxoolException;  
import org.logicalcobwebs.proxool.configuration.JAXPConfigurator;  
import org.logicalcobwebs.proxool.configuration.PropertyConfigurator;  

public class ProxoolListener implements ServletContextListener
{
 private static final Log LOG = LogFactory.getLog(ProxoolListener.class);  
    private static final String XML_FILE_PROPERTY = "xmlFile";  
    private static final String PROPERTY_FILE_PROPERTY = "propertyFile";  
    private static final String AUTO_SHUTDOWN_PROPERTY = "autoShutdown";  
    @SuppressWarnings("unused")  
    private boolean autoShutdown = true;  
      
    public void contextDestroyed(ServletContextEvent arg0){  
         System.out.println("destroy database pool....");  
     }  
 
    public void contextInitialized(ServletContextEvent contextEvent){  
         ServletContext context = contextEvent.getServletContext(); //对应servlet的init方法中ServletConfig.getServletContext()  
         String appDir = contextEvent.getServletContext().getRealPath("/");  
         Properties properties = new Properties();  
 
         Enumeration names = context.getInitParameterNames();  
        while (names.hasMoreElements()) {  
             String name = (String) names.nextElement();  
             String value = context.getInitParameter(name);  
 
            if (name.equals(XML_FILE_PROPERTY)) {  
                try {  
                     File file = new File(value);  
                    if (file.isAbsolute()) {  
                         JAXPConfigurator.configure(value, false);  
                     } else {  
                         JAXPConfigurator.configure(appDir + File.separator + value, false);  
                     }  
                 } catch (ProxoolException e) {  
                     LOG.error("Problem configuring " + value, e);  
                 }  
             } else if (name.equals(PROPERTY_FILE_PROPERTY)) {  
                try {  
                     File file = new File(value);  
                    if (file.isAbsolute()) {  
                         PropertyConfigurator.configure(value);  
                     } else {  
                         PropertyConfigurator.configure(appDir + File.separator + value);  
                     }  
                 } catch (ProxoolException e) {  
                     LOG.error("Problem configuring " + value, e);  
                 }  
             } else if (name.equals(AUTO_SHUTDOWN_PROPERTY)) {  
                 autoShutdown = Boolean.valueOf(value).booleanValue();  
             } else if (name.startsWith("jdbc")) { //此处以前是PropertyConfigurator.PREFIX改为jdbc,因为此源码是0.9.1版本的,与0.9RC3版本有点不一样  
                 properties.setProperty(name, value);  
             }  
         }  
 
        if (properties.size() > 0) {  
            try {  
                 PropertyConfigurator.configure(properties);  
             } catch (ProxoolException e) {  
                 LOG.error("Problem configuring using init properties", e);  
             }  
         }  
     }  

}

 

最后一步:整合spring和proxool。在applicationContext.xml文件中把原来数据源的配置成这样:

 

<!-- 引入proxool.xml文件,proxool-0.9.1.jar包和proxool-cglib.jar  -->
  <!-- 配置数据源 -->
 <bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
        <property name="driverClassName">
         <!-- 将数据库连接交给了proxool管理,使它的驱动 --> 
         <value>org.logicalcobwebs.proxool.ProxoolDriver</value> 
        </property>
        <property name="url"> 
            <!-- 数据库连接池的别名,与你的proxool.xml中的Alias必须一致 --> 
            <value>proxool.dbPool</value> 
        </property> 
 </bean>

 

这样,就一切ok了。