Ich habe eine Befehlszeilenanwendung erstellt, die mit Spring Boot eine Verbindung zur Datenbank herstellt. Obwohl es sich um eine häufig verwendete Anwendung handelt, werden DB-Verbindungsinformationen nur selten implementiert, sodass sie durch Befehlsparameter angegeben werden können. Daher werde ich die Implementierungsmethode zusammenfassen.
Wenn Sie eine Klasse implementieren, die die Schnittstelle "org.springframework.boot.CommandLineRunner" implementiert, ruft Spring Boot sie nach dem Startvorgang auf.
@Component
@Lazy(false)
public class MainRunner implements CommandLineRunner {
private static String HELP_MESSAGE = "java -jar cli-examples.jar -k <key> [option]";
@Autowired
ApplicationContext context;
@Override
public void run(String... args) throws Exception {
Options options = new Options();
options.addOption("?", "help", false, "Zeigen Sie eine Hilfemeldung an.");
options.addOption("h", "host", true, "Geben Sie den DB-Hostnamen an. Dieser Wert Der Standardwert ist\"localhost\"ist.");
options.addOption("p", "port", true, "Bitte geben Sie die DB-Portnummer an. Dieser Wert Der Standardwert ist\"5432\"ist.");
options.addOption("U", "dbUserId", true, "Bitte geben Sie die DB-Benutzer-ID an. Dieser Wert Der Standardwert ist\"postgres\"ist.");
options.addOption("P", "dbPassword", true, "Bitte geben Sie das DB-Passwort an. Dieser Wert Der Standardwert ist\"postgres\"ist.");
options.addOption("d", "dbName", true, "Bitte geben Sie den Datenbanknamen an. Dieser Wert Der Standardwert ist\"postgres\"ist.");
options.addOption("k", "key", true, "Bitte geben Sie den Schlüssel für die Datensuche an. Dieser Wert ist erforderlich.");
//Optionale Analyse
CommandLine cl = null;
try {
cl = new DefaultParser().parse(options, args);
} catch (UnrecognizedOptionException e) {
System.err.println("Eine unbekannte Option ist angegeben.[" + e.getMessage() + "]");
} catch (MissingArgumentException e) {
System.err.println("Es wurden keine optionalen Argumente eingegeben.[" + e.getMessage() + "]");
}
if (cl == null || cl.hasOption("?")) {
new HelpFormatter().printHelp(HELP_MESSAGE, options);
return;
}
//Informationen zur Datenbankverbindung abrufen
DataBaseInfo.create(cl);
if (DataBaseInfo.instance == null) {
new HelpFormatter().printHelp(HELP_MESSAGE, options);
return;
}
//Daten für die Datensuche abrufen
ParamInfo paramInfo = ParamInfo.create(cl);
if (paramInfo == null) {
new HelpFormatter().printHelp(HELP_MESSAGE, options);
return;
}
//Führen Sie den Dienst aus
MainService service = context.getBean(MainService.class);
long count = service.execute(paramInfo);
System.out.println("Schlüssel(" + paramInfo.key + ") Suchergebnisse:" + count + "Fall");
}
}
Ich habe es so implementiert. Was @Lazy (false) betrifft, werde ich später erklären, aber ich habe Apache Commons CLI verwendet, um die Parameter zu analysieren. Wenn ich die Hilfe anzeige, sieht es so aus.
usage: java -jar cli-examples.jar -k <key> [option]
-?,--help Zeigt Hilfemeldungen an.
-d,--dbName <arg>Bitte geben Sie den Datenbanknamen an. Dieser Wert Der Standardwert ist"postgres"ist.
-h,--host <arg>Geben Sie den DB-Hostnamen an. Dieser Wert Der Standardwert ist"localhost"ist.
-k,--key <arg>Bitte geben Sie den Schlüssel für die Datensuche an. Dieser Wert ist erforderlich.
-p,--port <arg>Bitte geben Sie die DB-Portnummer an. Dieser Wert Der Standardwert ist"5432"ist.
-P,--dbPassword <arg>Bitte geben Sie das DB-Passwort an. Dieser Wert Der Standardwert ist"postgres"ist.
-U,--dbUserId <arg>Bitte geben Sie die DB-Benutzer-ID an. Dieser Wert Der Standardwert ist"postgres"ist.
Für Python sind Parameteranalyseklassen in der Standardbibliothek enthalten. Fügen Sie sie daher bitte auch in Java ein.
Der Analyseprozess des Eingabeparameters ist in der obigen Quelle wie folgt.
DataBaseInfo.create(cl);
Da Spring Boot die Komponenten beim Start initialisiert, wird die Datenquelle initialisiert und ein Fehler tritt auf, wenn die DB-Zugriffsklasse DI für die registrierte Komponente ist. Daher führt die in Spring Boot v2.2.0 implementierte Lazy Initialization den Datenquelleninitialisierungsprozess zum Zeitpunkt der Komponentenerfassung durch. Um dies festzulegen, fügen Sie einfach die Einstellung "spring.main.lazy-initialization" zu "application.yml" hinzu.
spring:
main:
banner-mode: log
lazy-initialization: true
Der Datenquellen-Instanziierungsprozess ist also wie folgt.
@SpringBootApplication
@Configuration
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Bean
public DataSource dataSource() {
if (DataBaseInfo.instance == null) {
throw new IllegalStateException("Die Initialisierung der DB-Verbindungsinformationen ist nicht abgeschlossen.");
}
StringBuilder builder = new StringBuilder();
builder.append("jdbc:postgresql://");
builder.append(DataBaseInfo.instance.host).append(":").append(DataBaseInfo.instance.port);
builder.append("/").append(DataBaseInfo.instance.dbName);
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(org.postgresql.Driver.class);
dataSource.setUrl(builder.toString());
dataSource.setUsername(DataBaseInfo.instance.userId);
dataSource.setPassword(DataBaseInfo.instance.password);
Properties connectionProperties = new Properties();
connectionProperties.setProperty("autoCommit", "false");
dataSource.setConnectionProperties(connectionProperties);
return dataSource;
}
}
Außerdem wird in der Klasse "examples.cli.MainRunner", die die anfängliche Verarbeitung ausführt, "@Lazy (false)" hinzugefügt, um die Lazy-Initialisierung zu deaktivieren. (Es ist möglicherweise nicht sinnvoll, "@Lazy (false)" hinzuzufügen, da es sowieso sofort aufgerufen wird.)
Da die Klasse "examples.cli.MainRunner" vor der Analyse der Eingabeparameter ausgeführt wird, tritt beim Start ein Fehler auf, wenn die Klasse, die normalerweise auf die Datenbank zugreift, DI ist.
Daher wird die Erfassung der Klasse, die auf die Datenbank zugreift, so implementiert, dass sie direkt aus dem ApplicationContext erfasst wird.
//Führen Sie den Dienst aus
MainService service = context.getBean(MainService.class);
long count = service.execute(paramInfo);
Durch diese Implementierung kann der Datenquelleninitialisierungsprozess nach der Befehlsparameteranalyse durchgeführt werden.
Die Klassen, die den DB-Zugriff ausführen, sind wie folgt.
@Component
public class MainServiceImpl implements MainService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Transactional
@Override
public long execute(ParamInfo paramInfo) {
Long selectCount = jdbcTemplate.queryForObject(
"select count(*) from main_tbl where key = ?",
new Object[] { paramInfo.key },
Long.class);
return selectCount;
}
}
Wenn die verzögerte Initialisierung aus irgendeinem Grund nicht verwendet werden kann, kann dies mithilfe von org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource erreicht werden, mit dem Datenquellen dynamisch gewechselt werden können.
Löschen Sie die Einstellung von spring.main.lazy-initialization
und implementieren Sie den Datenquelleninitialisierungsprozess wie folgt.
@SpringBootApplication
@Configuration
public class App {
private static final String DS_NONE_KEY = "ds_none";
private static final String DS_PGSQL_KEY = "ds_pgsql";
static DynamicRoutingDataSourceResolver resolver = new DynamicRoutingDataSourceResolver();
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
@Bean
public DynamicRoutingDataSourceResolver dataSource() throws ClassNotFoundException {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
Map<Object, Object> dataSources = new HashMap<>();
dataSources.put(DS_NONE_KEY, dataSource);
resolver.setTargetDataSources(dataSources);
resolver.setDefaultTargetDataSource(dataSource);
return resolver;
}
static class DynamicRoutingDataSourceResolver extends AbstractRoutingDataSource {
private String dataSourcekey = DS_NONE_KEY;
@Override
protected Object determineCurrentLookupKey() {
return dataSourcekey;
}
public void initDataSource(DataBaseInfo dbInfo) {
StringBuilder builder = new StringBuilder();
builder.append("jdbc:postgresql://");
builder.append(dbInfo.host).append(":").append(dbInfo.port);
builder.append("/").append(dbInfo.dbName);
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(org.postgresql.Driver.class);
dataSource.setUrl(builder.toString());
dataSource.setUsername(dbInfo.userId);
dataSource.setPassword(dbInfo.password);
Properties connectionProperties = new Properties();
connectionProperties.setProperty("autoCommit", "false");
dataSource.setConnectionProperties(connectionProperties);
Map<Object, Object> dataSources = new HashMap<>();
dataSources.put(DS_PGSQL_KEY, dataSource);
dataSourcekey = DS_PGSQL_KEY;
setTargetDataSources(dataSources);
setDefaultTargetDataSource(dataSource);
afterPropertiesSet();
}
}
}
Ein Mechanismus, bei dem beim Start beim Initialisierungsprozess eine leere Datenquelle festgelegt wird und die Datenquelle umgeschaltet wird, wenn nach der Analyse der Befehlsparameter die Methode "initDataSource" aufgerufen wird.
Es mag einen besseren Weg geben, aber das ist die Grenze dessen, was Sie herausfinden können.
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
Die implementierte Quelle ist wie folgt.
Die auf diese Zeit bezogenen Sites sind wie folgt.
Der erste Beitrag war Spring Boot, was sehr praktisch ist. Ich denke, ich werde so etwas anstelle eines Memos posten.
Recommended Posts