【问题标题】:Spring Boot 2 Embedded Tomcat Jndi Datasource ConfigurationSpring Boot 2 嵌入式 Tomcat Jndi 数据源配置
【发布时间】:2018-09-28 10:01:07
【问题描述】:

在我的时区早上好

我已经关注了这两个 Stack Overflow 问题:

Spring Boot Using Embedded Tomcat with JNDI

和

Howto use JNDI database connection with Spring Boot and Spring Data using embedded Tomcat?

而且没有一个有效。 我正在使用 Spring Boot 2。 我想配置嵌入式 Tomcat 服务器以使用 JNDI。 我已经尝试过:

代码片段:

 @SpringBootApplication 
   public class MyApplication {

    public static void main ...


    @Bean   
   public ServletWebServerFactory servletContainer() {      TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {


     @Override          
     protected void postProcessContext(Context context) {
                    ContextResource resource = new ContextResource();
                    resource.setName("jdbc/CCC");
                    resource.setType(DataSource.class.getName());
                    resource.setProperty("driverClassName", "oracle.jdbc.driver.OracleDriver");
                    resource.setProperty("url", "jdbc:oracle:thin:@a77k11111188.tt.ddd.test:3000:BHJR00TT00");
                    resource.setProperty("username", "user");
                    resource.setProperty("password", "pass");
                    context.getNamingResources().addResource(resource);             }

     @Override          
    protected TomcatWebServer getTomcatWebServer(Tomcat tomcat){
                    tomcat.enableNaming();
                    TomcatWebServer container =  super.getTomcatWebServer(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;           }

            };      return tomcat;

然后使用application.properties

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

错误日志: 无法启动嵌入式 Tomcat
创建名为“servletEndpointRegistrar”的 bean 时出错
创建名为“dataSource”的 bean 时出错 DataSourceLookupFailureException:无法查找名为“java:comp/env/jdbc/CCC”的 JNDI 数据源
.NamingException: 无法创建资源工厂实例

ClassNotFoundException: org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory

相反,如果我不使用应用程序属性,而是像这样直接在 Spring Boot 应用程序中配置数据源 bean

@Bean(destroyMethod = "")
    public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
        JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
        bean.setJndiName("java:comp/env/jdbc/CCC");
        bean.setProxyInterface(DataSource.class);
        bean.setLookupOnStartup(false);
        bean.afterPropertiesSet();
        return (DataSource) bean.getObject();
    } 

错误日志
UnsatisfiedDependencyException:创建名为“entityManagerFactory”的 bean 时出错
BeanCreationException:创建名为“jpaVendorAdapter”的 bean 时出错

JndiLookupFailureException: JndiObjectTargetSource 未能获得新的目标对象
NamingException: 无法创建资源工厂实例

在我的 pom 中,我有以下依赖项

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
     <groupId>com.oracle</groupId>
     <artifactId>ojdbc7</artifactId>
     <version>12.1.0.2</version>
   </dependency>
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
  </dependency>  

我没有解决方案 提前致谢 最好的问候

【问题讨论】:

    标签: spring-boot spring-jdbc embedded-tomcat-8


    【解决方案1】:

    我也面临同样的问题,互联网上的大多数示例都在使用 TomcatEmbeddedServletContainerFactory 但是在尝试了几件事后,我终于能够在我的应用程序中获得 jndi 连接。

    我仍在找出问题的确切根本原因,但以下是供您参考的代码。

    @SpringBootApplication
    public class MybatisJNDISampleApplication {
        public static void main(String[] args) {
            SpringApplication.run(MybatisJNDISampleApplication.class, args);
        }
    
        @Bean
        public TomcatServletWebServerFactory tomcatFactory() {
            return new TomcatServletWebServerFactory() {
                @Override
                protected TomcatWebServer getTomcatWebServer(org.apache.catalina.startup.Tomcat tomcat) {
                    tomcat.enableNaming();
                    return super.getTomcatWebServer(tomcat);
                }
    
                @Override
                protected void postProcessContext(Context context) {
                    ContextResource resource = new ContextResource();           
                    //resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
                    resource.setName("jdbc/myDatasourceName");
                    resource.setType(DataSource.class.getName());
                    resource.setProperty("driverClassName", "oracle.jdbc.OracleDriver");
                    resource.setProperty("url", "db_url");
                    resource.setProperty("username", "db_username");
                    resource.setProperty("password", "db_password");
                    context.getNamingResources().addResource(resource);
                }
            };
        }
    }
    

    以下是我的配置类:

    @Configuration
    @MapperScan("com.sample.mybatis")
    public class DataConfig {
    
        public final String MAPPER_LOCATIONS_PATH = "classpath:mybatis-mappers/*.xml";
    
        @Bean(destroyMethod="")
        public DataSource dataSource() throws IllegalArgumentException, NamingException {
            JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
            bean.setJndiName("java:comp/env/jdbc/myDatasourceName");
            //bean.setResourceRef(true); // this was previously uncommented
            bean.setProxyInterface(DataSource.class);
            //bean.setLookupOnStartup(false); // this was previously uncommented
            bean.afterPropertiesSet();
            return (DataSource)bean.getObject();
        }
    
        @Bean
        public DataSourceTransactionManager transactionManager() throws NamingException {
            return new DataSourceTransactionManager(dataSource());
        }
    
        @Bean
        public SqlSessionFactory sqlSessionFactory() throws Exception {
            SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
            configureSqlSessionFactory(sessionFactory, dataSource());
            return sessionFactory.getObject();
        }
    
        public void configureSqlSessionFactory(SqlSessionFactoryBean sessionFactoryBean, DataSource dataSource) throws IOException {
            PathMatchingResourcePatternResolver pathResolver = new PathMatchingResourcePatternResolver();
            sessionFactoryBean.setDataSource(dataSource);
            sessionFactoryBean.setMapperLocations(pathResolver.getResources(MAPPER_LOCATIONS_PATH));
        }
    }
    

    希望这可以帮助您解决问题。

    【讨论】:

    • 一般情况下,我们使用JNDI配置来避免在通用源代码中暴露DB配置细节。您建议仅在应用程序启动文件中进行配置。在这种情况下,在 application.properties 文件中配置 DB 连接信息会有什么不同?
    • 我们是否需要添加任何依赖来解析SqlSessionFactory和SqlSessionFactoryBean?
    猜你喜欢
    • 1970-01-01
    • 2015-03-23
    • 2015-12-11
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    • 2016-01-07
    • 2017-08-08
    • 2021-04-30
    相关资源
    最近更新 更多