Lors de la gestion des valeurs de réglage dans Spring Framework, les valeurs de réglage peuvent être spécifiées dans les fichiers de propriétés, les propriétés système (valeurs spécifiées par -D), les variables d'environnement du système d'exploitation, JNDI (environnement d'application Web uniquement), etc. Il peut être obtenu via @ Value
ou ʻEnvironment`.
Par exemple, cela ressemble à ce qui suit.
Exemple de spécification de valeur de réglage(fichier de propriétés)
services.user.url=http://user.service.com/{id}
services.company.url=http://company.service.com/{id}
Exemple de référence de valeur de réglage
@Service
public class MyService {
private final RestTemplate restTemplate = new RestTemplate();
private final Environment environment;
@Value("${services.user.url}") //Injectez la valeur de réglage lors de la génération du bean
private String userServiceUrl;
public MyService(Environment environment) {
this.environment = environment;
}
public User getUser(String id) {
User user = restTemplate.getForObject(userServiceUrl, User.class, id);
return user;
}
public Company getCompany(String id) {
String companyServiceUrl = environment.getProperty("services.company.url"); //Obtenir la valeur définie lors de l'exécution
Company company = restTemplate.getForObject(companyServiceUrl, User.class);
return company;
}
}
Dans Spring Boot, au lieu de "@ Value", "[Propriétés de configuration de type sécurisé](https://docs.spring.io/spring-boot/docs/2.1.7.RELEASE/reference/htmlsingle/#" Je pense qu'il est courant d'utiliser "boot-features-external-config-typesafe-configuration-properties)", mais ici ** intentionnellement ** "
@ Value` "est utilisé comme espace réservé de propriété (" Spécifie d'utiliser «$ {...}»). (Bien que je ne l'explique pas, la méthode présentée ici est également applicable aux "Propriétés de configuration de type sécurisé")
Spring Framwork (malheureusement?) Ne fournit pas de classe pour obtenir les paramètres de la base de données, mais la destination de sauvegarde des paramètres est abstraite par une classe appelée PropertySource
, donc les paramètres de la base de données. Si vous créez une PropertySource
et que vous l'appliquez à ʻEnvironment`, vous pouvez y faire référence depuis votre application.
PropertySource
pour obtenir les paramètres de la base de donnéesEssayez de créer une classe qui obtient la valeur de paramètre de la base de données au démarrage, la met en cache et met à jour le cache à tout moment (bien que la sécurité des threads semble suspecte ...).
package com.example.demo;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.env.EnumerablePropertySource;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class JdbcPropertySource extends EnumerablePropertySource<DataSource> implements InitializingBean {
private final JdbcTemplate jdbcTemplate;
private final String[] tableNames;
private Map<String, Object> properties = Collections.emptyMap();
public JdbcPropertySource(String name, DataSource dataSource, String... tableNames) {
super(name, dataSource);
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.tableNames = tableNames.length == 0 ? new String[]{"t_properties"} : tableNames;
}
@Override
public String[] getPropertyNames() {
return properties.keySet().toArray(new String[0]);
}
@Override
public Object getProperty(String name) {
Map<String, Object> currentProperties = properties;
return currentProperties.get(name);
}
@Override
public void afterPropertiesSet() {
load();
}
public void load() {
Map<String, Object> loadedProperties = Stream.of(tableNames)
.flatMap(tableName -> jdbcTemplate.queryForList("SELECT name, value FROM " + tableName).stream())
.collect(Collectors.toMap(e -> (String) e.get("name"), e -> e.get("value")));
this.properties = loadedProperties;
}
}
package com.example.actuatordemo;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
@Configuration
public class MyConfiguration {
//Paramètres DataSource
@Bean
DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.setName("demo")
.addScript("classpath:init-db.sql")
.build();
}
//Paramètre de JdbcPropertySource créé cette fois
@Bean
JdbcPropertySource jdbcPropertySource(DataSource dataSource) {
return new JdbcPropertySource("jdbcProperties", dataSource);
}
//Définition de bean pour appliquer le JdbcPropertySource créé cette fois à l'environnement
@Bean
static BeanFactoryPostProcessor environmentPropertySourcesCustomizer() {
return bf -> {
ConfigurableEnvironment environment = bf.getBean(ConfigurableEnvironment.class);
JdbcPropertySource propertySource = bf.getBean(JdbcPropertySource.class);
//Appliquer selon la priorité suivante des variables d'environnement du système d'exploitation (la priorité est déterminée en fonction des exigences)
environment.getPropertySources()
.addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, propertySource);
};
}
//Définition de bean pour activer les espaces réservés de propriété
@Bean
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Cette fois, je l'ai appliqué à ʻEnvironment en utilisant le mécanisme de
BeanFactoryPostProcessor`. Est-ce la meilleure méthode? N'est pas très confiant. Je vous serais reconnaissant si vous pouviez dire s'il y a une meilleure façon.
Étant donné que cette entrée utilise une base de données intégrée, préparez une table et SQL pour saisir les données.
src/main/resources/init-db.sql
drop table t_properties if exists;
create table t_properties (
name varchar(512) not null primary key,
value text
);
insert into t_properties (name, value) values ('services.user.url','http://dev01/services/user/{id}');
insert into t_properties (name, value) values ('services.company.url','http://dev01/services/company/{id}');
Dans le cas où je suis actuellement impliqué (cas non-Spring Boot ...), il peut être nécessaire (éventuellement) d'avoir des valeurs de réglage dans la base de données (du point de vue du fonctionnement du système), alors que puis-je faire techniquement? J'y ai pensé et en ai fait un prototype. Il semble y avoir une marge d'amélioration telle que la garantie de la sécurité des threads, mais je suis soulagé de savoir que cela peut être réalisé en utilisant les points d'extension de Spring Framework.
Recommended Posts