????? 最近做的一个项目中运用到了连接池技术,可能我们大家比较熟悉的开源连接池有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了。
?
?