我正在尝试使用jetty EmbeddedContainerServlet和jndi数据源配置Spring启动项目,代码如下
@Configuration
public class EmbeddedJettyServer {
@Value("${jetty.http.port:8080}")
private Integer port;
@Value("${jetty.threadPool.maxThreads:200}")
private String maxThreads;
@Value("${jetty.threadPool.minThreads:8}")
private String minThreads;
@Value("${jetty.threadPool.idleTimeout:60000}")
private Integer idleTimeout;
private JettyServerCustomizer jettyServerCustomizer() {
return new JettyServerCustomizer() {
@Override
public void customize(Server server) {
try {
// Tweak the connection pool used by Jetty to handle
// incoming HTTP connections
final QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(Integer.valueOf(maxThreads));
threadPool.setMinThreads(Integer.valueOf(minThreads));
server.getBeans().add(threadPool);
WebAppContext webAppContext = (WebAppContext) server.getHandler();
createConfiguration(
"/Users/kewnen/git/zeus-info-provider/zeus-info-provider-web/ops/resources/jetty-datasource.xml")
.configure(webAppContext);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private XmlConfiguration createConfiguration(String xml) throws IOException, SAXException {
return new XmlConfiguration(new FileInputStream(xml));
}
};
}
@Bean
public EmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
final JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory = new JettyEmbeddedServletContainerFactory() {
@Override
protected JettyEmbeddedServletContainer getJettyEmbeddedServletContainer(Server server) {
return new JettyEmbeddedServletContainer(server);
}
};
jettyEmbeddedServletContainerFactory.addServerCustomizers(jettyServerCustomizer());
jettyEmbeddedServletContainerFactory.setPort(port);
jettyEmbeddedServletContainerFactory.setSessionTimeout(idleTimeout);
return jettyEmbeddedServletContainerFactory;
}
}
我定义数据源内容的jetty-datasource.xml文件的内容
<?xml version="1.0"?>
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<New id="cf" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg>jdbc/zeus-info</Arg>
<Arg>
<New class="org.apache.commons.dbcp.BasicDataSource">
<Set name="driverClassName">org.postgresql.Driver</Set>
<Set name="url">jdbc:postgresql://localhost:5433/myDb</Set>
<Set name="username">postgres</Set>
<Set name="password">password</Set>
<Set name="validationQuery">SELECT 1</Set>
</New>
</Arg>
</New>
然后我用下面的代码定义一个数据源
@Bean
public DataSource dataSource() {
JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
return dsLookup.getDataSource("jdbc/zeus-info");
}
当我运行它时,我得到了这个例外
Caused by: javax.naming.NameNotFoundException; remaining name 'jdbc/zeus-info'
at org.eclipse.jetty.jndi.local.localContextRoot.lookup(localContextRoot.java:490)
at org.eclipse.jetty.jndi.local.localContextRoot.lookup(localContextRoot.java:536)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:155)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:179)
at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:104)
at org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup.getDataSource(JndiDataSourceLookup.java:45)
当debuggin我清楚地看到Datasource bean在我定义我的jndi数据源的JettyEmbeddedServletContainerFactory的定义之前实例化,
我试图通过将@DependsOn注释添加到数据源定义来强制执行该命令但不起作用,它始终在容器之前实例化DataSource bean,
修改
提供更多详情,
我已经通过这种方式定义数据源而不使用jndi来测试它并且工作正常:
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(DRIVER_CLASS_NAME);
dataSource.setUrl(URL);
dataSource.setUsername(USER);
dataSource.setPassword(PASS);
return dataSource;
}
但是由于它是从classique war迁移到jndi定义的数据源到spring boot jar打包项目,我想从现有项目中重现相同的内容,因为我不知道将jndi方式改变为这个的影响。
我尝试通过在数据源定义上添加此行来强制数据源在容器之后进行实例化
@DependsOn("jettyEmbeddedServletContainerFactory")
但始终在jetty容器之前实例化数据源
修复:
问题是spring-boot自动配置一个名为jettyEmbeddedServletContainerFactory的容器,这就是为什么 @DependsOn(“jettyEmbeddedServletContainerFactory”)无效,
我添加
@EnableAutoConfiguration(exclude = EmbeddedServletContainerAutoConfiguration.class)
到我的应用程序,现在可以正常工作
感谢您的帮助!
答案 0 :(得分:0)
您可以使用Spring Boot属性初始化数据源bean而不是JNDI:
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.password=password
spring.datasource.type=org.apache.commons.dbcp.BasicDataSource
spring.datasource.url=jdbc:postgresql://localhost:5433/myDb
spring.datasource.username=postgres
spring.datasource.validation-query=SELECT 1
评论反应:
所以你的开发环境应尽可能接近Prod。因此,我不会使用嵌入式容器,而是使用独立容器进行开发。对于CI构建,您可以使用 maven-jetty-plugin或Gradle Jetty plugin