java - 使用 Spring Boot 通过 jndi 查找配置两个数据源

标签 java spring-boot datasource jndi

我有一个使用 Spring Boot 构建的小型 Web 应用程序,它有两个数据源(一个用于应用程序数据,一个用于检索用户访问信息)。我已使用每个数据源的配置类并使用 application.properties 文件中的数据源连接详细信息成功配置了此配置。

我现在尝试重构它以使用 jndi 查找数据源详细信息,以便我可以在本地使用与在开发/测试和生产中使用的相同方法。

我已经修改了数据库配置类以使用 jndi 查找,现在正在 Spring Tool Suite 中提供的 Pivotal tc Server 上运行我的应用程序。

目前我可以看到其中一个数据源配置正确(我在应用程序启动时从表中返回记录计数)。但是,我的第二个数据源似乎没有正确配置,并且出现异常...

java.sql.SQLException: The url cannot be null
    at java.sql.DriverManager.getConnection(DriverManager.java:556) ~[na:1.7.0_40]
    at java.sql.DriverManager.getConnection(DriverManager.java:187) ~[na:1.7.0_40]
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:308) ~[tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:716) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:648) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:468) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:143) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:118) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:107) [tomcat-jdbc-8.5.4.jar:na]
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:131) [tomcat-jdbc-8.5.4.jar:na]
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) [spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) [spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:342) [spring-jdbc-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection.isEmbedded(EmbeddedDatabaseConnection.java:139) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.getDefaultDdlAuto(JpaProperties.java:224) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.getOrDeduceDdlAuto(JpaProperties.java:212) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.getAdditionalProperties(JpaProperties.java:188) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate.access$000(JpaProperties.java:129) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.getHibernateProperties(JpaProperties.java:126) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.isInitializingDatabase(DataSourceInitializedPublisher.java:80) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.postProcessAfterInitialization(DataSourceInitializedPublisher.java:68) [spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1723) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:113) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1600) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:254) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:448) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:299) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:129) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1214) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1214) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:776) [spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861) [spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) [spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:369) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:313) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.web.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:150) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.web.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:130) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.boot.web.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:86) [spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE]
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169) [spring-web-4.3.2.RELEASE.jar:4.3.2.RELEASE]
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5156) [catalina.jar:na]
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:na]
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:725) [catalina.jar:na]
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:701) [catalina.jar:na]
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:717) [catalina.jar:na]
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:586) [catalina.jar:8.0.26.B]
    at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1750) [catalina.jar:8.0.26.B]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [na:1.7.0_40]
    at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_40]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_40]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_40]
    at java.lang.Thread.run(Thread.java:724) [na:1.7.0_40]

我的 application.properties 文件具有以下属性

spring.datasource.jndi-name=java:comp/env/jdbc/app_datasource
spring.datasource.expected-type=javax.sql.DataSource

security.datasource.jndi-name=java:comp/env/jdbc/security_datasource
security.datasource.expected-type=javax.sql.DataSource

我的数据库配置类如下所示..

@Configuration
@EnableConfigurationProperties
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
public class AppDBConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public JndiPropertyHolder primary() {
        return new JndiPropertyHolder();
    }

    @Bean(name = "app")
    @Primary
    public DataSource appDataSource() {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource(primary().getJndiName());
        return dataSource;
    }
}

@Configuration
@EnableConfigurationProperties
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
public class SecurityDBConfig {

    @Bean
    @ConfigurationProperties(prefix = "security.datasource")
    public JndiPropertyHolder security() {
        return new JndiPropertyHolder();
    }

    @Bean(name = "security")
    public DataSource securityDataSource() {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource(security().getJndiName());
        return dataSource;
    }
}

server.xml 看起来像这样

<?xml version="1.0" encoding="UTF-8"?>
<Server port="${base.shutdown.port}" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
    <Listener className="com.springsource.tcserver.serviceability.deploy.TcContainerDeployer"/>
    <Listener accessFile="${catalina.base}/conf/jmxremote.access" address="127.0.0.1" authenticate="true" className="com.springsource.tcserver.serviceability.rmi.JmxSocketListener" passwordFile="${catalina.base}/conf/jmxremote.password" port="${base.jmx.port}" useSSL="false"/>
    <GlobalNamingResources>
        <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
    </GlobalNamingResources>
    <Service name="Catalina">
        <Executor maxThreads="300" minSpareThreads="50" name="tomcatThreadPool" namePrefix="tomcat-http--"/>
        <Engine defaultHost="localhost" name="Catalina">
            <Realm className="org.apache.catalina.realm.LockOutRealm">
                <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
            </Realm>
            <Host appBase="webapps" autoDeploy="true" deployOnStartup="true" deployXML="true" name="localhost" unpackWARs="true">
                <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t &quot;%r&quot; %s %b" prefix="localhost_access_log." suffix=".txt"/>
                <Context docBase="bsc" path="/bsc" reloadable="true" source="org.eclipse.jst.jee.server:bsc">
                    <Resource auth="Container" defaultAutoCommit="true" driverClassName="com.sybase.jdbc3.jdbc.SybDriver" maxActive="20" maxIdle="30000" maxWait="100" name="jdbc/security_datasource" password="securityPassword" removeAbandoned="true" removeAbandonedTimeout="15" type="javax.sql.DataSource" url="jdbc:sybase:Tds:server.systems.uk.co:10010/security_database" username="securityUserName"/>
                    <Resource auth="Container" defaultAutoCommit="true" driverClassName="net.sourceforge.jtds.jdbc.Driver" maxActive="20" maxIdle="30000" maxWait="100" name="jdbc/app_datasource" password="appPassword" removeAbandoned="true" removeAbandonedTimeout="15" type="javax.sql.DataSource" url="jdbc:jtds:sybase://server.systems.uk.co:10010/app_database" username="appUserName"/>
                </Context>
            </Host>
        </Engine>
        <Connector maxHttpHeaderSize="1508192" acceptCount="100" connectionTimeout="20000" executor="tomcatThreadPool" maxKeepAliveRequests="15" port="${bio.http.port}" protocol="org.apache.coyote.http11.Http11Protocol" redirectPort="${bio.https.port}"/>
    </Service>
</Server>

谁能明白为什么我的第二个数据源没有配置?这是生命周期时间问题吗?正如我所说,主数据源配置正确,但安全性失败

更新

JndiPropertyHolder 只是一个简单的便利类,如下所示

import org.springframework.stereotype.Component;

@Component
public class JndiPropertyHolder {
    private String jndiName;

    public String getJndiName() {
        return this.jndiName;
    }

    public void setJndiName(final String jndiName) {
        this.jndiName = jndiName;
    }

}

最佳答案

我通过配置我的 Spring Boot 项目成功实现了这一点,如下所述:

//1. Application.java
//package hello;
//
//import javax.sql.DataSource;
//
//import org.apache.commons.logging.Log;
//import org.apache.commons.logging.LogFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.boot.SpringApplication;
//import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
//import org.springframework.boot.builder.SpringApplicationBuilder;
//import org.springframework.boot.web.support.SpringBootServletInitializer;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.ComponentScan;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.Primary;
//import org.springframework.jdbc.core.JdbcTemplate;
//import org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup;
//
//import hello.utilspackage.Foo;
//import springfox.documentation.builders.PathSelectors;
//import springfox.documentation.builders.RequestHandlerSelectors;
//import springfox.documentation.spi.DocumentationType;
//import springfox.documentation.spring.web.plugins.Docket;
//import springfox.documentation.swagger2.annotations.EnableSwagger2;
//
//@Configuration
//@ComponentScan
//@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {

    private final Log logg = LogFactory.getLog(getClass());

    public static void main(String[] args) {
        SpringApplication.run(applicationClass, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        logg.info("Server startup data loading started");
        new Foo().bar();
        logg.info("Server startup data loading completed");
        return application.sources(applicationClass);
    }

    @Configuration
    public class Config {
        @Value("${foo.spring.datasource.jndi-name}")
        private String primaryJndiName;

        @Value("${bar.spring.datasource.jndi-name}")
        private String secondaryJndiName;

        @Primary
        @Bean(destroyMethod = "")

        public DataSource primaryDs() {
            JndiDataSourceLookup lookup = new JndiDataSourceLookup();
            return lookup.getDataSource(primaryJndiName);
        }

        @Bean(destroyMethod = "")

        public DataSource secondaryDs() {
            JndiDataSourceLookup lookup = new JndiDataSourceLookup();
            return lookup.getDataSource(secondaryJndiName);
        }
    }

    @Configuration
    public class ConfigJdbcTemplates {
        @Value("${foo.spring.datasource.jndi-name}")
        private String primaryJndiName;

        @Value("${bar.spring.datasource.jndi-name}")
        private String secondaryJndiName;

        @Primary
        @Bean(destroyMethod = "")

        public JdbcTemplate primaryJT() {
            JndiDataSourceLookup lookup = new JndiDataSourceLookup();
            return new JdbcTemplate(lookup.getDataSource(primaryJndiName));
        }

        @Bean(destroyMethod = "")

        public JdbcTemplate secondaryJT() {
            JndiDataSourceLookup lookup = new JndiDataSourceLookup();
            return new JdbcTemplate(lookup.getDataSource(secondaryJndiName));
        }
    }

    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
        @Bean
        public Docket api() {
            return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any())
                    .paths(PathSelectors.any()).build();
        }
    }

    private static Class<Application> applicationClass = Application.class;

}

Observe the class Config in above code snippet , it has been annotated with @Configuration and one of the datasources in it is declared as @Primary

//GreetingController.java
//package hello;
//
//import java.util.List;
//import java.util.Map;
//import java.util.Set;
//import java.util.concurrent.atomic.AtomicLong;
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.jdbc.core.JdbcTemplate;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestParam;
//import org.springframework.web.bind.annotation.RestController;
//
//import hello.Application.Config;
//
//@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @Autowired
    Config conf;

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
        String ss = null;
        List<Map<String, Object>> a = new JdbcTemplate(conf.secondaryDs())
                .queryForList("SELECT * from secondaryDB");
        for (Map<String, Object> map : a) {
            Set<String> kkeys = map.keySet();
            for (String string : kkeys) {
                if (map.get(string) != null)
                    ss += string + "  --  " + map.get(string).toString() + "## ";
            }
        }
        return new Greeting(counter.incrementAndGet(), String.format(template, ss));
    }

    @RequestMapping("/")
    public Greeting greetingBlank() throws Exception {
        String ss = null;
        List<Map<String, Object>> a = new JdbcTemplate(conf.primaryDs()).queryForList(
                "SELECT * from primaryDB");
        for (Map<String, Object> map : a) {
            Set<String> kkeys = map.keySet();
            for (String string : kkeys) {
                if (map.get(string) != null)
                    ss += string + "  --  " + map.get(string).toString() + "## ";
            }
        }
        return new Greeting(counter.incrementAndGet(), String.format(template, ss));
    }
}

现在,在我的其余 Controller 之一中,即在 GreetingController 类中,我可以安全地使用 @Autowired Config 配置实例。这样我们就可以使用 new JdbcTemplate(conf.secondaryDs())用于查询辅助数据源引用的数据库。或new JdbcTemplate(conf.primaryDs()) 用于查询主数据源引用的数据库

**Same can be achieved by configuring JdbcTemplates in Application.class , for this observe the class ConfigJdbcTemplates in Application.java. Please have a look at below implementation in controller DatabasePrimaryQueryController

//DatabasePrimaryQueryController.java
//package hello;
//
//import java.util.List;
//import java.util.Map;
//import java.util.Set;
//import java.util.concurrent.atomic.AtomicLong;
//
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RestController;
//
//import hello.Application.ConfigJdbcTemplates;
//
//@RestController
public class DatabasePrimaryQueryController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @Autowired
    ConfigJdbcTemplates confJts;

    @RequestMapping("/queryforpas")
    public Greeting greeting() throws Exception {
        String ss = null;
        List<Map<String, Object>> a = confJts.secondaryJT()
                .queryForList("SELECT * from secondaryDB");
        for (Map<String, Object> map : a) {
            Set<String> kkeys = map.keySet();
            for (String string : kkeys) {
                if (map.get(string) != null)
                    ss += string + "  --  " + map.get(string).toString() + "## ";
            }
        }
        return new Greeting(counter.incrementAndGet(), String.format(template, ss));
    }

    @RequestMapping("/queryforods")
    public Greeting greetingBlank() throws Exception {
        String ss = null;
        List<Map<String, Object>> a = confJts.primaryJT().queryForList(
                "SELECT * from primaryDB");
        for (Map<String, Object> map : a) {
            Set<String> kkeys = map.keySet();
            for (String string : kkeys) {
                if (map.get(string) != null)
                    ss += string + "  --  " + map.get(string).toString() + "## ";
            }
        }
        return new Greeting(counter.incrementAndGet(), String.format(template, ss));
    }
}

上述两种方法都按预期工作,唯一的区别是在第一个实现中我 Autowiring 数据源,而在第二个实现中 Jdbctemplate 是 Autowiring 的。

我的application.properties文件如下

server.servlet-path=/*
server.port=7877
foo.spring.datasource.jndi-name=java:/PrimaryDB
bar.spring.datasource.jndi-name=java:/SecondaryDB

此应用程序部署在 jboss eap 6.4 上,其中 jndi 名称与 jboss' standalone.xml 中的数据源详细信息绑定(bind)。

关于java - 使用 Spring Boot 通过 jndi 查找配置两个数据源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41941147/

相关文章:

java - 循环浏览 jComboBox

java - 如何将 Bolt 驱动程序与 Spring Boot/Data Neo4j 一起使用

ios - Firebase 数据库不等于请求 - 替代解决方案(适用于 iOS)

java - 单击按钮后显示小窗口

java - Hibernate 多对多映射,使用 PK 和额外列连接表

java - GC 多久执行一次?

java - Spring Boot OpenId Connect 和 Gluu 的配置问题

spring - 在每个 Spring 启动 @Test 上覆盖单个 @Configuration 类

spring-boot:如果密码失败,则在没有数据库的情况下启动应用程序

java - Tomcat 5.5 在启动时无法识别数据源(空组件 Catalina :type=DataSource)