【问题标题】: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 连接信息会有什么不同?
    • 我们是否需要添加任何依赖来解析SqlSessionFactorySqlSessionFactoryBean
    猜你喜欢
    • 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
    相关资源
    最近更新 更多