working propertysourcesplaceholderconfigurer propertysource not leer example application java spring properties-file spring-el

java - not - propertysourcesplaceholderconfigurer



Cómo rellenar HashMap desde el archivo de propiedades de Java con Spring @Value (4)

¿Es posible usar Spring @Value para mapear valores del archivo de propiedades al HashMap?

Sí lo es. Con un poco de ayuda de código y Spel .

En primer lugar, considere este singleton Spring-bean (debe escanearlo):

@Component("PropertySplitter") public class PropertySplitter { /** * Example: one.example.property = KEY1:VALUE1,KEY2:VALUE2 */ public Map<String, String> map(String property) { return this.map(property, ","); } /** * Example: one.example.property = KEY1:VALUE1.1,VALUE1.2;KEY2:VALUE2.1,VALUE2.2 */ public Map<String, List<String>> mapOfList(String property) { Map<String, String> map = this.map(property, ";"); Map<String, List<String>> mapOfList = new HashMap<>(); for (Entry<String, String> entry : map.entrySet()) { mapOfList.put(entry.getKey(), this.list(entry.getValue())); } return mapOfList; } /** * Example: one.example.property = VALUE1,VALUE2,VALUE3,VALUE4 */ public List<String> list(String property) { return this.list(property, ","); } /** * Example: one.example.property = VALUE1.1,VALUE1.2;VALUE2.1,VALUE2.2 */ public List<List<String>> groupedList(String property) { List<String> unGroupedList = this.list(property, ";"); List<List<String>> groupedList = new ArrayList<>(); for (String group : unGroupedList) { groupedList.add(this.list(group)); } return groupedList; } private List<String> list(String property, String splitter) { return Splitter.on(splitter).omitEmptyStrings().trimResults().splitToList(property); } private Map<String, String> map(String property, String splitter) { return Splitter.on(splitter).omitEmptyStrings().trimResults().withKeyValueSeparator(":").split(property); } }

Nota: PropertySplitter clase PropertySplitter usa la utilidad Splitter de Guava. Por favor, consulte su documentación para más detalles.

Entonces, en un frijol tuyo:

@Component public class MyBean { @Value("#{PropertySplitter.map(''${service.expiration}'')}") Map<String, String> propertyAsMap; }

Y finalmente, la propiedad:

service.expiration = name1:100,name2:20

No es exactamente lo que ha preguntado, porque este PropertySplitter funciona con una sola propiedad que se transforma en un Map , pero creo que podría cambiar a esta manera de especificar propiedades o modificar el código PropertySplitter para que coincida con el más jerárquico camino que deseas.

¿Es posible utilizar Spring @Value para mapear valores del archivo de propiedades al HashMap?

Actualmente tengo algo como esto, y mapear un valor no es un problema. Pero necesito asignar valores personalizados en expiraciones de HashMap. Es algo como esto posible?

@Service @PropertySource(value = "classpath:my_service.properties") public class SomeServiceImpl implements SomeService { @Value("#{conf[''service.cache'']}") private final boolean useCache = false; @Value("#{conf[''service.expiration.[<custom name>]'']}") private final HashMap<String, String> expirations = new HashMap<String, String>();

Archivo de propiedad: ''my_service.properties''

service.cache=true service.expiration.name1=100 service.expiration.name2=20

¿Es posible mapear como esta clave: conjunto de valores

  • name1 = 100

  • name2 = 20


Desde Spring 4.1.x (aunque no recuerdo la versión específica), puedes hacer algo como

@Value("#{${your.properties.key.name}}") private Map<String, String> myMap;

donde your.properties.key.name en su archivo de propiedades debería ser algo así como

your.properties.key.name={/ name1 : 100, / name2 : 200 / }

Solo asegúrese de crear el bean PropertySourcesPlaceholderConfigurer para que funcione tanto en su aplicación como si está escribiendo un código de prueba unitaria para probar el código; de lo contrario, $ {...} marcador de posición para el valor de la propiedad no funcionará como se espera y verás algunos errores SpringEL extraños.


Hago una solución inspirada en la publicación anterior.

Registrar el archivo de propiedad en la configuración de Spring:

<util:properties id="myProp" location="classpath:my.properties"/>

Y creo componentes:

@Component("PropertyMapper") public class PropertyMapper { @Autowired ApplicationContext applicationContext; public HashMap<String, Object> startWith(String qualifier, String startWith) { return startWith(qualifier, startWith, false); } public HashMap<String, Object> startWith(String qualifier, String startWith, boolean removeStartWith) { HashMap<String, Object> result = new HashMap<String, Object>(); Object obj = applicationContext.getBean(qualifier); if (obj instanceof Properties) { Properties mobileProperties = (Properties)obj; if (mobileProperties != null) { for (Entry<Object, Object> e : mobileProperties.entrySet()) { Object oKey = e.getKey(); if (oKey instanceof String) { String key = (String)oKey; if (((String) oKey).startsWith(startWith)) { if (removeStartWith) key = key.substring(startWith.length()); result.put(key, e.getValue()); } } } } } return result; } }

Y cuando quiero mapear todas las propiedades que comienzan con el valor de specifix en HashMap, con la anotación @Value:

@Service public class MyServiceImpl implements MyService { @Value("#{PropertyMapper.startWith(''myProp'', ''service.expiration.'', true)}") private HashMap<String, Object> portalExpirations;


La solución más rápida basada en Spring Boot que se me ocurre es la siguiente. En mi ejemplo particular estoy migrando datos de un sistema a otro. Es por eso que necesito un mapeo para un campo llamado prioridad .

Primero he creado el archivo de propiedades (priority-migration.properties) como este:

my.prefix.priority.0:0 my.prefix.priority.10:1 my.prefix.priority.15:2 my.prefix.priority.20:2 another.prefix.foo:bar

y ponerlo en el classpath.

Suponiendo que desea utilizar el mapa en un bean / componente manejado por resorte, anote su clase con:

@Component @PropertySource("classpath:/priority-migration.properties")

Lo que realmente quiere en su mapa es, por supuesto, solo los pares clave / valor que están prefijados con my.prefix, es decir, esta parte:

{ 0:0 10:1 15:2 20:2 }

Para lograr eso, debe anotar su componente con

@ConfigurationProperties("my.prefix")

y crea un getter para el infijo prioritario . Este último resultó ser obligatorio en mi caso (aunque el documento de Sring dice que es suficiente tener una prioridad de propiedad e inicializarlo con un valor variable)

private final Map<Integer, Integer> priorityMap = new HashMap<>(); public Map<Integer, Integer> getPriority() { return priorityMap; }

En el final

Se ve algo como esto:

@Component @ConfigurationProperties("my.prefix") @PropertySource("classpath:/priority-migration.properties") class PriorityProcessor { private final Map<Integer, Integer> priorityMap = new HashMap<>(); public Map<Integer, Integer> getPriority() { return priorityMap; } public void process() { Integer myPriority = priorityMap.get(10) // use it here } }