web-dev-qa-db-fra.com

Accéder au fichier de propriétés par programme avec Spring?

Nous utilisons le code ci-dessous pour injecter les propriétés d'un fichier de propriétés dans les beans Spring.

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations" value="classpath:/my.properties"/>
</bean>

<bean id="blah" class="abc">
    <property name="path" value="${the.path}"/>
</bean>

Existe-t-il un moyen d'accéder aux propriétés par programme? J'essaie de faire du code sans injection de dépendance. Donc j'aimerais avoir un code comme celui-ci:

PropertyPlaceholderConfigurer props = new PropertyPlaceholderConfigurer();
props.load("classpath:/my.properties");
props.get("path");
126
Marcus Leon

Que diriez-vous PropertiesLoaderUtils ?

Resource resource = new ClassPathResource("/my.properties");
Properties props = PropertiesLoaderUtils.loadProperties(resource);
156
skaffman

CREDIT: Accès par programme aux propriétés de Spring sans relire le fichier de propriétés

J'ai trouvé une implémentation de Nice permettant d'accéder aux propriétés par programme au printemps sans recharger les propriétés déjà chargées par spring. [De plus, il n'est pas nécessaire de coder en dur l'emplacement du fichier de propriétés dans la source]

Avec ces modifications, le code semble plus propre et plus facile à gérer.

Le concept est assez simple. Il suffit d'étendre l'espace réservé de propriété par défaut du printemps (PropertyPlaceholderConfigurer) et de capturer les propriétés qu'il charge dans la variable locale

public class SpringPropertiesUtil extends PropertyPlaceholderConfigurer {

    private static Map<String, String> propertiesMap;
    // Default as in PropertyPlaceholderConfigurer
    private int springSystemPropertiesMode = SYSTEM_PROPERTIES_MODE_FALLBACK;

    @Override
    public void setSystemPropertiesMode(int systemPropertiesMode) {
        super.setSystemPropertiesMode(systemPropertiesMode);
        springSystemPropertiesMode = systemPropertiesMode;
    }

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {
        super.processProperties(beanFactory, props);

        propertiesMap = new HashMap<String, String>();
        for (Object key : props.keySet()) {
            String keyStr = key.toString();
            String valueStr = resolvePlaceholder(keyStr, props, springSystemPropertiesMode);
            propertiesMap.put(keyStr, valueStr);
        }
    }

    public static String getProperty(String name) {
        return propertiesMap.get(name).toString();
    }

}

Exemple d'utilisation

SpringPropertiesUtil.getProperty("myProperty")

Changements de configuration de printemps

<bean id="placeholderConfigMM" class="SpringPropertiesUtil">
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
    <property name="locations">
    <list>
        <value>classpath:myproperties.properties</value>
    </list>
    </property>
</bean>

J'espère que cela aide à résoudre les problèmes que vous avez

49
Ashok Koyi

Si tout ce que vous voulez faire, c'est accéder à la valeur d'espace réservé à partir du code, il existe l'annotation @Value:

@Value("${settings.some.property}")
String someValue;

Pour accéder aux espaces réservés à partir de SPEL, utilisez cette syntaxe:

#('${settings.some.property}')

Pour exposer la configuration aux vues dont SPEL est désactivé, vous pouvez utiliser cette astuce:

package com.my.app;

import Java.util.Collection;
import Java.util.Map;
import Java.util.Set;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.stereotype.Component;

@Component
public class PropertyPlaceholderExposer implements Map<String, String>, BeanFactoryAware {  
    ConfigurableBeanFactory beanFactory; 

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = (ConfigurableBeanFactory) beanFactory;
    }

    protected String resolveProperty(String name) {
        String rv = beanFactory.resolveEmbeddedValue("${" + name + "}");

        return rv;
    }

    @Override
    public String get(Object key) {
        return resolveProperty(key.toString());
    }

    @Override
    public boolean containsKey(Object key) {
        try {
            resolveProperty(key.toString());
            return true;
        }
        catch(Exception e) {
            return false;
        }
    }

    @Override public boolean isEmpty() { return false; }
    @Override public Set<String> keySet() { throw new UnsupportedOperationException(); }
    @Override public Set<Java.util.Map.Entry<String, String>> entrySet() { throw new UnsupportedOperationException(); }
    @Override public Collection<String> values() { throw new UnsupportedOperationException(); }
    @Override public int size() { throw new UnsupportedOperationException(); }
    @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException(); }
    @Override public void clear() { throw new UnsupportedOperationException(); }
    @Override public String put(String key, String value) { throw new UnsupportedOperationException(); }
    @Override public String remove(Object key) { throw new UnsupportedOperationException(); }
    @Override public void putAll(Map<? extends String, ? extends String> t) { throw new UnsupportedOperationException(); }
}

Et utilisez ensuite l'exposant pour exposer les propriétés à une vue:

<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" id="tilesViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
    <property name="attributesMap">
        <map>
            <entry key="config">
                <bean class="com.my.app.PropertyPlaceholderExposer" />
            </entry>
        </map>
    </property>
</bean>

Ensuite, utilisez les propriétés exposées comme ceci:

${config['settings.some.property']}

Cette solution présente l’avantage de pouvoir compter sur un espace réservé standard Implémentation injectée par la balise context: property-placeholder.

Pour terminer, si vous avez vraiment besoin de capturer toutes les propriétés d’espace réservé et leurs valeurs, vous devez les rediriger vers StringValueResolver pour vous assurer que les espaces réservés fonctionnent correctement dans les valeurs de propriété. Le code suivant le fera.

package com.my.app;

import Java.util.Collection;
import Java.util.HashMap;
import Java.util.Map;
import Java.util.Properties;
import Java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.util.StringValueResolver;

public class AppConfig extends PropertyPlaceholderConfigurer implements Map<String, String> {

    Map<String, String> props = new HashMap<String, String>();

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
            throws BeansException {

        this.props.clear();
        for (Entry<Object, Object> e: props.entrySet())
            this.props.put(e.getKey().toString(), e.getValue().toString());

        super.processProperties(beanFactory, props);
    }

    @Override
    protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
            StringValueResolver valueResolver) {

        super.doProcessProperties(beanFactoryToProcess, valueResolver);

        for(Entry<String, String> e: props.entrySet())
            e.setValue(valueResolver.resolveStringValue(e.getValue()));
    }

    // Implement map interface to access stored properties
    @Override public Set<String> keySet() { return props.keySet(); }
    @Override public Set<Java.util.Map.Entry<String, String>> entrySet() { return props.entrySet(); }
    @Override public Collection<String> values() { return props.values(); }
    @Override public int size() { return props.size(); }
    @Override public boolean isEmpty() { return props.isEmpty(); }
    @Override public boolean containsValue(Object value) { return props.containsValue(value); }
    @Override public boolean containsKey(Object key) { return props.containsKey(key); }
    @Override public String get(Object key) { return props.get(key); }
    @Override public void clear() { throw new UnsupportedOperationException(); }
    @Override public String put(String key, String value) { throw new UnsupportedOperationException(); }
    @Override public String remove(Object key) { throw new UnsupportedOperationException(); }
    @Override public void putAll(Map<? extends String, ? extends String> t) { throw new UnsupportedOperationException(); }
}
49
anttix

J'ai fait cela et cela a fonctionné.

Properties props = PropertiesLoaderUtils.loadAllProperties("my.properties");
PropertyPlaceholderConfigurer props2 = new PropertyPlaceholderConfigurer();
props2.setProperties(props);

Cela devrait fonctionner.

44
Zoidberg

Vous pouvez également utiliser les utilitaires de ressort ou les propriétés de chargement via le PropertiesFactoryBean.

<util:properties id="myProps" location="classpath:com/foo/myprops.properties"/>

ou:

<bean id="myProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  <property name="location" value="classpath:com/foo/myprops.properties"/>
</bean>

Ensuite, vous pouvez les récupérer dans votre application avec:

@Resource(name = "myProps")
private Properties myProps;

et utilisez en plus ces propriétés dans votre configuration:

<context:property-placeholder properties-ref="myProps"/>

Cela se trouve également dans les documents: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xsd-config-body-schemas-util-properties

24
enkor

Créez une classe comme ci-dessous

    package com.tmghealth.common.util;

    import Java.util.Properties;

    import org.springframework.beans.BeansException;

    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

    import org.springframework.context.annotation.Configuration;

    import org.springframework.context.annotation.PropertySource;

    import org.springframework.stereotype.Component;


    @Component
    @Configuration
    @PropertySource(value = { "classpath:/spring/server-urls.properties" })
    public class PropertiesReader extends PropertyPlaceholderConfigurer {

        @Override
        protected void processProperties(
                ConfigurableListableBeanFactory beanFactory, Properties props)
                throws BeansException {
            super.processProperties(beanFactory, props);

        }

    }

Ensuite, partout où vous souhaitez accéder à une utilisation de la propriété 

    @Autowired
        private Environment environment;
    and getters and setters then access using 

    environment.getProperty(envName
                    + ".letter.fdi.letterdetails.restServiceUrl");

- écrire des getters et des setters dans la classe d'accesseurs

    public Environment getEnvironment() {
            return environment;
        }`enter code here`

        public void setEnvironment(Environment environment) {
            this.environment = environment;
        }
9
user1419261

Cela m'aide:

ApplicationContextUtils.getApplicationContext().getEnvironment()
2
Ruzal Yumaev

Voici un autre échantillon.

XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
cfg.postProcessBeanFactory(factory);
2
Venky

Cela résoudra toutes les propriétés imbriquées.

public class Environment extends PropertyPlaceholderConfigurer {

/**
 * Map that hold all the properties.
 */
private Map<String, String> propertiesMap; 

/**
 * Iterate through all the Property keys and build a Map, resolve all the nested values before building the map.
 */
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {
    super.processProperties(beanFactory, props);

    propertiesMap = new HashMap<String, String>();
    for (Object key : props.keySet()) {
        String keyStr = key.toString();
        String valueStr = beanFactory.resolveEmbeddedValue(placeholderPrefix + keyStr.trim() + DEFAULT_PLACEHOLDER_SUFFIX);
        propertiesMap.put(keyStr, valueStr);
    }
} 

/**
 * This method gets the String value for a given String key for the property files.
 * 
 * @param name - Key for which the value needs to be retrieved.
 * @return Value
 */
public String getProperty(String name) {
    return propertiesMap.get(name).toString();
}
2
Sohan

Comme vous le savez, les nouvelles versions de Spring n'utilisent pas PropertyPlaceholderConfigurer, mais une autre construction cauchemardesque appelée PropertySourcesPlaceholderConfigurer. Si vous essayez de récupérer les propriétés résolues à partir du code et souhaitez que l'équipe de Spring nous donne le moyen de le faire il y a longtemps, votez pour cet article! ... Parce que c'est comme ça que vous le faites de la nouvelle façon:

Sous-classe PropertySourcesPlaceholderConfigurer:

public class SpringPropertyExposer extends PropertySourcesPlaceholderConfigurer {

    private ConfigurableListableBeanFactory factory;

    /**
     * Save off the bean factory so we can use it later to resolve properties
     */
    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
            final ConfigurablePropertyResolver propertyResolver) throws BeansException {
        super.processProperties(beanFactoryToProcess, propertyResolver);

        if (beanFactoryToProcess.hasEmbeddedValueResolver()) {
            logger.debug("Value resolver exists.");
            factory = beanFactoryToProcess;
        }
        else {
            logger.error("No existing embedded value resolver.");
        }
    }

    public String getProperty(String name) {
        Object propertyValue = factory.resolveEmbeddedValue(this.placeholderPrefix + name + this.placeholderSuffix);
        return propertyValue.toString();
    }
}

Pour l'utiliser, veillez à utiliser votre sous-classe dans votre @Configuration et enregistrez une référence à celle-ci pour une utilisation ultérieure.

@Configuration
@ComponentScan
public class PropertiesConfig {

    public static SpringPropertyExposer commonEnvConfig;

    @Bean(name="commonConfig")
    public static PropertySourcesPlaceholderConfigurer commonConfig() throws IOException {
        commonEnvConfig = new SpringPropertyExposer(); //This is a subclass of the return type.
        PropertiesFactoryBean commonConfig = new PropertiesFactoryBean();
        commonConfig.setLocation(new ClassPathResource("META-INF/spring/config.properties"));
        try {
            commonConfig.afterPropertiesSet();
        }
        catch (IOException e) {
            e.printStackTrace();
            throw e;
        }
        commonEnvConfig.setProperties(commonConfig.getObject());
        return commonEnvConfig;
    }
}

Usage:

Object value = PropertiesConfig.commonEnvConfig.getProperty("key.subkey");
2
TheJeff

Cet article explique également comment accéder aux propriétés: http://maciej-miklas.blogspot.de/2013/07/spring-31-programmatic-access-to.html

Vous pouvez accéder aux propriétés chargées par un paramètre de substitution de propriété de printemps sur un haricot de printemps:

@Named
public class PropertiesAccessor {

    private final AbstractBeanFactory beanFactory;

    private final Map<String,String> cache = new ConcurrentHashMap<>();

    @Inject
    protected PropertiesAccessor(AbstractBeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    public  String getProperty(String key) {
        if(cache.containsKey(key)){
            return cache.get(key);
        }

        String foundProp = null;
        try {
            foundProp = beanFactory.resolveEmbeddedValue("${" + key.trim() + "}");
            cache.put(key,foundProp);
        } catch (IllegalArgumentException ex) {
           // ok - property was not found
        }

        return foundProp;
    }
}
1
Maciej Miklas

Il suffit d’injecter Environment et d’appeler getProperty.

@Autowired
private Environment env;

void foo() {
    env.getProperty("your.property");
}
1
Ahmed Rezk

Veuillez utiliser le code ci-dessous dans votre fichier de configuration de ressort pour charger le fichier à partir du chemin d'accès aux classes de votre application.

 <context:property-placeholder
    ignore-unresolvable="true" ignore-resource-not-found="false" location="classpath:property-file-name" />
0
Abhishek Jha

C’est la meilleure façon dont je l’ai obtenu:

package your.package;

import Java.io.IOException;
import Java.util.Properties;
import Java.util.logging.Level;
import Java.util.logging.Logger;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;

public class ApplicationProperties {

    private Properties properties;

    public ApplicationProperties() {
        // application.properties located at src/main/resource
        Resource resource = new ClassPathResource("/application.properties");
        try {
            this.properties = PropertiesLoaderUtils.loadProperties(resource);
        } catch (IOException ex) {
            Logger.getLogger(ApplicationProperties.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public String getProperty(String propertyName) {
        return this.properties.getProperty(propertyName);
    }
}
0
Daniel Almeida

Vous pouvez obtenir vos propriétés via la classe Environment. En tant que documentation:

Les propriétés jouent un rôle important dans presque toutes les applications et peuvent provenir de diverses sources: fichiers de propriétés, propriétés système JVM, variables d'environnement système, JNDI, paramètres de contexte de servlet, objets de propriétés ad-hoc, cartes, etc. Le rôle de l’environnement en relation avec les propriétés est de fournir à l’utilisateur une interface de service pratique pour la configuration des sources de propriétés et la résolution de celles-ci.

Ayant Environment comme variable env, appelez simplement: 

env.resolvePlaceholders("${your-property:default-value}")

Vous pouvez obtenir vos propriétés "brutes" via: 

env.getProperty("your-property")

Il effectuera une recherche dans toutes les propriétés source enregistrées par spring.

Vous pouvez soit obtenir l'environnement via: 

  • injecter ApplicationContext en implémentant ApplicationContextAware puis appeler getEnvironment() sur le contexte 
  • implémenter EnvironmentAware.

Elle est obtenue via l'implémentation d'une classe car les propriétés sont résolues au tout début du démarrage de l'application, car elles peuvent être requises pour la construction de beans. 

En savoir plus sur la documentation: Spring Environment Documentation

0
Augustin Ghauratto
create .properties file in classpath of your project and add path configuration in xml`<context:property-placeholder location="classpath*:/*.properties" />`

dans servlet-context.xml après cela, vous pouvez directement utiliser votre fichier partout

0
Aniket