[JAVA] Application Spring Boot qui spécifie les paramètres de connexion à la base de données avec des paramètres

J'ai créé une application de ligne de commande qui se connecte à DB avec Spring Boot. Bien qu'il s'agisse d'une application courante en soi, il est rare que les informations de connexion à la base de données soient implémentées de manière à pouvoir être spécifiées par des paramètres de commande, je vais donc résumer la méthode de mise en œuvre.

environnement

Traitement initial

ʻOrg.springframework.boot.CommandLineRunner` Si vous implémentez une classe qui implémente l'interface, Spring Boot l'appellera après le processus de démarrage.

@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, "Affichez un message d'aide.");
        options.addOption("h", "host", true, "Spécifiez le nom d'hôte de la base de données. Cette valeur La valeur par défaut est\"localhost\"est.");
        options.addOption("p", "port", true, "Veuillez spécifier le numéro de port DB. Cette valeur La valeur par défaut est\"5432\"est.");
        options.addOption("U", "dbUserId", true, "Veuillez spécifier l'ID utilisateur de la base de données. Cette valeur La valeur par défaut est\"postgres\"est.");
        options.addOption("P", "dbPassword", true, "Veuillez spécifier le mot de passe DB. Cette valeur La valeur par défaut est\"postgres\"est.");
        options.addOption("d", "dbName", true, "Veuillez spécifier le nom de la base de données. Cette valeur La valeur par défaut est\"postgres\"est.");
        options.addOption("k", "key", true, "Veuillez spécifier la clé pour la recherche de données. Cette valeur est obligatoire.");

        //Analyse facultative
        CommandLine cl = null;
        try {
            cl = new DefaultParser().parse(options, args);
        } catch (UnrecognizedOptionException e) {
            System.err.println("Une option inconnue est spécifiée.[" + e.getMessage() + "]");
        } catch (MissingArgumentException e) {
            System.err.println("Aucun argument facultatif n'a été entré.[" + e.getMessage() + "]");
        }
        if (cl == null || cl.hasOption("?")) {
            new HelpFormatter().printHelp(HELP_MESSAGE, options);
            return;
        }

        //Obtenir les informations de connexion à la base de données
        DataBaseInfo.create(cl);
        if (DataBaseInfo.instance == null) {
            new HelpFormatter().printHelp(HELP_MESSAGE, options);
            return;
        }

        //Obtenez des données pour la recherche de données
        ParamInfo paramInfo = ParamInfo.create(cl);
        if (paramInfo == null) {
            new HelpFormatter().printHelp(HELP_MESSAGE, options);
            return;
        }

        //Exécutez le service
        MainService service = context.getBean(MainService.class);
        long count = service.execute(paramInfo);
        System.out.println("Clé(" + paramInfo.key + ") Résultats de recherche:" + count + "Cas");
    }

}

Je l'ai implémenté comme ça. Quant à @Lazy (false), je l'expliquerai plus tard, mais j'ai utilisé la CLI Apache Commons pour analyser les paramètres. Lorsque j'affiche l'aide, cela ressemble à ceci.

usage: java -jar cli-examples.jar -k <key> [option]
 -?,--help Affiche les messages d'aide.
 -d,--dbName <arg>Veuillez spécifier le nom de la base de données. Cette valeur La valeur par défaut est"postgres"est.
 -h,--host <arg>Spécifiez le nom d'hôte de la base de données. Cette valeur La valeur par défaut est"localhost"est.
 -k,--key <arg>Veuillez spécifier la clé pour la recherche de données. Cette valeur est obligatoire.
 -p,--port <arg>Veuillez spécifier le numéro de port DB. Cette valeur La valeur par défaut est"5432"est.
 -P,--dbPassword <arg>Veuillez spécifier le mot de passe DB. Cette valeur La valeur par défaut est"postgres"est.
 -U,--dbUserId <arg>Veuillez spécifier l'ID utilisateur de la base de données. Cette valeur La valeur par défaut est"postgres"est.

Pour Python, les classes d'analyse de paramètres sont incluses dans la bibliothèque standard, veuillez donc les inclure également dans Java.

Initialisation des paramètres de connexion à la base de données

Le processus d'analyse du paramètre d'entrée est le suivant dans la source ci-dessus.

DataBaseInfo.create(cl);

Puisque Spring Boot initialise les composants au démarrage, si la classe liée à l'accès à la base de données est DI pour le composant enregistré, la source de données sera initialisée et une erreur se produira. Par conséquent, l'initialisation paresseuse implémentée à partir de Spring Boot v2.2.0 exécutera le processus d'initialisation de la source de données au moment de l'acquisition du composant. Pour le définir, ajoutez simplement le paramètre de spring.main.lazy-initialization à ʻapplication.yml`.

spring:
  main:
    banner-mode: log
    lazy-initialization: true

Ainsi, le processus d'instanciation de la source de données est le suivant.

@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("L'initialisation des informations de connexion à la base de données n'est pas terminée.");
        }

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

}

De plus, dans la classe ʻexamples.cli.MainRunner qui effectue le traitement initial, l'initialisation différée est désactivée en ajoutant @Lazy (false) . (Cela peut ne pas avoir de sens d'ajouter @Lazy (false)` car il sera appelé immédiatement de toute façon)

Classe d'accès à la base de données

La classe ʻExamples.cli.MainRunner` est exécutée avant l'analyse des paramètres d'entrée, donc si vous DI une classe qui accède normalement à DB, une erreur se produira au démarrage.

Par conséquent, l'acquisition de la classe qui accède à la base de données est implémentée de sorte qu'elle soit acquise directement à partir de ApplicationContext.

//Exécutez le service
MainService service = context.getBean(MainService.class);
long count = service.execute(paramInfo);

En mettant en œuvre de cette manière, le processus d'initialisation de la source de données peut être effectué après l'analyse des paramètres de commande.

Les classes qui effectuent l'accès à la base de données sont les suivantes.

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

}

Méthode d'implémentation sans initialisation paresseuse

Si l'initialisation différée ne peut pas être utilisée pour une raison quelconque, elle peut être réalisée en utilisant ʻorg.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource`, qui peut changer dynamiquement les sources de données.

Supprimez le paramètre de spring.main.lazy-initialization et implémentez le processus d'initialisation de la source de données comme suit.

@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();
        }
    }

}

Un mécanisme dans lequel une source de données vide est définie dans le processus d'initialisation au démarrage, et la source de données est commutée lorsque la méthode ʻinitDataSource` est appelée après l'analyse des paramètres de commande.

Il existe peut-être un meilleur moyen, mais c'est la limite de ce que vous pouvez découvrir.

@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })

La source

La source implémentée est la suivante.

cli-examples

référence

Les sites auxquels il est fait référence cette fois sont les suivants.

en conclusion

Le premier article était Spring Boot, ce qui est très pratique. Je pense que je vais publier quelque chose comme ça au lieu d'un mémo.

Recommended Posts

Application Spring Boot qui spécifie les paramètres de connexion à la base de données avec des paramètres
Pool de connexion de base de données Spring Boot
Créer une application d'enquête avec Spring Boot
Traitement lors du démarrage d'une application avec Spring Boot
Démarrez le développement d'applications Web avec Spring Boot
Lancez l'application Nginx + Spring Boot avec docker-compose
Exécutez l'application WEB avec Spring Boot + Thymeleaf
Développement d'applications Web Spring Boot2 avec connexion Visual Studio Code SQL Server
Configurer l'application Spring Boot avec le module multiple maven
Disponibilité de l'application Spring Boot 2.3
Télécharger avec Spring Boot
Paramètres de connexion à MySQL avec Spring Boot + Spring JDBC
Essayez d'utiliser OpenID Connect avec Keycloak (application Spring Boot)
Spring Boot avec les paramètres du filtre de sécurité Spring et les points addictifs
Générer un code à barres avec Spring Boot
Implémenter GraphQL avec Spring Boot
Essayez la connexion DB avec Java
Démarrez avec Spring Boot
Implémenter l'API REST avec Spring Boot et JPA (Application Layer)
Paramètres de connexion à la base de données Spring-Boot application.properties
Bonjour tout le monde avec Spring Boot!
[Spring Boot] Création d'applications Web
Exécutez LIFF avec Spring Boot
Connexion SNS avec Spring Boot
Paramètres d'échange à chaud Spring Boot
Téléchargement de fichiers avec Spring Boot
Spring Boot commençant par copie
Exemple d'application Web qui gère plusieurs bases de données avec Spring Boot 1.5
Application Java CICS-Run - (4) Application Spring Boot
Spring Boot à partir de Docker
Conseils relatifs à Spring Boot DB
Définir des cookies avec Spring Boot
Utiliser Spring JDBC avec Spring Boot
Ajouter un module avec Spring Boot
Premiers pas avec Spring Boot
Paramètres liés aux performances de Spring Boot
Créer un micro service avec Spring Boot
Envoyer du courrier avec Spring Boot
Introduction de la bibliothèque ff4j qui réalise le basculement de fonctionnalités avec Spring Boot
Créons une application Web de gestion de livres avec Spring Boot part1
Créons une application Web de gestion de livres avec Spring Boot part3
Créons une application Web de gestion de livres avec Spring Boot part2
[Débutant] Essayez d'écrire l'API REST pour l'application Todo avec Spring Boot
Utiliser l'authentification de base avec Spring Boot
Développement d'applications Spring Boot dans Eclipse
Points de révision du code de l'application Spring Boot
gRPC sur Spring Boot avec grpc-spring-boot-starter
Créez une application avec Spring Boot 2
Déploiement à chaud avec le développement Spring Boot
Liaison de base de données avec doma2 (Spring boot)
Programmation Spring Boot avec VS Code
Jusqu'à "Hello World" avec Spring Boot
Obtenez des résultats de validation avec Spring Boot
(Intellij) Hello World avec Spring Boot
Créez une application avec Spring Boot
Google Cloud Platform avec Spring Boot 2.0.0
Implémenter l'application Spring Boot dans Gradle
J'ai essayé GraphQL avec Spring Boot
[Java] Intégration LINE avec Spring Boot