【问题标题】:JNDI in Spring Boot with optional Embedded Tomcat Container带有可选嵌入式 Tomcat 容器的 Spring Boot 中的 JNDI
【发布时间】:2019-06-30 05:09:01
【问题描述】:

我对 Spring Boot 比较陌生,并且按照 How to create JNDI context in Spring Boot with Embedded Tomcat Container 中给出的建议实现了一种在 JNDI 上下文中放置数据源的方法

我通过将这些 bean 添加到应用程序来使其工作,这可以命名并将数据源放置在 JNDI 上下文中,如下所示:

@Autowired
Environment env;

public static void main(final String[] args) {
 SpringApplication.run(MyApplication.class, args);
}


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

  @Override
  public TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(final Tomcat tomcat) {
    tomcat.enableNaming();
    return super.getTomcatEmbeddedServletContainer(tomcat);
  }

  @Override
  public void postProcessContext(final Context context) {
    final String dataSourceURL = env.getProperty("datasource.url");
    // more properties

    final ContextResource resource = new ContextResource();
    resource.setType(DataSource.class.getName());
    resource.setProperty("url", dataSourceURL);
    // more properties

    resource.setName("jdbc/myDB");
    resource.setAuth("Container");
    resource.setType("javax.sql.DataSource");
    resource.setScope("Sharable");

    resource.setProperty("factory", "org.apache.commons.dbcp.BasicDataSourceFactory");

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

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

到目前为止一切顺利,它奏效了。但现在项目的规范已经改变。除了提供一个启动嵌入式 Tomcat 的胖 JAR(如最初计划的那样)之外,我还需要能够提供一个不引用嵌入式 Tomcat 的 WAR。 因此,我创建了额外的打包项目,并通过 Maven 依赖项处理了嵌入式 Tomcat 的可选包含。问题是,我必须将上面显示的代码从我的主类中移出并放入一个单独的包中,我通过 Maven 依赖项包含该包。现在它不再起作用了。

我承认我不太熟悉 @Autowired 和 @Bean 的 Spring 魔术是如何工作的,所以我有点在这儿磕磕绊绊。

我必须做些什么才能在我的主类之外创建 JNDI 上下文?

【问题讨论】:

  • 不要......只是不要......让用户决定。只需创建一个 WAR 文件(与 jar 一样可执行),如果人们想使用 JNDI 绑定数据源,请指定 spring.dataosurce.jndi-name 属性,否则使用其他 spring.datasoure 属性配置数据库。不要试图用 JNDI 将所有这些硬塞到嵌入式 tomcat 中,因为这会使事情变得过于复杂。
  • 我是否还必须启用命名才能做到这一点?在我看来它会回到同样的问题。
  • 不,你不需要那个。
  • 我仍然不确定我是否理解。您建议根本不使用 JNDI 或将其设为可选?问题是我正在重用一个旧的、已建立的持久层,它需要将数据源放在 JNDI 中,所以我无法避免它。您介意详细说明您的建议吗?
  • 从您的配置来看,它需要一个DataSource,它来自哪里并不重要。 Spring boot 两者都支持。

标签: java spring maven spring-boot tomcat


【解决方案1】:

结果证明解决方案非常简单,我可以通过了解更多关于 spring bean 的信息来找到它。我创建了另一个在其中创建 bean 的类,用 @Configuration 对其进行注释并将其添加到主类的 @ComponentScan 规范中。看起来像这样:

@ComponentScan(basePackages = {"myBasePackage",
                           "externalPackageContainingConfiguration"})

externalPackageContainingConfiguration 仅在通过 Maven 依赖项添加工件时才被发现。有点 hacky,但可以解决问题。

【讨论】:

    猜你喜欢
    • 2015-04-18
    • 2018-08-08
    • 2018-01-26
    • 2015-03-23
    • 2018-06-13
    • 1970-01-01
    • 2016-01-07
    • 2014-09-16
    • 2017-09-14
    相关资源
    最近更新 更多