您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

如何使用嵌入式Tomcat将JNDI数据库连接与Spring Boot和Spring Data结合使用?

如何使用嵌入式Tomcat将JNDI数据库连接与Spring Boot和Spring Data结合使用?

Tomcat使用线程的上下文类加载器确定要执行查找的JNDI上下文。如果线程上下文类加载器不是Web应用程序类加载器,则JNDI上下文为空,因此查找失败。

问题在于,DataSource启动期间执行的JNDI查找是在主线程上执行的,而主线程的TCCL不是Tomcat的Web应用程序类加载器。您可以通过更新TomcatEmbeddedServletContainerFactorybean来设置线程上下文类加载器来解决此问题。我还没有说服自己,这不是一个可怕的骇客,但确实有效……

这是更新的bean:

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

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                Tomcat tomcat) {
            tomcat.enableNaming();
            TomcatEmbeddedServletContainer container = 
                    super.getTomcatEmbeddedServletContainer(tomcat);
            for (Container child: container.getTomcat().getHost().findChildren()) {
                if (child instanceof Context) {
                    ClassLoader contextClassLoader = 
                            ((Context)child).getLoader().getClassLoader();
                    Thread.currentThread().setContextClassLoader(contextClassLoader);
                    break;
                }
            }
            return container;
        }

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

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

getEmbeddedServletContainer提取上下文的类加载器,并将其设置为当前线程的上下文类加载器。这是 调用super方法之后发生的。这种顺序非常重要,因为对super方法调用会创建并启动容器,并在创建过程中创建上下文的类加载器。

Java 2022/1/1 18:21:45 有325人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶