我们在使用flyway的时候,只能处理对于表相关的一些操作,但是在部署的时候,如果没有库,那么也是没有用的,所以我们要在启动服务的时候,自动创建数据库。
直接上代码:
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.core.env.ConfigurableEnvironment;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class CustomApplicationRunListener implements SpringApplicationRunListener {
private static final Map<String, String> DRIVER_DB_NAME_MAP = new HashMap<>();
static {
DRIVER_DB_NAME_MAP.put("org.postgresql.Driver", "postgres");
DRIVER_DB_NAME_MAP.put("com.mysql.cj.jdbc.Driver", "mysql");
}
public CustomApplicationRunListener(SpringApplication app, String[] args) {
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
log.info("CustomApplicationRunListener environmentPrepared...");
String driver = environment.getProperty("spring.datasource.driver-class-name");
String dbUrl = environment.getProperty("spring.datasource.url");
String username = environment.getProperty("spring.datasource.username");
String password = environment.getProperty("spring.datasource.password");
createDatabase(driver, dbUrl, username, password);
}
private void createDatabase(String driver, String dbUrl, String username, String password) {
try {
if (driver != null && dbUrl != null && username != null && password != null) {
String dbName = dbUrl.substring(dbUrl.lastIndexOf("/") + 1, dbUrl.indexOf("?"));
log.info(dbName);
Class.forName(driver);
try (Connection conn = DriverManager.getConnection(dbUrl, username, password)) {
log.info("{} create connection success...", dbUrl);
} catch (Exception e1) {
log.error("connect db failed.", e1);
dbUrl = dbUrl.replace(dbName, DRIVER_DB_NAME_MAP.get(driver));
try (Connection conn = DriverManager.getConnection(dbUrl, username, password);
Statement stat = conn.createStatement()) {
stat.executeUpdate("create database " + dbName);
}
}
}
} catch (Exception e) {
log.error("create db failed", e);
}
}
}
新建spring.factories
这里其实使用的是SPI模式:
SPI 的全名为 Service Provider Interface 大多数开发人员可能不熟悉,因为这个是是针对厂商或者插件的。在java.util.ServiceLoader 的文档里有比较详细的介绍;
在SpringBoot 中也有一种类似SPI的加载机制,路径位于jar包中的META-INF/spring.factories,数据为key=value格式存储,类似于下面这种,作用就是为了将指定类,注入到Bean中;
把路径配置好:
org.springframework.boot.SpringApplicationRunListener=*****.common.CustomApplicationRunListener
重启即可。