[JAVA] Spring Boot-Anwendung, die DB-Verbindungseinstellungen mit Parametern angibt

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.

Umgebung

Erstverarbeitung

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.

Initialisierung der DB-Verbindungseinstellungen

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.)

Klasse für DB-Zugriff

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;
    }

}

Implementierungsmethode ohne Lazy Initialization

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 })

Quelle

Die implementierte Quelle ist wie folgt.

cli-examples

Referenz

Die auf diese Zeit bezogenen Sites sind wie folgt.

abschließend

Der erste Beitrag war Spring Boot, was sehr praktisch ist. Ich denke, ich werde so etwas anstelle eines Memos posten.

Recommended Posts

Spring Boot-Anwendung, die DB-Verbindungseinstellungen mit Parametern angibt
Spring Boot DB-Verbindungspool
Erstellen Sie eine Anfrage-App mit Spring Boot
Verarbeitung beim Starten einer Anwendung mit Spring Boot
Starten Sie die Entwicklung von Webanwendungen mit Spring Boot
Starten Sie die Nginx + Spring Boot-Anwendung mit Docker-Compose
Führen Sie die WEB-Anwendung mit Spring Boot + Thymeleaf aus
Spring Boot2-Webanwendungsentwicklung mit Visual Studio Code SQL Server-Verbindung
Konfigurieren Sie die Spring Boot-Anwendung mit dem Maven Multi-Modul
Spring Boot 2.3 Verfügbarkeit von Anwendungen
Mit Spring Boot herunterladen
Einstellungen für die Verbindung zu MySQL mit Spring Boot + Spring JDBC
Versuchen Sie, OpenID Connect mit Keycloak (Spring Boot-Anwendung) zu verwenden.
Spring Boot mit Spring Security Filter-Einstellungen und Suchtpunkten
Generieren Sie mit Spring Boot einen Barcode
Implementieren Sie GraphQL mit Spring Boot
Versuchen Sie eine DB-Verbindung mit Java
Beginnen Sie mit Spring Boot
Implementieren Sie die REST-API mit Spring Boot und JPA (Application Layer).
DB-Verbindungseinstellungen Spring-Boot application.properties
Hallo Welt mit Spring Boot!
[Spring Boot] Erstellung von Webanwendungen
Führen Sie LIFF mit Spring Boot aus
SNS-Login mit Spring Boot
Spring Boot Hot Swapping-Einstellungen
Datei-Upload mit Spring Boot
Spring Boot beginnt mit dem Kopieren
Beispiel einer Webanwendung, die mit Spring Boot 1.5 mehrere Datenbanken verwaltet
CICS-Java-Anwendung ausführen- (4) Spring Boot-App
Spring Boot beginnend mit Docker
Tipps zur Spring Boot DB
Setzen Sie Cookies mit Spring Boot
Verwenden Sie Spring JDBC mit Spring Boot
Modul mit Spring Boot hinzufügen
Erste Schritte mit Spring Boot
Einstellungen für die Spring Boot-Leistung
Erstellen Sie mit Spring Boot einen Mikrodienst
Mail mit Spring Boot verschicken
Einführung der Bibliothek ff4j, die Feature Toggle mit Spring Boot realisiert
Erstellen wir eine Buchverwaltungs-Webanwendung mit Spring Boot part1
Lassen Sie uns mit Spring Boot part3 eine Webanwendung für die Buchverwaltung erstellen
Lassen Sie uns mit Spring Boot part2 eine Webanwendung für die Buchverwaltung erstellen
[Anfänger] Versuchen Sie, die REST-API für die Todo-App mit Spring Boot zu schreiben
Verwenden Sie die Standardauthentifizierung mit Spring Boot
Spring Boot-Anwendungsentwicklung in Eclipse
Überprüfungspunkte für den Spring Boot-Anwendungscode
gRPC auf Spring Boot mit grpc-spring-boot-Starter
Erstellen Sie eine App mit Spring Boot 2
Hot Deploy mit Spring Boot-Entwicklung
Datenbankverknüpfung mit doma2 (Spring Boot)
Spring Boot Programmierung mit VS Code
Bis "Hallo Welt" mit Spring Boot
Erhalten Sie Validierungsergebnisse mit Spring Boot
(Intellij) Hallo Welt mit Spring Boot
Erstellen Sie eine App mit Spring Boot
Google Cloud Platform mit Spring Boot 2.0.0
Implementieren Sie die Spring Boot-Anwendung in Gradle
Ich habe GraphQL mit Spring Boot ausprobiert
[Java] LINE-Integration mit Spring Boot