2017-03-10 2 views
0

Nous devons charger plusieurs fichiers de propriétés ensemble et les utiliser comme une source de propriétés. <util:properties> vous permet de passer une liste de fichiers séparés par des virgules et tout fonctionne bien jusqu'à présent. Donc, ce qui suit est bon:Problème lors du chargement de plusieurs fichiers de propriétés avec Spring <util: properties /> lorsque la liste de fichiers est un paramètre

<util:properties loaction="conf/file1.properties,conf/file2.properties,abc-*.properties" /> 

Cependant, dans notre cas, la liste des fichiers de propriétés est pas fixe et il vient d'une autre propriétés de maître fichier qui est chargé avant. Nous voulons passer cette liste à <util:properties> en tant que paramètre, mais cela ne fonctionne pas.

<util:properties location="${allPropertiesFiles}" /> 

${allPropertiesFiles} est défini comme

allPropertiesFiles=conf/file1.properties,conf/file2.properties,abc-*.properties 

Cela échoue à cause de virgules dans la liste des fichiers. Il les traite comme un nom de fichier unique et lève FileNotFoundException.

Je me demande à quel moment Spring tente de diviser les fichiers par des virgules et il semble que cela se produise avant de résoudre $ {allPropertiesFiles}. Par exemple, si je fais comme ci-dessous, cela fonctionne bien, mais ce n'est pas une solution pratique pour nous car nous ne savons pas combien de fichiers sont inclus dans cette liste.

<util:properties location="${propFile.location1},${propFile.location2},${propFile.location3}" /> 

MISE À JOUR:

Il semble être un problème de printemps avec le traitement et le fractionnement avec « » avant la résolution de la valeur de la propriété dans ${...}. J'ai même essayé d'utiliser Spring EL pour le diviser mais il échoue à nouveau en analysant le EL valide, car il le casse d'abord en fonction de ',' puis évalue l'expression. L'exemple ci-dessous échoue avec l'exception EL parse:

<util:properties location="#{'${allPropertiesFiles}'.split(',')}" /> 

FYI cette observation est avec Spring 4.2.x. Toute suggestion est très appréciée.

Répondre

0

Alors, j'ai trouvé une solution/solution à ma question et je voudrais partager ici.

Les parseurs de fèves de util:properties et context:property-placeholder diviser la valeur de chaîne donnée pour location propriété par ,. Cela arrive bien avant que la résolution de propriété se produise.Par conséquent, si vous voulez passer une liste de fichiers de propriétés séparés par des virgules à ces beans, cela ne fonctionnera pas. Donc, au lieu d'utiliser <util:properties>, j'ai décidé d'utiliser directement PropertiesFactoryBean et de définir l'emplacement en tant que paramètre. Cela corrige la façon dont la définition du bean est construite au printemps, car elle utilise l'analyseur de beans Spring par défaut. Puis j'ai fourni une version personnalisée de Spring ResourceArrayPropertyEditor qui convertit un String en Resource[]. L'éditeur de propriétés gère les chaînes séparées par des virgules lors de la conversion en Resource[].

Voici mon xml contexte maintenant:

<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> 
     <property name="customEditors"> 
      <map> 
       <entry key="org.springframework.core.io.Resource[]" value="com.mycompany.CustomResourceArrayPropertyEditor"/> 
      </map> 
     </property> 
    </bean> 
    <bean id="allPropertiesFromFiles" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> 
      <property name="locations" value="${propertiesFile.locations}" /> 
    </bean> 

Et voici mon habitude PropertyEditor:

public class CustomResourceArrayPropertyEditor extends ResourceArrayPropertyEditor 
{ 
    private final ResourcePatternResolver resourcePatternResolver; 

    public CustomResourceArrayPropertyEditor() 
    { 
    this(new PathMatchingResourcePatternResolver()); 
    } 

    public CustomResourceArrayPropertyEditor(ResourcePatternResolver resourcePatternResolver) 
    { 
    super(resourcePatternResolver, null); 
    this.resourcePatternResolver = resourcePatternResolver; 
    } 

    @Override 
    public void setAsText(String text) 
    { 
    String pattern = resolvePath(text).trim(); 
    String[] resourceNames = StringUtils.commaDelimitedListToStringArray(pattern); 
    List<Resource> resourceList = new ArrayList<Resource>(); 
    try { 
     for (String resourceName: resourceNames) 
     { 
     Resource[] resources = resourcePatternResolver.getResources(resourceName); 
     for (Resource res: resources) 
      resourceList.add(res); 
     } 
    } 
    catch (IOException ex) { 
     throw new IllegalArgumentException("Could not resolve resource location pattern [" + pattern + "]", ex); 
    } 

    setValue(resourceList.toArray(new Resource[0])); 
    } 
} 

L'autre solution que je pouvais penser était de créer un BeanFactoryPostProcessor pour visiter les haricots et la mise à jour définitions de bean de util:properties et context:propery-placeholder pour simplement utiliser TypedStringValue pour la propriété locations par opposition à String[].

Espérons que ça aide.

0

Avez-vous essayé d'entourer votre valeur de variable par des guillemets doubles? Dans un petit test, cela a fonctionné comme un charme:

ApplicationContext:

<bean id="test" class="de.de.proptest.Test"> 
    <property name="p" ref="props" /> 
</bean> 
<util:properties location="${props}" id="props" /> 

J'ai des fichiers 2 propriétés, a.properties avec le contenu:

a=1 

et b.properties avec le contenu :

b=2 

Avec l'argument JVM

-Dprops="file:/home/dominik/sandbox/proptest/a.properties, file:/home/dominik/sandbox/proptest/b.properties" 

-je obtenir la sortie suivante (coupe aux points intéressants):

Mar 11, 2017 1:32:11 PM org.springframework.beans.factory.config.PropertiesFactoryBean loadProperties 
INFO: Loading properties file from URL [file:/home/dominik/sandbox/proptest/a.properties] 
Mar 11, 2017 1:32:11 PM org.springframework.beans.factory.config.PropertiesFactoryBean loadProperties 
INFO: Loading properties file from URL [file:/home/dominik/sandbox/proptest/b.properties] 
Test [p={b=2, a=1}] 
+0

Vous aviez besoin de guillemets doubles car vous transmettiez la liste des fichiers de propriétés en argument jvm et il y a un espace après la virgule dans votre liste. Ma liste provient d'un autre fichier de propriétés et si je l'entoure de "" cela devient une partie de la valeur de la propriété. – user3739116

+0

Deuxièmement, j'ai essayé votre exemple et cela ne fonctionne que pour moi si la liste est passée en argument jvm avec Spring 4.3.x. Les versions antérieures de Spring (par exemple, 4.2.x) échouent toujours en raison de la virgule dans la liste. Nous sommes sur Spring 4.2.x maintenant et nous ne pouvons pas mettre à jour pour le moment. Troisièmement, votre exemple échoue lorsque j'ai essayé de passer la liste d'un fichier de propriétés qui est chargé par ''. On dirait que Spring 4.3.x gère mieux jvm arg, je ne sais pas pourquoi. S'il vous plaît laissez-moi savoir si j'ai tort. – user3739116