Spring Boot JNDI 应用程序设置

7

我正在尝试创建一个测试Spring Boot项目,使用JNDI连接到数据库。这是我的 application.properties 文件:

spring.datasource.name=jdbc/test
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.jndi-name=java:jdbc/test
spring.datasource.url=...
spring.datasource.username=...
spring.datasource.password=...
spring.datasource.type=javax.sql.DataSource
spring.datasource.separator=;

这是我的配置文件:

以下是我的配置文件:

@Configuration
@EnableConfigurationProperties
public class AppConfig {
    @Bean
    public TomcatEmbeddedServletContainerFactory tomcatFactory() {
        return new TomcatEmbeddedServletContainerFactory() {
            @Override
            protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
                tomcat.enableNaming();
                return super.getTomcatEmbeddedServletContainer(tomcat);
            }
        };
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
        DataSource dataSource = dataSourceLookup.getDataSource("java:jdbc/test");
        return dataSource;
    }
}

这是我的Application.java文件:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

当我运行这个程序时,遇到了以下错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [com/example/AppConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException: Failed to look up JNDI DataSource with name 'java:jdbc/test'; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
    at com.example.DemoApplication.main(DemoApplication.java:13) [classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException: Failed to look up JNDI DataSource with name 'java:jdbc/test'; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    ... 17 common frames omitted
Caused by: org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException: Failed to look up JNDI DataSource with name 'java:jdbc/test'; nested exception is javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup.getDataSource(JndiDataSourceLookup.java:48) ~[spring-jdbc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at com.example.AppConfig.dataSource(AppConfig.java:36) ~[classes/:na]
    at com.example.AppConfig$$EnhancerBySpringCGLIB$$7d9e0060.CGLIB$dataSource$0(<generated>) ~[classes/:na]
    at com.example.AppConfig$$EnhancerBySpringCGLIB$$7d9e0060$$FastClassBySpringCGLIB$$c85b73da.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at com.example.AppConfig$$EnhancerBySpringCGLIB$$7d9e0060.dataSource(<generated>) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_121]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    ... 18 common frames omitted
Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662) ~[na:1.8.0_121]
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313) ~[na:1.8.0_121]
    at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:350) ~[na:1.8.0_121]
    at javax.naming.InitialContext.lookup(InitialContext.java:417) ~[na:1.8.0_121]
    at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:155) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:179) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95) ~[spring-context-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    at org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup.getDataSource(JndiDataSourceLookup.java:45) ~[spring-jdbc-4.3.7.RELEASE.jar:4.3.7.RELEASE]
    ... 29 common frames omitted

我哪里做错了?
更新1: 这是我的pom.xml
<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
1个回答

10

Spring Boot旨在简化所有这些事情。

您应该在属性中拥有datasource urlusernamepassword或其jndi-name,而不是两个选项一起。

仅在application.properties中保留一个关于数据源的JNDI名称,无需前缀。希望您已经成功在Tomcat上配置了它。

spring.datasource.jndi-name=jdbc/test

然后从您的AppConfig中删除datasource()方法。 只需注入(自动装配)数据源并使用它。


那么其他所有的内容(用户名、密码、URL等)都应该放在META-INF文件夹内的context.xml中吗?如果我正在运行嵌入式Tomcat,那么我应该把这些信息放在哪里呢? - Richard
1
嗨,David。使用属性:spring.datasource.jndi-name=jdbc/test 只能在嵌入式服务器中使用吗?如果应用程序部署在外部应用服务器(如Jboss或WebLogic)上会发生什么? - J. Abel
@AndriySlobodyanyk 注入数据源并在哪里使用它?我的JPA仓库里吗? - Prabhat Gaur
@PrabhatGaur 因为只有一个数据源,所以根本不需要提及它。但是如果你想的话,可以按照通常的方式注入它。 - Andriy Slobodyanyk
@AndriySlobodyanyk 由于 javax.naming.NoInitialContextException 在 NamingManager.java 的 662 行引起。 - Prabhat Gaur
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接