使用 JNDI 配置数据源 使用外部 Tomcat 9 服务器:Spring Boot

Posted

技术标签:

【中文标题】使用 JNDI 配置数据源 使用外部 Tomcat 9 服务器:Spring Boot【英文标题】:Configure DataSource Using JNDI Using external Tomcat 9 Server: Spring Boot 【发布时间】:2021-01-12 12:44:46 【问题描述】:

我有一个SpringBootApplication,打包成war文件:

@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
public class Application extends SpringBootServletInitializer 

    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    
    
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) 
        return application.sources(Application.class);
    


在 application.properties 上:

spring.datasource.jndi-name=java:comp/env/jdbc/bonanza

但是当我在 Tomcat 9 中部署战争时,我在日志中看到了这些消息:

Name [spring.datasource.jndi-name] is not bound in this Context. Unable to find [spring.datasource.jndi-name].. Returning null.

日志:

12:37:53.989 [main] DEBUG o.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/spring.datasource.jndi-name]
12:37:53.989 [main] DEBUG o.s.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/spring.datasource.jndi-name] not found - trying original name [spring.datasource.jndi-name]. javax.naming.NameNotFoundException: Name [spring.datasource.jndi-name] is not bound in this Context. Unable to find [spring.datasource.jndi-name].
12:37:53.990 [main] DEBUG o.springframework.jndi.JndiTemplate - Looking up JNDI object with name [spring.datasource.jndi-name]
12:37:53.991 [main] DEBUG o.s.jndi.JndiPropertySource - JNDI lookup for name [spring.datasource.jndi-name] threw NamingException with message: Name [spring.datasource.jndi-name] is not bound in this Context. Unable to find [spring.datasource.jndi-name].. Returning null.
12:37:53.995 [main] DEBUG o.springframework.jndi.JndiTemplate - Looking up JNDI object with name [java:comp/env/spring.datasource.jndi-name]
12:37:53.996 [main] DEBUG o.s.jndi.JndiLocatorDelegate - Converted JNDI name [java:comp/env/spring.datasource.jndi-name] not found - trying original name [spring.datasource.jndi-name]. javax.naming.NameNotFoundException: Name [spring.datasource.jndi-name] is not bound in this Context. Unable to find [spring.datasource.jndi-name].
12:37:53.996 [main] DEBUG o.springframework.jndi.JndiTemplate - Looking up JNDI object with name [spring.datasource.jndi-name]
12:37:53.997 [main] DEBUG o.s.jndi.JndiPropertySource - JNDI lookup for name [spring.datasource.jndi-name] threw NamingException with message: Name [spring.datasource.jndi-name] is not bound in this Context. Unable to find [spring.datasource.jndi-name].. Returning null.
12:37:53.998 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Found key 'spring.datasource.jndi-name' in PropertySource 'configurationProperties' with value of type String

在我的tomcat9/conf/context.xml:

 <Resource  name="jdbc/bonanza" 
                auth="Container" 
                type="javax.sql.DataSource"
                maxTotal="100" 
                maxIdle="30" 
                maxWaitMillis="10000"
                username="a_usr" 
                password="Mu*7gydlcdstg100@" 
                driverClassName="com.mysql.jdbc.Driver"
                url="jdbc:mysql://172.175.77.55:3306/a_db"
        />

【问题讨论】:

您使用的是嵌入式 tomcat 服务器还是外部 tomcat? 外部 tomcat,先生 我对下面的答案做了一些改动,你可以试试看。 tomcat.apache.org/tomcat-7.0-doc/jndi-resources-howto.html 【参考方案1】:

正如错误提示,spring boot 在 JNDI 查找中找不到键。 JNDI 在 Spring boot 的嵌入式 Tomcat 中被禁用,因此您需要使用 Tomcat#enableNaming 启用它,一旦完成,您需要在 JNDI 中创建一个查找条目。您可以参考我从 Spring Boot 项目维护者存储库之一复制的以下代码 GitHub repo JNDI-Tomcat

@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() 
    return new TomcatEmbeddedServletContainerFactory() 

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                Tomcat tomcat) 
            tomcat.enableNaming();
            return super.getTomcatEmbeddedServletContainer(tomcat);
        

        @Override
        protected void postProcessContext(Context context) 
            ContextResource resource = new ContextResource();
            resource.setName("jdbc/bonanza");
            resource.setType(DataSource.class.getName());
            resource.setProperty("driverClassName", "your.db.Driver");
            resource.setProperty("url", "jdbc:yourDb");

            context.getNamingResources().addResource(resource);
        
    ;

[编辑]

由于您没有使用嵌入式 tomcat 服务器,您可以通过使用 tomcat 配置文件来配置 JNDI:

在server.xml中,在&lt;GlobalNamingResources&gt;下创建一个Resource

<Resource auth="Container" driverClassName="..." 
                           maxActive="..." 
                           maxIdle="..." 
                           maxWait="..." 
                           name="jdbc/bonanza"  
                           username="..."
                           password="..."
                           type="..."
                           url="..."/>

在Context.xml中,可以链接资源

<context>
    <ResourceLink auth="Container" name="jdbc/bonanza" global="jdbc/bonanza" type="javax.sql.DataSource" />
</context>

另外,请确保您没有使用 spring-boot main 方法启动应用程序。您需要使用 maven/gradle 构建 war 文件,然后将其部署到 tomcat 并进行测试。

【讨论】:

我做了同样的结果,先生 :-( @NuñitodelaCalzada 出了什么问题?我怀疑您正在使用 spring-boot main 方法进行测试,而不是部署战争。是这样吗? 确实如此 :-)

以上是关于使用 JNDI 配置数据源 使用外部 Tomcat 9 服务器:Spring Boot的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot - 外部 Tomcat - JNDI 数据源

Tomcat配置JNDI

如何使用外部化的属性文件在 Tomcat 中执行 JNDI

在 Spring Boot 应用程序中查找 JNDI 数据源失败

JNDI学习总结:tomcat下使用c3p0数据库连接池配置JNDI数据源

Tomcat数据源的原理,配置及使用(JNDI)