您的位置:首页 > 编程语言 > Java开发

Spring+Hibernate与proxool连接池的配置

2014-01-06 18:27 465 查看
前一篇文章讲过了如何在Hibernate中配置Proxool以连接oracle 11g,今天这篇来讲针对Spring+Hibernate如何对proxool连接池进行配置。

这次以MySQL为例。

第一步:首先去http://proxool.sourceforge.net/下载proxool.zip文,现在最新版本是proxool-0.9.1,解压缩后从中找到proxool-0.9.1.jar和proxool-cglib.jar,导入到对应的web项目中。如果用的是proxool-0.8.3,那只需导入一个jar包——proxool-0.8.3.jar。

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

ProxoolConf.xml的配置文件如下: 

<?xml version="1.0" encoding="UTF-8"?>
<something-else-entirely>
<proxool>
<alias>ConnectionPool</alias>
<driver-url>jdbc:mysql://localhost:3306/myTest</driver-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<driver-properties>
<property name="user" value="ukpss"/>
<property name="password" value="ukpss"/>
</driver-properties>

<house-keeping-sleep-time>90000</house-keeping-sleep-time>
<maximum-new-connections>20</maximum-new-connections>
<prototype-count>5</prototype-count>
<maximum-connection-count>100</maximum-connection-count>
<minimum-connection-count>10</minimum-connection-count>
<maximum-active-time>900000</maximum-active-time>
<maximum-connection-lifetime>1200000</maximum-connection-lifetime>
</proxool>
</something-else-entirely>
具体的元素说明请参看我的另一篇文章,Hibernate配置Proxool以连接oracle 11g

第三步:加载并初始化proxool.xml文件。

因为它是连接数据库的,其他很多模块都用到数据,所以你必须首先加载它,在web.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/ProxoolConf.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

如果你以前加载applicationContext.xml用的是

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>


由于listener先于servlet被加载,必须改为

<servlet>
<servlet-name>contextConfigLocation</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
【如果报找不到org.springframework.web.context.ContextLoaderServlet的错误,则到网上下载一个spring-web.jar放入工程项目即可。】

要不然你就会遇见这样的错误: 

Problem 
    
org.logicalcobwebs.proxool.ProxoolException: Attempt to refer to a unregistered pool by its alias ‘ConnectionPool’
 如果用过proxool与spring整合时,不少就遇到过这样的问题,其实这个问题很明显就是你的proxool.xml没有被先加载初始化,我们应该让它先加载。

完整的web.xml的配置内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- servlet for proxool -->
<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/ProxoolConf.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
<!-- servlet for proxool -->

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/com/config/spring/applicationContext-resource.xml,
classpath*:/com/config/spring/applicationContext-mapping.xml,
classpath*:/com/config/spring/applicationContext-adminAction.xml,

</param-value>
</context-param>
<servlet>
<servlet-name>contextConfigLocationServlet</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

<!-- load authority info into servlet context -->

<!-- load category data cache in servletcontext when spring application context creat
d58f
ion complete -->

<!-- Introspector 缓存清除监听器 -->
<listener>
<listener-class>
org.springframework.web.util.IntrospectorCleanupListener
</listener-class>
</listener>

<!-- encodingFilter to encode every page with GB2312 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- security Filter -->
<servlet>
<servlet-name>Dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>

</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>Dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>flushMode</param-name>
<param-value>AUTO</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<welcome-file-list>
<welcome-file>consumer/consumerLogin.jsp</welcome-file>
</welcome-file-list>

</web-app>
最后一步:整合spring和proxool。

在applicationContext.xml文件中把原来数据源的配置成这样: 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"><!-- 数据源类采用JDBC数据源 -->
<property name="driverClassName">
<!-- 将数据库连接交给了proxool管理,使它的驱动 --> <value>org.logicalcobwebs.proxool.ProxoolDriver</value>
</property>
<property name="url">
<!-- 数据库连接池的别名,与你的proxool.xml中的Alias必须一致 -->
<value>proxool.ConnectionPool</value>  <!--注意,此处的proxool并不是ProxoolConf.xml的文件名,不管你取什么文件名,这边都是用proxool. -->
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.connection.autocommit">true</prop>
<prop key="hibernate.show_sql">true</prop>
<!--
此处要注意因为proxool自己释放数据库连接比慢,所以要在此给出释放连接的模式,具体几种模式对应的意思,可以Google一下hibernate.connection.release_mode,有很多说明,在此不多说
-->
<prop key="hibernate.connection.release_mode">
after_statement
</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>cn/wt/vo/Admin.hbm.xml</value>
<value>cn/wt/vo/User.hbm.xml</value>
</list>
</property>
</bean>
<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="adminDao" class="cn.wt.dao.AdminDao" abstract="true" />
<bean id="adminDaoImpl" class="cn.wt.dao.impl.AdminDaoImpl"
parent="adminDao">
<property name="hibernateTemplate">
<ref bean="hibernateTemplate" />
</property>
</bean>
</beans>

这个 <property name="url">要配置成proxool.xml中的别名。其他地方不用改了。

如果会报无法为proxool.ConnectionPool加载驱动org.logicalcobwebs.proxool.ProxoolDriver,则应考虑是否ProxoolConf.xml的编码(如UTF-8)有问题。

至此配置就结束了!

如果你用的服务器是weblogic,那么恭喜你,在tomcat下运行好好的项目,到weblogic上可能会出现各种问题,两种web容器区别还是比较大的。这里,我仅介绍一下关于proxool会出现的问题:

按上面的配置,在tomcat上能无差错地运行,但在weblogic下会出现找不到ProxoolConf.xml文件的问题(特别是你以war包进行部署的时候),这是因为tomcat与weblogic默认的根目录不同。

这里,我们就不再使用servlet,改用listener来实现,这时就需要自己写一个listener类来加载proxool的配置文件,完整代码如下:

package com.airconditioner.proxool.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.log4j.Logger;
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 Logger logger = Logger
.getLogger(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";
private boolean autoShutdown = true;

public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("destroy database pool....");
}

public void contextInitialized(ServletContextEvent contextEvent) {
System.out.println(">>>>>>ProxoolListener init");
ServletContext context = contextEvent.getServletContext(); // 对应servlet的init方法中ServletConfig.getServletContext()
String appDir = this.getClass().getClassLoader().getResource("/").getPath();
logger.info(">>>>>>appDir: "+appDir);
//contextEvent.getServletContext().getResourceAsStream("");
Properties properties = new Properties();
Enumeration<?> names = context.getInitParameterNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
String value = context.getInitParameter(name);
String pathString = "";
if (name.equals(XML_FILE_PROPERTY)) {

try {
File file = new File(value);
if (file.isAbsolute()) {
JAXPConfigurator.configure(value, false);
} else {
pathString=appDir + ".." + File.separator + value;//
JAXPConfigurator.configure(pathString, false);
}
} catch (ProxoolException e) {
logger.error("Problem configuring pathString: " + pathString, e);
}
} else if (name.equals(PROPERTY_FILE_PROPERTY)) {
try {
File file = new File(value);
if (file.isAbsolute()) {
PropertyConfigurator.configure(value);
} else {
pathString=appDir + ".." + File.separator + value;//appDir +
PropertyConfigurator.configure(pathString);
}
} catch (ProxoolException e) {
logger.error("Problem configuring pathString2: " + pathString, e);
}
} else if (name.equals(AUTO_SHUTDOWN_PROPERTY)) {
autoShutdown = Boolean.valueOf(value).booleanValue();
} else if (name.startsWith("jdbc")) {

properties.setProperty(name, value);
}
}
if (properties.size() > 0) {
try {
PropertyConfigurator.configure(properties);
} catch (ProxoolException e) {
logger.error("Problem configuring using init properties", e);
}
}

}
}
其中,String appDir = this.getClass().getClassLoader().getResource("/").getPath();是用来获得weblogic下该项目的根目录,

得到的结果类似于XXX/XXXX项目/agmkr0/war/WEB-INF/classes/,由于ProxoolConf.xml我们放在了WEB-INF下,因此只要回退一层目录即可(用../)。用listener后,就不用多加载spring-web.jar包了。其他配置不变,修改web.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/com/config/spring/applicationContext-resource.xml,
classpath*:/com/config/spring/applicationContext-mapping.xml,
classpath*:/com/config/spring/applicationContext-adminAction.xml,

</param-value>
</context-param>

<!--proxool -->
<context-param>
<param-name>xmlFile</param-name>
<param-value>ProxoolConf.xml</param-value>
</context-param>

<listener>
<!-- 一定要排在所有listener前面 -->
<listener-class>com.airconditioner.proxool.listener.ProxoolListener</listener-class>
</listener>

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

<!-- load authority info into servlet context -->

<!-- load category data cache in servletcontext when spring application context creation complete -->

<!-- Introspector 缓存清除监听器 -->
<listener>
<listener-class>
org.springframework.web.util.IntrospectorCleanupListener
</listener-class>
</listener>

<!-- encodingFilter to encode every page with GB2312 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- security Filter -->
<servlet>
<servlet-name>Dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>

</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>Dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>flushMode</param-name>
<param-value>AUTO</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<welcome-file-list>
<welcome-file>consumer/consumerLogin.jsp</welcome-file>
</welcome-file-list>

</web-app>
其中修改、增加的部分如下:
<!--proxool -->
<context-param>
<param-name>xmlFile</param-name>
<param-value>ProxoolConf.xml</param-value>
</context-param>

<listener>
<!-- 一定要排在所有listener前面 -->
<listener-class>com.airconditioner.proxool.listener.ProxoolListener</listener-class>
</listener>由于listener得到的路径已经包含了WEB-INF,所以xmlFile对应的路径就不在写上这个了。

这样修改完,就可以同时支持weblogic和tomcat啦!

参考文章:
项目中成功的运用proxool连接池
Spring整合Hibernate时使用proxool连接池
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息