如何在Spring Boot应用程序启动时启动H2 TCP服务器?

通过在SpringBootServletInitializer主方法中添加以下行,当我将应用程序作为Spring Boot应用程序运行时,我能够启动H2 TCP服务器(文件中的数据库):

@SpringBootApplication public class NatiaApplication extends SpringBootServletInitializer { public static void main(String[] args) { Server.createTcpServer().start(); SpringApplication.run(NatiaApplication.class, args); } } 

但是如果我在Tomcat上运行WAR文件,它就不起作用,因为没有调用main方法。 在bean初始化之前,如何在应用程序启动时启动H2 TCP服务器有更好的通用方法吗? 我使用Flyway(autoconfig)并且它在“Connection refused:connect”上失败可能是因为服务器没有运行。 谢谢。

这个解决方案适合我。 如果应用程序作为Spring Boot应用程序运行,并且如果它在Tomcat上运行,它将启动H2服务器。 创建H2服务器作为bean不起作用,因为先前创建了Flyway bean并且“Connection refused”失败了。

 @SpringBootApplication @Log public class NatiaApplication extends SpringBootServletInitializer { public static void main(String[] args) { startH2Server(); SpringApplication.run(NatiaApplication.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { startH2Server(); return application.sources(NatiaApplication.class); } private static void startH2Server() { try { Server h2Server = Server.createTcpServer().start(); if (h2Server.isRunning(true)) { log.info("H2 server was started and is running."); } else { throw new RuntimeException("Could not start H2 server."); } } catch (SQLException e) { throw new RuntimeException("Failed to start H2 server: ", e); } } } 

对于WAR包装,您可以这样做:

 public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class[] getRootConfigClasses() { return null; } @Override protected Class[] getServletConfigClasses() { Server.createTcpServer().start(); return new Class[] { NatiaApplication.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } } 

是的, 直接从文档中 ,您可以使用bean引用:

   

还有一个servlet侦听器选项可以自动启动/停止它。

这回答了你的问题,但我认为如果它与你的Spring Boot应用程序一起部署,你应该使用嵌入式模式。 这在资源上更快,更轻。 您只需指定正确的URL,数据库就会启动:

 jdbc:h2:/usr/share/myDbFolder 

( 直接从备忘单中 )。

你可以这样做:

 @Configuration public class H2ServerConfiguration { @Value("${db.port}") private String h2TcpPort; /** * TCP connection to connect with SQL clients to the embedded h2 database. * * @see Server * @throws SQLException if something went wrong during startup the server. * @return h2 db Server */ @Bean public Server server() throws SQLException { return Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", h2TcpPort).start(); } /** * @return FlywayMigrationStrategy the strategy for migration. */ @Bean @DependsOn("server") public FlywayMigrationStrategy flywayMigrationStrategy() { return Flyway::migrate; } } 

有一个警告在其他答案中没有考虑过。 您需要注意的是,启动服务器是对DataSource bean的短暂依赖。 这是因为DataSource只需要网络连接,而不是bean关系。

这导致的问题是spring-boot不会知道在创建DataSource之前需要启动的h2数据库,因此最终可能会在应用程序启动时出现连接exception。

使用spring-framework,这不是问题,因为您将数据库服务器启动放在根配置中,并将数据库作为子项。 使用弹簧靴AFAIK,只有一个上下文。

要解决此问题,您可以在数据源上创建一个Optional依赖项。 Optional的原因是您可能无法始终启动可能具有生产数据库的服务器(配置参数)。

 @Bean(destroyMethod = "close") public DataSource dataSource(Optional h2Server) throws PropertyVetoException { HikariDataSource ds = new HikariDataSource(); ds.setDriverClassName(env.getProperty("db.driver")); ds.setJdbcUrl(env.getProperty("db.url")); ds.setUsername(env.getProperty("db.user")); ds.setPassword(env.getProperty("db.pass")); return ds; }