如何解决如何创建自定义 c3p0 ComboPooledDataSource 并在 tomcat context.xml 中引用
我有一个 tomcat 应用服务器,我的数据库连接是在 context.xml 中定义的,并将数据源作为 JNDI 获取。
<Context>
<!-- Default set of monitored resources. If one of these changes,the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<Resource name="datasource/test" auth="Container"
type="com.mchange.v2.c3p0.ComboPooledDataSource"
factory="org.apache.naming.factory.beanfactory"
user="abc"
password="abc123"
jdbcUrl="jdbc:MysqL://localhost:3306/jacplus"
driverClass="com.MysqL.jdbc.Driver"
minPoolSize="2"
initialPoolSize="30"
maxPoolSize="50"
idleConnectionTestPeriod="600"
acquireRetryAttempts="30"/>
</Context>
而不是在 context.xml 中硬编码用户名和密码。我想将数据库凭据存储在 aws 机密管理器中,并使用从 aws 机密管理器检索到的数据库凭据创建数据源。
为此,我创建了以下自定义 ComboPooledDataSource 类。
import com.mchange.v2.c3p0.AbstractComboPooledDataSource;
import javax.naming.Referenceable;
import java.io.Serializable;
public final class CustomComboPoolDataSource extends AbstractComboPooledDataSource implements Serializable,Referenceable {
}
import com.mchange.v2.c3p0.PoolConfig;
import org.apache.tomcat.jdbc.pool.DataSourceFactory;
import java.sql.sqlException;
import java.util.Properties;
import javax.naming.Context;
import javax.sql.DataSource;
import org.apache.tomcat.jdbc.pool.PoolConfiguration;
public class SecuretomcatDataSourceImpl extends DataSourceFactory {
public SecuretomcatDataSourceImpl() {
}
@Override
public DataSource createDataSource(Properties properties,Context context,boolean XA) throws sqlException {
String userName = getFromAWSSecretManager("username");
String password = getFromAWSSecretManager("password");
PoolConfiguration poolProperties = SecuretomcatDataSourceImpl.parsePoolProperties(properties);
PoolConfig poolConfig = new PoolConfig(properties);
CustomComboPoolDataSource customDataSource = new CustomComboPoolDataSource();
customDataSource.setProperties(properties);
customDataSource.setUser(userName );
customDataSource.setPassword(password);
// The rest of the code is copied from Tomcat's DataSourceFactory.
if (poolProperties.getDataSourceJNDI() != null && poolProperties.getDataSource() == null) {
performJNDILookup(context,poolProperties);
}
return customDataSource;
}
}
之后,我从上面的实现中创建了一个 jar 文件并将其放入 tomcat /lib 文件夹中。
并且我在 tomcat/conf 文件夹中的 Context.xml 文件中做了以下修改。
<Resource name="datasource/test" auth="Container"
type="com.mchange.v2.c3p0.ComboPooledDataSource"
**factory="com.aws.rds.SecuretomcatDataSourceImpl"
user=""
password=""**
jdbcUrl="jdbc:MysqL://localhost:3306/jacplus"
driverClass="com.MysqL.jdbc.Driver"
minPoolSize="2"
initialPoolSize="30"
maxPoolSize="50"
idleConnectionTestPeriod="600"
acquireRetryAttempts="30"/>
但是当我启动 tomcat 时,我遇到了以下异常。
失败了;嵌套异常是 org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException: 无法使用名称查找 JNDI 数据源 'java:comp/env/datasource/test';嵌套异常是 javax.naming.NameNotFoundException: JNDI 对象 [java:comp/env/datasource/test] 未找到:JNDI 实现 返回空值 org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.initializeBean(AbstractAutowireCapablebeanfactory.java:1745) 在 org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.doCreateBean(AbstractAutowireCapablebeanfactory.java:576) 在 org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBean(AbstractAutowireCapablebeanfactory.java:498) 在 org.springframework.beans.factory.support.Abstractbeanfactory.lambda$doGetBean$0(Abstractbeanfactory.java:320) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) 在 org.springframework.beans.factory.support.Abstractbeanfactory.doGetBean(Abstractbeanfactory.java:318) 在 org.springframework.beans.factory.support.Abstractbeanfactory.getBean(Abstractbeanfactory.java:199) 在 org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083) 在 org.springframework.context.support.AbstractApplicationContext.finishbeanfactoryInitialization(AbstractApplicationContext.java:853) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) 在 org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:400) 在 org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:291) 在 org.springframework.web.context.ContextLoaderListener.contextinitialized(ContextLoaderListener.java:103) 在 org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4770) 在 org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5236) 在 org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) 在 org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:754) 在 org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730) 在 org.apache.catalina.core.StandardHost.addChild(StandardHost.java:744) 在 org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:980) 在 org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1851) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 在 java.util.concurrent.FutureTask.run(FutureTask.java:266) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 在 java.lang.Thread.run(Thread.java:748)
Caused by: javax.naming.NameNotFoundException: JNDI object with [java:comp/env/datasource/test] 未找到:JNDI 实现 返回空值 org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:158) 在 org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178) 在 org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:96) 在 org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup.getDataSource(JndiDataSourceLookup.java:45)
解决方法
您正在扩展 Tomcat JDBC 的 ObjectFactory
以创建您的数据源,只要类型属性不是 null
、javax.sql.DataSource
或 {{ 1}} 并将问题记录到警告级别(参见source code)。
如果您设置 javax.sql.XADataSource
,它应该可以工作,但您的解决方案依赖于Tomcat JDBC 和 C3P0。
我宁愿检索用户名和密码,并在 org.apache.tomcat.jdbc.pool.DataSource
的默认构造函数中调用 setUser
和 setPassword
,并使用泛型 type="javax.sql.DataSource"
在 Tomcat 中对其进行配置。>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。