问题描述
我正在尝试在应用程序首次启动时进行一些数据库清理。 首先,我将JNDI连接定义如下:
@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/myDataSource");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "your.db.Driver");
resource.setProperty("url", "jdbc:yourDb");
context.getNamingResources().addResource(resource);
}
};
}
然后我希望在ApplicationListener ContextRefreshedEvent中检索资源,ApplicationListener实现如下:
@Component
public class StartupConfiguration implements ApplicationListener<ContextRefreshedEvent>
{
@Override
public void onApplicationEvent(ContextRefreshedEvent event)
{
ApplicationContext ctx = event.getApplicationContext();
Context initialContext = new InitialContext();
DataSource datasource = (DataSource) initialContext.lookup("java:comp/env/jdbc/myDataSource");
...
}
}
问题是它无法找到java:comp / env / jdbc / myDataSource,我已经使用各种事件进行了测试,而唯一起作用的事件是RequestHandledEvent
,我认为这不是一个很好的解决方案。
1楼
我在以下堆栈溢出问题中找到了答案stackoverflow.com/questions/27822619
我会引用安迪·威尔金森(Andy Wilkinson)
Tomcat使用线程的上下文类加载器确定要执行查找的JNDI上下文。 如果线程上下文类加载器不是Web应用程序类加载器,则JNDI上下文为空,因此查找失败。
还有安迪·威尔金森(Andy Wilkinson)提出的修复建议
@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);
}
};
}