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.
ʻ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.
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)
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;
}
}
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 implémentée est la suivante.
Les sites auxquels il est fait référence cette fois sont les suivants.
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