SSM+多数据源(oracle+mysql)+tomcat在服务停止时报错:[Abandoned connection cleanup thread] has failed to stop

本文介绍如何在SSM框架中配置多数据源(oracle+mysql),并解决服务关闭时出现的驱动未释放及内存泄漏问题。通过自定义监听器实现驱动注销,确保资源正确释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天进行SSM框架整合并使用多数据源配置(oracle+mysql),具体配置如下:
1、spring.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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.2.xsd">
    <!--加载properties文件-->
    <context:property-placeholder location="classpath:database.properties"></context:property-placeholder>

    <!--启用spring扫描-->
    <context:component-scan base-package="com.wondersgroup.hadoop">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
    </context:component-scan>

    <!--datasource-->
    <!--mysql-->
    <bean id="dataSourceDefault" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${mysql.jdbc.driver}"></property>
        <property name="url" value="${mysql.jdbc.url}"></property>
        <property name="username" value="${mysql.jdbc.username}"></property>
        <property name="password" value="${mysql.jdbc.password}"></property>
        <property name="maxActive" value="20"></property>
        <property name="maxIdle" value="10"></property>
        <property name="minIdle" value="2"></property>
        <!--30分钟回收一次-->
        <property name="timeBetweenEvictionRunsMillis" value="1800000"></property>
        <property name="initialSize" value="2"></property>
        <property name="validationQuery" value="select 1 from dual"></property>
    </bean>
    <!--oracle-->
    <bean id="dataSourceBusiness" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${oracle.jdbc.driver}"></property>
        <property name="url" value="${oracle.jdbc.url}"></property>
        <property name="username" value="${oracle.jdbc.username}"></property>
        <property name="password" value="${oracle.jdbc.password}"></property>
        <property name="maxActive" value="20"></property>
        <property name="maxIdle" value="10"></property>
        <property name="minIdle" value="2"></property>
        <!--30分钟回收一次-->
        <property name="timeBetweenEvictionRunsMillis" value="1800000"></property>
        <property name="initialSize" value="2"></property>
        <property name="validationQuery" value="select 1 from dual"></property>
    </bean>
    <!--多数据源汇总-->
    <bean id="dataSource" class="com.wondersgroup.hadoop.configration.datasource.MultiDataSource">
        <property name="targetDataSources">
            <map>
                <entry key="dataSourceMySql" value-ref="dataSourceDefault"></entry>
                <entry key="dataSourceOracle" value-ref="dataSourceBusiness"></entry>
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="dataSourceDefault"></property>
    </bean>

    <!--mybaitis-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="mapperLocations" value="classpath:com/wondersgroup/hadoop/mapper/**/*.xml"></property>
    </bean>
    <!--自动扫描dao接口,并生成代理对象,注意,dao接口必须实现@MapperScan注解-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.wondersgroup.hadoop.dao.*"></property>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
    </bean>

    <!--事物管理-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

服务在启动和使用(切换数据源查询)中都没有问题,但在关闭服务的时候,会出现两个错误:
1、数据库的(mysql和oracle)驱动无法释放。

2、The web application [] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak

针对驱动无法释放的问题,可以通过设置ServlectContextListner,在服务停止前,释放所有的Driver
import org.apache.log4j.Logger;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

/**
 * Created by lenovo on 2018/2/27.
 */
public class DriverMangerListner implements ServletContextListener {
    private final static Logger logger = Logger.getLogger(DriverMangerListner.class);
    public void contextInitialized(ServletContextEvent sce) {

    }

    public void contextDestroyed(ServletContextEvent sce) {
        logger.info("[DriverMangerListner]:-------DriverManager deregisterDriver start...");
        //com.mysql.jdbc.AbandonedConnectionCleanupThread.uncheckedShutdown();
        Enumeration<Driver> enumeration = DriverManager.getDrivers();
        while (enumeration.hasMoreElements()) {
            try {
                DriverManager.deregisterDriver(enumeration.nextElement());
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        logger.debug("[DriverMangerListner]:-------DriverManager deregisterDriver end...");
    }
}

针对问题2,网上查找的描述是mysql的驱动包不能加载到项目里面,需要放到tomcat的lib下,这个方法也确实可行。
问题2的第二种解决方案:在上面的listner中,添加一行代码

com.mysql.jdbc.AbandonedConnectionCleanupThread.uncheckedShutdown();

以上问题的产生原因还未知,等待后续更新...
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值